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.
This commit is contained in:
parent
5e13cf2543
commit
b2cc3f6fc2
2 changed files with 48 additions and 17 deletions
|
@ -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)
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue