diff options
author | Thomas Troeger <tstroege@gmx.de> | 2020-01-13 12:36:55 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-01-13 12:36:55 +0000 |
commit | 1d67fe3b6e696fccb902d9919b9e58b7299a3205 (patch) | |
tree | 84e284092b19da0c349671ccc287d8afd7c1c4b6 /opcodes | |
parent | a4f2b7c5d931f2aa27851b59ae5817a6ee43cfcb (diff) | |
download | fsf-binutils-gdb-1d67fe3b6e696fccb902d9919b9e58b7299a3205.zip fsf-binutils-gdb-1d67fe3b6e696fccb902d9919b9e58b7299a3205.tar.gz fsf-binutils-gdb-1d67fe3b6e696fccb902d9919b9e58b7299a3205.tar.bz2 |
Add an option to objdump's disassembler to generate ascii art diagrams showing the destinations of flow control instructions.
binutils* objdump.c (visualize_jumps, color_output, extended_color_output)
(detected_jumps): New variables.
(usage): Add the new jump visualization options.
(option_values): Add new option value.
(long_options): Add the new option.
(jump_info_new, jump_info_free): New functions.
(jump_info_min_address, jump_info_max_address): Likewise.
(jump_info_end_address, jump_info_is_start_address): Likewise.
(jump_info_is_end_address, jump_info_size): Likewise.
(jump_info_unlink, jump_info_insert): Likewise.
(jump_info_add_front, jump_info_move_linked): Likewise.
(jump_info_intersect, jump_info_merge): Likewise.
(jump_info_sort, jump_info_visualize_address): Likewise.
(disassemble_jumps): New function - used to locate jumps.
(disassemble_bytes): Add ascii art generation.
(disassemble_section): Add scan to locate jumps.
(main): Parse the new visualization option.
* doc/binutils.texi: Document the new feature.
* NEWS: Mention the new feature.
opcodes * arm-dis.c (print_insn_arm): Fill in insn info fields for control
flow instructions.
(print_insn_thumb16, print_insn_thumb32): Likewise.
(print_insn): Initialize the insn info.
* i386-dis.c (print_insn): Initialize the insn info fields, and
detect jumps.
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/ChangeLog | 9 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 47 | ||||
-rw-r--r-- | opcodes/i386-dis.c | 61 |
3 files changed, 113 insertions, 4 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index bb235dc..8f3f944 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,12 @@ +2020-01-13 Thomas Troeger <tstroege@gmx.de> + + * arm-dis.c (print_insn_arm): Fill in insn info fields for control + flow instructions. + (print_insn_thumb16, print_insn_thumb32): Likewise. + (print_insn): Initialize the insn info. + * i386-dis.c (print_insn): Initialize the insn info fields, and + detect jumps. + 2012-01-13 Claudiu Zissulescu <claziss@gmail.com> * arc-opc.c (C_NE): Make it required. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 55ec321..b174f83 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -9886,7 +9886,13 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) case 'b': { bfd_vma disp = (((given & 0xffffff) ^ 0x800000) - 0x800000); - info->print_address_func (disp * 4 + pc + 8, info); + bfd_vma target = disp * 4 + pc + 8; + info->print_address_func (target, info); + + /* Fill in instruction information. */ + info->insn_info_valid = 1; + info->insn_type = dis_branch; + info->target = target; } break; @@ -10024,6 +10030,11 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) address += 2; info->print_address_func (address, info); + + /* Fill in instruction information. */ + info->insn_info_valid = 1; + info->insn_type = dis_branch; + info->target = address; } break; @@ -10388,6 +10399,11 @@ print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given) + ((given & 0x00f8) >> 2) + ((given & 0x0200) >> 3)); info->print_address_func (address, info); + + /* Fill in instruction information. */ + info->insn_info_valid = 1; + info->insn_type = dis_branch; + info->target = address; } break; @@ -10461,8 +10477,14 @@ print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given) case 'B': reg = ((reg ^ (1 << bitend)) - (1 << bitend)); - info->print_address_func (reg * 2 + pc + 4, info); + bfd_vma target = reg * 2 + pc + 4; + info->print_address_func (target, info); value_in_comment = 0; + + /* Fill in instruction information. */ + info->insn_info_valid = 1; + info->insn_type = dis_branch; + info->target = target; break; case 'c': @@ -11019,7 +11041,13 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) offset |= (given & 0x000007ff) << 1; offset -= (1 << 20); - info->print_address_func (pc + 4 + offset, info); + bfd_vma target = pc + 4 + offset; + info->print_address_func (target, info); + + /* Fill in instruction information. */ + info->insn_info_valid = 1; + info->insn_type = dis_branch; + info->target = target; } break; @@ -11043,6 +11071,11 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) offset &= ~2u; info->print_address_func (offset, info); + + /* Fill in instruction information. */ + info->insn_info_valid = 1; + info->insn_type = dis_branch; + info->target = offset; } break; @@ -11715,6 +11748,14 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) bfd_boolean found = FALSE; struct arm_private_data *private_data; + /* Clear instruction information field. */ + info->insn_info_valid = 0; + info->branch_delay_insns = 0; + info->data_size = 0; + info->insn_type = dis_noninsn; + info->target = 0; + info->target2 = 0; + if (info->disassembler_options) { parse_arm_disassembler_options (info->disassembler_options); diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 5d24fb5..c73e964 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -11069,6 +11069,9 @@ static const struct dis386 rm_table[][8] = { #define BND_PREFIX (0xf2 | 0x400) #define NOTRACK_PREFIX (0x3e | 0x100) +/* Remember if the current op is a jump instruction. */ +static bfd_boolean op_is_jump = FALSE; + static int ckprefix (void) { @@ -12143,6 +12146,50 @@ print_insn (bfd_vma pc, disassemble_info *info) } } + /* Clear instruction information. */ + if (the_info) + { + the_info->insn_info_valid = 0; + the_info->branch_delay_insns = 0; + the_info->data_size = 0; + the_info->insn_type = dis_noninsn; + the_info->target = 0; + the_info->target2 = 0; + } + + /* Reset jump operation indicator. */ + op_is_jump = FALSE; + + { + int jump_detection = 0; + + /* Extract flags. */ + for (i = 0; i < MAX_OPERANDS; ++i) + { + if ((dp->op[i].rtn == OP_J) + || (dp->op[i].rtn == OP_indirE)) + jump_detection |= 1; + else if ((dp->op[i].rtn == BND_Fixup) + || (!dp->op[i].rtn && !dp->op[i].bytemode)) + jump_detection |= 2; + else if ((dp->op[i].bytemode == cond_jump_mode) + || (dp->op[i].bytemode == loop_jcxz_mode)) + jump_detection |= 4; + } + + /* Determine if this is a jump or branch. */ + if ((jump_detection & 0x3) == 0x3) + { + op_is_jump = TRUE; + if (jump_detection & 0x4) + the_info->insn_type = dis_condbranch; + else + the_info->insn_type = + (dp->name && !strncmp(dp->name, "call", 4)) + ? dis_jsr : dis_branch; + } + } + /* If VEX.vvvv and EVEX.vvvv are unused, they must be all 1s, which are all 0s in inverted form. */ if (need_vex && vex.register_specifier != 0) @@ -12256,7 +12303,19 @@ print_insn (bfd_vma pc, disassemble_info *info) if (needcomma) (*info->fprintf_func) (info->stream, ","); if (op_index[i] != -1 && !op_riprel[i]) - (*info->print_address_func) ((bfd_vma) op_address[op_index[i]], info); + { + bfd_vma target = (bfd_vma) op_address[op_index[i]]; + + if (the_info && op_is_jump) + { + the_info->insn_info_valid = 1; + the_info->branch_delay_insns = 0; + the_info->data_size = 0; + the_info->target = target; + the_info->target2 = 0; + } + (*info->print_address_func) (target, info); + } else (*info->fprintf_func) (info->stream, "%s", op_txt[i]); needcomma = 1; |