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/i386-dis.c | |
parent | a4f2b7c5d931f2aa27851b59ae5817a6ee43cfcb (diff) | |
download | gdb-1d67fe3b6e696fccb902d9919b9e58b7299a3205.zip gdb-1d67fe3b6e696fccb902d9919b9e58b7299a3205.tar.gz 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/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 61 |
1 files changed, 60 insertions, 1 deletions
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; |