[binutils-gdb] x86 disassembler: Add -Mannotate option to display symbolic names associated with immediates
Nick Clifton via Binutils-cvs <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a9450872773511b5c527cf68598a2381a4a03fca commit a9450872773511b5c527cf68598a2381a4a03fca Author: Nick Clifton <[email protected]> Date: Fri Apr 24 14:34:50 2026 +0100 x86 disassembler: Add -Mannotate option to display symbolic names associated with immediates Diff: --- binutils/NEWS | 4 ++ binutils/doc/binutils.texi | 6 ++ binutils/testsuite/binutils-all/x86-64/x86-64.exp | 31 +++++++++++ opcodes/i386-dis.c | 68 +++++++++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/binutils/NEWS b/binutils/NEWS index 5ac0e8b7811..29821c96d0f 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,9 @@ -*- text -*- +* The x86 and x86_64 disassemblers now accept a command line option of + "-M annotate-immediates" which displays the symbol associated with immediate + values, should there be one. + * Objdump and readelf now have a --debug-dir=<DIR> option which can be used to tell them where to find separate debug info files. diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 59ffe548543..45df92394b6 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2729,6 +2729,12 @@ When in AT&T mode and also for a limited set of instructions when in Intel mode, instructs the disassembler to print a mnemonic suffix even when the suffix could be inferred by the operands or, for certain instructions, the execution mode's defaults. + +@item annotate-immediates +Display the symbol associated with immediate values, should there be +one. Only works on executable binaries and shared libraries, not +static object files. + @end table For PowerPC, the @option{-M} argument @option{raw} selects diff --git a/binutils/testsuite/binutils-all/x86-64/x86-64.exp b/binutils/testsuite/binutils-all/x86-64/x86-64.exp index 162030e5aea..49ade490fb7 100644 --- a/binutils/testsuite/binutils-all/x86-64/x86-64.exp +++ b/binutils/testsuite/binutils-all/x86-64/x86-64.exp @@ -323,3 +323,34 @@ if {[catch "system \"bzip2 -dc $t > $obj\""] != 0} { run_pr33230_test "$testname" $obj "" $run_readelf run_pr33230_test "$testname" $obj "--input-target=default" $run_readelf } + +# Test objdump -M annotate + +proc test_objdump_M_annotate { } { + global srcdir + global subdir + global OBJDUMP + global OBJDUMPFLAGS + global exe + + set test "objdump -M annotate" + + if { [target_compile $srcdir/$subdir/../testprog.c tmpdir/testprog${exe} executable debug] != "" } { + unsupported "$test (build)" + return + } + + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -d -M annotate tmpdir/testprog${exe}"] + + # Look for something like this in the disassembly: + # 400419: bf 18 30 40 00 mov $0x403018,%edi # [common] + set want " \[common\]" + + if [regexp $want $got] then { + pass $test + } else { + fail $test + } +} + +test_objdump_M_annotate diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 21f37bc7509..f0749c1fad0 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -41,6 +41,8 @@ typedef struct instr_info instr_info; +static bool annotate_immediates = false; + static bool dofloat (instr_info *, int); static int putop (instr_info *, const char *, int); static void oappend_with_style (instr_info *, const char *, @@ -121,6 +123,9 @@ static void ATTRIBUTE_PRINTF_3 i386_dis_printf (const disassemble_info *, /* The maximum operand buffer size. */ #define MAX_OPERAND_BUFFER_SIZE 128 +/* The comment buffer size. */ +#define COMMENT_BUFFER_SIZE 128 + enum address_mode { mode_16bit, @@ -176,6 +181,8 @@ struct instr_info char obuf[MAX_OPERAND_BUFFER_SIZE]; char *obufp; + char cbuf[COMMENT_BUFFER_SIZE]; + char * cbufp; char *mnemonicendp; const uint8_t *start_codep; uint8_t *codep; @@ -9043,6 +9050,7 @@ with the -M switch (multiple options should be separated by commas):\n")); fprintf (stream, _(" suffix Always display instruction suffix in AT&T syntax\n")); fprintf (stream, _(" amd64 Display instruction in AMD64 ISA\n")); fprintf (stream, _(" intel64 Display instruction in Intel64 ISA\n")); + fprintf (stream, _(" annotate-immediates Annotate immediate operands that match symbols\n")); } /* Bad opcode. */ @@ -9741,6 +9749,7 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) .start_codep = priv.the_buffer, .codep = priv.the_buffer, .obufp = ins.obuf, + .cbufp = ins.cbuf, .last_lock_prefix = -1, .last_repz_prefix = -1, .last_repnz_prefix = -1, @@ -9825,6 +9834,9 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) else if (startswith (p, "suffix")) priv.orig_sizeflag |= SUFFIX_ALWAYS; + else if (startswith (p, "annotate")) + annotate_immediates = true; + p = strchr (p, ','); if (p != NULL) p++; @@ -10363,6 +10375,13 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) info); break; } + if (ins.cbufp != ins.cbuf) + { + if (i == MAX_OPERANDS) + i386_dis_printf (info, dis_style_comment_start, " # "); + i386_dis_printf (info, dis_style_comment_start, "%s", ins.cbuf); + } + ret = ins.codep - priv.the_buffer; out: info->private_data = NULL; @@ -11564,6 +11583,26 @@ oappend_with_style (instr_info *ins, const char *s, ins->obufp = stpcpy (ins->obufp, s); } +/* Add a comment to the comment buffer. */ + +static void +cappend_with_style (instr_info *ins, const char *s, + enum disassembler_style style) +{ + if (ins->cbufp + strlen (s) + 4 >= ins->cbuf + COMMENT_BUFFER_SIZE) + return; + + unsigned num = (unsigned) style; + + *ins->cbufp++ = STYLE_MARKER_CHAR; + *ins->cbufp++ = (num < 10 ? ('0' + num) + : ((num < 16) ? ('a' + (num - 10)) : '0')); + *ins->cbufp++ = STYLE_MARKER_CHAR; + *ins->cbufp = '\0'; + + ins->cbufp = stpcpy (ins->cbufp, s); +} + /* Add a single character C to the buffer pointer to by INS->obufp, marking the style for the character as STYLE. */ @@ -11637,7 +11676,36 @@ oappend_immediate (instr_info *ins, bfd_vma imm) { if (!ins->intel_syntax) oappend_char_with_style (ins, '$', dis_style_immediate); + print_operand_value (ins, imm, dis_style_immediate); + + /* Determine if we can display some more information about this immediate. */ + if (! annotate_immediates + /* Don't bother with zero, even if there is symbol associated with it. */ + || imm == 0 + /* For the next tests we need a BFD. If we do not have one then do not proceed. */ + || ins->info->section == NULL + || ins->info->section->owner == NULL + /* Save time by avoiding immediates that cannot reference part of the address space. */ + || imm < ins->info->section->owner->start_address + /* Also skip static object files as their symbols have not been resolved. */ + || (ins->info->section->owner->flags & (EXEC_P | DYNAMIC)) == 0) + return; + + asymbol * sym = ins->info->symbol_at_address_func (imm, ins->info); + if (sym == NULL) + return; + + char * annotation = NULL; + + /* FIXME: Potential memory leak: strictly speaking asprintf() + can return 0 whilst also having allocated some memory. */ + if (asprintf (& annotation, " [%s]", sym->name) > 0) + { + /* Display the symbol associated with address 'imm'. */ + cappend_with_style (ins, annotation, dis_style_symbol); + free (annotation); + } } /* Put DISP in BUF as signed hex number. */