[binutils-gdb] Objdump: Add "-M annotate" option to the AArch64 disassembler.
Nick Clifton
nickc@sourceware.org
Fri May 8 10:11:02 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0166d3cedefcd8f60417427f7b72f46e74a35290
commit 0166d3cedefcd8f60417427f7b72f46e74a35290
Author: Nick Clifton <nickc@redhat.com>
Date: Fri May 8 11:10:05 2026 +0100
Objdump: Add "-M annotate" option to the AArch64 disassembler.
Diff:
---
binutils/NEWS | 4 +++
binutils/doc/binutils.texi | 10 +++++-
.../testsuite/binutils-all/aarch64/aarch64.exp | 32 +++++++++++++++++
.../testsuite/binutils-all/aarch64/objdumpM1.c | 42 ++++++++++++++++++++++
.../testsuite/binutils-all/aarch64/objdumpM2.c | 5 +++
opcodes/aarch64-dis.c | 39 ++++++++++++++++++--
6 files changed, 129 insertions(+), 3 deletions(-)
diff --git a/binutils/NEWS b/binutils/NEWS
index 29821c96d0f..5532670b4a2 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,9 @@
-*- text -*-
+* The AArch64 disassembler now accepts a command line option of "-M annotate"
+ which displays the symbol associated with undefined instructions, should
+ there be one.
+
* 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.
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 45df92394b6..198ae8244ef 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -2691,7 +2691,15 @@ compilers.
For AArch64 targets this switch can be used to set whether instructions are
disassembled as the most general instruction using the @option{-M no-aliases}
option or whether instruction notes should be generated as comments in the
-disasssembly using @option{-M notes}.
+disasssembly using @option{-M notes}. In addition the @option{-M
+annotate} option can be used to customise the handling of undefined
+instructions when disassembling executables and shared libraries.
+Normally the disassembler will just show the hexadecimal value of tge
+undefined instruction, but if annotation is enabled it will first try
+to find a symbol whose value matches the instruction's encoding. If
+there is a match then the symbol name will be displayed instead. This
+can be useful when disassembling non-code sections which may contain
+function and data addresses.
For the x86, some of the options duplicate functions of the @option{-m}
switch, but allow finer grained control.
diff --git a/binutils/testsuite/binutils-all/aarch64/aarch64.exp b/binutils/testsuite/binutils-all/aarch64/aarch64.exp
index 05edcf53203..9699df54894 100644
--- a/binutils/testsuite/binutils-all/aarch64/aarch64.exp
+++ b/binutils/testsuite/binutils-all/aarch64/aarch64.exp
@@ -28,3 +28,35 @@ foreach t $test_list {
verbose [file rootname $t]
run_dump_test [file rootname $t]
}
+
+# Test objdump -M annotate
+
+proc test_objdump_M_annotate { } {
+ global srcdir
+ global subdir
+ global OBJDUMP
+ global OBJDUMPFLAGS
+
+ set test "objdump -M annotate"
+
+ set result [target_compile "$srcdir/$subdir/objdumpM1.c $srcdir/$subdir/objdumpM2.c" tmpdir/objdumpM executable debug]
+ if { $result != "" } {
+ unsupported "$test (build): compile result: $result"
+ return
+ }
+
+ set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -D -M annotate tmpdir/objdumpM"]
+
+ # Look for something like this in the disassembly:
+ # 420020: 00400780 .inst 0x00400780 ; [func1]
+ set want "; \[func1\]"
+
+ if [regexp $want $got] then {
+ pass $test
+ # file delete objdumpM
+ } else {
+ fail $test
+ }
+}
+
+test_objdump_M_annotate
diff --git a/binutils/testsuite/binutils-all/aarch64/objdumpM1.c b/binutils/testsuite/binutils-all/aarch64/objdumpM1.c
new file mode 100644
index 00000000000..1b7c8604f9b
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/objdumpM1.c
@@ -0,0 +1,42 @@
+int datum = 22;
+
+extern int func1 (int);
+extern int func2 (int);
+extern int func3 (int);
+extern int func4 (int);
+extern int func5 (int);
+
+/* Create an array of function pointers in the .data section. */
+struct ptrs
+{
+ int (* fptr)(int);
+ int field;
+}
+fred [5] =
+{
+ { func1, 1 },
+ { func2, 2 },
+ { func3, 3 },
+ { func4, 4 },
+ { func5, 5 }
+};
+
+int main (int arg)
+{
+ /* FIXME: We want a way to make sure that undefined instructions that
+ are inserted via the .inst directive are not annotated. (Since the .inst
+ directive is used explicitly for instructions and the user does not care
+ if they happen to match a symbolic value).
+
+ Unfortunately the .inst directive only supports constant expressions so
+ we cannot use an unresolved symbolic value. Inserting a symbolic value
+ via one of the data directives does not work since they are labeled as
+ data (via the MAP_DATA mapping state) and hence they become eligible
+ for annotation.
+
+ So for now we are stuck. */
+
+ /* Stop the compiler from optimizing away the function pointer array
+ by using it in a non-predictable manner. */
+ return fred[arg].fptr (fred[arg].field * datum);
+}
diff --git a/binutils/testsuite/binutils-all/aarch64/objdumpM2.c b/binutils/testsuite/binutils-all/aarch64/objdumpM2.c
new file mode 100644
index 00000000000..a4e8dee4365
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/objdumpM2.c
@@ -0,0 +1,5 @@
+int func1 (int arg) { return arg * 2; }
+int func2 (int arg) { return arg * 3; }
+int func3 (int arg) { return arg * 4; }
+int func4 (int arg) { return arg * 5; }
+int func5 (int arg) { return arg * 6; }
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 8544ce4b6d4..a7a170661b2 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -49,6 +49,7 @@ static enum map_type last_type;
static int last_mapping_sym = -1;
static bfd_vma last_stop_offset = 0;
static bfd_vma last_mapping_addr = 0;
+static bool annotate_undefined_insns = false;
/* Other options */
static int no_aliases = 0; /* If set disassemble as most general inst. */
@@ -91,6 +92,18 @@ parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED)
return;
}
+ if (startswith (option, "annotate"))
+ {
+ annotate_undefined_insns = true;
+ return;
+ }
+
+ if (startswith (option, "no-annotate"))
+ {
+ annotate_undefined_insns = false;
+ return;
+ }
+
#ifdef DEBUG_AARCH64
if (startswith (option, "debug_dump"))
{
@@ -4260,8 +4273,24 @@ print_insn_aarch64_word (bfd_vma pc,
".inst\t");
(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
"0x%08x", word);
- (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
- " ; %s", err_msg[ret]);
+ asymbol * sym = NULL;
+ /* See if this "instruction" is actually the address of something. */
+ if (annotate_undefined_insns
+ /* Skip values that have been explicitly tagged as code. */
+ && last_type == MAP_DATA
+ /* Skip static object files as symbol values have not be resolved yet. */
+ && info->section != NULL
+ && info->section->owner != NULL
+ && (info->section->owner->flags & (EXEC_P | DYNAMIC)))
+ {
+ sym = info->symbol_at_address_func (word, info);
+ if (sym != NULL)
+ info->fprintf_styled_func (info->stream, dis_style_symbol,
+ " ; [%s]", sym->name);
+ }
+ if (sym == NULL)
+ info->fprintf_styled_func (info->stream, dis_style_comment_start,
+ " ; %s", err_msg[ret]);
break;
case ERR_OK:
user_friendly_fixup (&inst);
@@ -4595,6 +4624,12 @@ with the -M switch (multiple options should be separated by commas):\n"));
fprintf (stream, _("\n\
notes Do print instruction notes.\n"));
+ fprintf (stream, _("\n\
+ annotate Display symbol names for undefined instructions.\n"));
+
+ fprintf (stream, _("\n\
+ no-annotate Do not display symbol names for undefined instructions.\n"));
+
#ifdef DEBUG_AARCH64
fprintf (stream, _("\n\
debug_dump Temp switch for debug trace.\n"));
More information about the Binutils-cvs
mailing list