-*- 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.
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.
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
--- /dev/null
+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);
+}
--- /dev/null
+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; }
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. */
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"))
{
".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);
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"));