This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] S/390: Dump unknown instructions according to their length.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b2cc3f6fc2c5abc0a5ac7e0f2b5fb2365e89d33f

commit b2cc3f6fc2c5abc0a5ac7e0f2b5fb2365e89d33f
Author: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
Date:   Fri Jun 10 13:40:48 2016 +0200

    S/390: Dump unknown instructions according to their length.
    
    Unknown instructions are currently just dumped as .long 1234.  On
    S/390 we can do a bit better since the instruction length is encoded
    in the opcode.  That way also unknown instructions can be skipped
    according to their real length.  That way we can continue correctly
    after that instruction.  However, there are also some drawbacks with
    that behavior when dumping data.  So for now that behavior is only
    enabled for text section but even there it might mess things up when
    having a literal pool embedded in the code.  Therefore I've left the
    feature disabled by default and have added the -Minsnlength option to
    enable it explicitely.
    
    opcodes/ChangeLog:
    
    2016-06-10  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
    
    	* s390-dis.c (option_use_insn_len_bits_p): New file scope
    	variable.
    	(init_disasm): Handle new command line option "insnlength".
    	(print_s390_disassembler_options): Mention new option in help
    	output.
    	(print_insn_s390): Use the encoded insn length when dumping
    	unknown instructions.

Diff:
---
 opcodes/ChangeLog  | 10 ++++++++++
 opcodes/s390-dis.c | 55 +++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index f218365..fbde3e1 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,13 @@
+2016-06-10  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+	* s390-dis.c (option_use_insn_len_bits_p): New file scope
+	variable.
+	(init_disasm): Handle new command line option "insnlength".
+	(print_s390_disassembler_options): Mention new option in help
+	output.
+	(print_insn_s390): Use the encoded insn length when dumping
+	unknown instructions.
+
 2016-06-03  Pitchumani Sivanupandi  <pitchumani.s@atmel.com>
 
 	* avr-dis.c (avr_operand): Add default data address space origin (0x800000)
diff --git a/opcodes/s390-dis.c b/opcodes/s390-dis.c
index eeaeaf8..8134073 100644
--- a/opcodes/s390-dis.c
+++ b/opcodes/s390-dis.c
@@ -29,6 +29,7 @@
 static int init_flag = 0;
 static int opc_index[256];
 static int current_arch_mask = 0;
+static int option_use_insn_len_bits_p = 0;
 
 /* Set up index table for first opcode byte.  */
 
@@ -51,6 +52,8 @@ init_disasm (struct disassemble_info *info)
 	current_arch_mask = 1 << S390_OPCODE_ESA;
       else if (CONST_STRNEQ (p, "zarch"))
 	current_arch_mask = 1 << S390_OPCODE_ZARCH;
+      else if (CONST_STRNEQ (p, "insnlength"))
+	option_use_insn_len_bits_p = 1;
       else
 	fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
 
@@ -261,7 +264,7 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
   bfd_byte buffer[6];
   const struct s390_opcode *opcode = NULL;
   unsigned int value;
-  int status, opsize, bufsize;
+  int status, opsize, bufsize, bytes_to_dump, i;
 
   if (init_flag == 0)
     init_disasm (info);
@@ -307,38 +310,54 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
 		  || opcode_mask_more_specific (op, opcode)))
 	    opcode = op;
 	}
-    }
 
-  if (opcode != NULL)
-    {
-      /* The instruction is valid.  Print it and return its size.  */
-      s390_print_insn_with_opcode (memaddr, info, buffer, opcode);
-      return opsize;
+      if (opcode != NULL)
+	{
+	  /* The instruction is valid.  Print it and return its size.  */
+	  s390_print_insn_with_opcode (memaddr, info, buffer, opcode);
+	  return opsize;
+	}
     }
 
+  /* For code sections it makes sense to skip unknown instructions
+     according to their length bits.  */
+  if (status == 0
+      && option_use_insn_len_bits_p
+      && info->section != NULL
+      && (info->section->flags & SEC_CODE))
+    bytes_to_dump = opsize;
+  else
+    /* By default unknown instructions are printed as .long's/.short'
+       depending on how many bytes are available.  */
+    bytes_to_dump = bufsize >= 4 ? 4 : bufsize;
+
+  if (bytes_to_dump == 0)
+    return 0;
+
   /* Fall back to hex print.  */
-  if (bufsize >= 4)
+  switch (bytes_to_dump)
     {
+    case 4:
       value = (unsigned int) buffer[0];
       value = (value << 8) + (unsigned int) buffer[1];
       value = (value << 8) + (unsigned int) buffer[2];
       value = (value << 8) + (unsigned int) buffer[3];
       info->fprintf_func (info->stream, ".long\t0x%08x", value);
       return 4;
-    }
-  else if (bufsize >= 2)
-    {
+    case 2:
       value = (unsigned int) buffer[0];
       value = (value << 8) + (unsigned int) buffer[1];
       info->fprintf_func (info->stream, ".short\t0x%04x", value);
       return 2;
+    default:
+      info->fprintf_func (info->stream, ".byte\t0x%02x",
+			  (unsigned int) buffer[0]);
+      for (i = 1; i < bytes_to_dump; i++)
+	info->fprintf_func (info->stream, ",0x%02x",
+			  (unsigned int) buffer[i]);
+      return bytes_to_dump;
     }
-  else
-    {
-      value = (unsigned int) buffer[0];
-      info->fprintf_func (info->stream, ".byte\t0x%02x", value);
-      return 1;
-    }
+  return 0;
 }
 
 void
@@ -350,4 +369,6 @@ with the -M switch (multiple options should be separated by commas):\n"));
 
   fprintf (stream, _("  esa         Disassemble in ESA architecture mode\n"));
   fprintf (stream, _("  zarch       Disassemble in z/Architecture mode\n"));
+  fprintf (stream, _("  insnlength  Print unknown instructions according "
+		     "to length from first two bits\n"));
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]