Update objdump's --disassemble=<symbol> feature so that if <symbol> is a function, the entire function will be disassembled, regardless of the presence of interveening symbols.
* objdump.c (disassemble_section): When disassembling from a symbol only stop at the next symbol if the original symbol was not a function symbol. Otherwise continue disassembling until a new function is reached. * testsuite/binutils-all/objdump.exp: Add tests of extended functionality. * testsuite/binutils-all/disasm.s: New test source file.
This commit is contained in:
parent
e89c694196
commit
baae986a40
6 changed files with 213 additions and 25 deletions
|
@ -1,3 +1,13 @@
|
||||||
|
2019-01-17 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* objdump.c (disassemble_section): When disassembling from a
|
||||||
|
symbol only stop at the next symbol if the original symbol was not
|
||||||
|
a function symbol. Otherwise continue disassembling until a new
|
||||||
|
function is reached.
|
||||||
|
* testsuite/binutils-all/objdump.exp: Add tests of extended
|
||||||
|
functionality.
|
||||||
|
* testsuite/binutils-all/disasm.s: New test source file.
|
||||||
|
|
||||||
2019-01-16 Kito Cheng <kito@andestech.com>
|
2019-01-16 Kito Cheng <kito@andestech.com>
|
||||||
Nelson Chu <nelson@andestech.com>
|
Nelson Chu <nelson@andestech.com>
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
* Objdump's --disassemble option can now take a parameter, specifying the
|
* Objdump's --disassemble option can now take a parameter, specifying the
|
||||||
starting symbol for disassembly. Disassembly will continue from this
|
starting symbol for disassembly. Disassembly will continue from this
|
||||||
symbol up to the next symbol.
|
symbol up to the next symbol or the end of the function.
|
||||||
|
|
||||||
* The MIPS port now supports the Loongson 2K1000 processor which implements
|
* The MIPS port now supports the Loongson 2K1000 processor which implements
|
||||||
the MIPS64r2 ISA, the Loongson-mmi ASE, Loongson-cam ASE, Loongson-ext ASE,
|
the MIPS64r2 ISA, the Loongson-mmi ASE, Loongson-cam ASE, Loongson-ext ASE,
|
||||||
|
|
|
@ -2230,9 +2230,11 @@ with ctags tool.
|
||||||
Display the assembler mnemonics for the machine instructions from the
|
Display the assembler mnemonics for the machine instructions from the
|
||||||
input file. This option only disassembles those sections which are
|
input file. This option only disassembles those sections which are
|
||||||
expected to contain instructions. If the optional @var{symbol}
|
expected to contain instructions. If the optional @var{symbol}
|
||||||
argument is given, then display the assembler mnemonics only from
|
argument is given, then display the assembler mnemonics starting at
|
||||||
@var{symbol} up to next symbol. If there are no matches for
|
@var{symbol}. If @var{symbol} is a function name then disassembly
|
||||||
@var{symbol} then nothing will be displayed.
|
will stop at the end of the function, otherwise it will stop when the
|
||||||
|
next symbol is encountered. If there are no matches for @var{symbol}
|
||||||
|
then nothing will be displayed.
|
||||||
|
|
||||||
@item -D
|
@item -D
|
||||||
@itemx --disassemble-all
|
@itemx --disassemble-all
|
||||||
|
|
|
@ -2211,6 +2211,13 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||||
long rel_count;
|
long rel_count;
|
||||||
bfd_vma rel_offset;
|
bfd_vma rel_offset;
|
||||||
unsigned long addr_offset;
|
unsigned long addr_offset;
|
||||||
|
bfd_boolean do_print;
|
||||||
|
enum loop_control
|
||||||
|
{
|
||||||
|
stop_offset_reached,
|
||||||
|
function_sym,
|
||||||
|
next_sym
|
||||||
|
} loop_until;
|
||||||
|
|
||||||
/* Sections that do not contain machine
|
/* Sections that do not contain machine
|
||||||
code are not normally disassembled. */
|
code are not normally disassembled. */
|
||||||
|
@ -2328,13 +2335,15 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||||
the symbol we have just found. Then print the symbol and find the
|
the symbol we have just found. Then print the symbol and find the
|
||||||
next symbol on. Repeat until we have disassembled the entire section
|
next symbol on. Repeat until we have disassembled the entire section
|
||||||
or we have reached the end of the address range we are interested in. */
|
or we have reached the end of the address range we are interested in. */
|
||||||
|
do_print = paux->symbol == NULL;
|
||||||
|
loop_until = stop_offset_reached;
|
||||||
|
|
||||||
while (addr_offset < stop_offset)
|
while (addr_offset < stop_offset)
|
||||||
{
|
{
|
||||||
bfd_vma addr;
|
bfd_vma addr;
|
||||||
asymbol *nextsym;
|
asymbol *nextsym;
|
||||||
bfd_vma nextstop_offset;
|
bfd_vma nextstop_offset;
|
||||||
bfd_boolean insns;
|
bfd_boolean insns;
|
||||||
bfd_boolean do_print = TRUE;
|
|
||||||
|
|
||||||
addr = section->vma + addr_offset;
|
addr = section->vma + addr_offset;
|
||||||
addr = ((addr & ((sign_adjust << 1) - 1)) ^ sign_adjust) - sign_adjust;
|
addr = ((addr & ((sign_adjust << 1) - 1)) ^ sign_adjust) - sign_adjust;
|
||||||
|
@ -2360,20 +2369,80 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||||
pinfo->symtab_pos = -1;
|
pinfo->symtab_pos = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we are only disassembling from a specific symbol,
|
||||||
|
check to see if we should start or stop displaying. */
|
||||||
if (sym && paux->symbol)
|
if (sym && paux->symbol)
|
||||||
{
|
{
|
||||||
const char *name = bfd_asymbol_name (sym);
|
if (do_print)
|
||||||
char *alloc = NULL;
|
|
||||||
|
|
||||||
if (do_demangle && name[0] != '\0')
|
|
||||||
{
|
{
|
||||||
/* Demangle the name. */
|
/* See if we should stop printing. */
|
||||||
alloc = bfd_demangle (abfd, name, demangle_flags);
|
switch (loop_until)
|
||||||
if (alloc != NULL)
|
{
|
||||||
name = alloc;
|
case function_sym:
|
||||||
|
if (sym->flags & BSF_FUNCTION)
|
||||||
|
do_print = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case stop_offset_reached:
|
||||||
|
/* Handled by the while loop. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case next_sym:
|
||||||
|
/* FIXME: There is an implicit assumption here
|
||||||
|
that the name of sym is different from
|
||||||
|
paux->symbol. */
|
||||||
|
if (! bfd_is_local_label (abfd, sym))
|
||||||
|
do_print = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char * name = bfd_asymbol_name (sym);
|
||||||
|
char * alloc = NULL;
|
||||||
|
|
||||||
|
if (do_demangle && name[0] != '\0')
|
||||||
|
{
|
||||||
|
/* Demangle the name. */
|
||||||
|
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||||
|
if (alloc != NULL)
|
||||||
|
name = alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are not currently printing. Check to see
|
||||||
|
if the current symbol matches the requested symbol. */
|
||||||
|
if (streq (name, paux->symbol))
|
||||||
|
{
|
||||||
|
do_print = TRUE;
|
||||||
|
|
||||||
|
if (sym->flags & BSF_FUNCTION)
|
||||||
|
{
|
||||||
|
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
|
||||||
|
&& ((elf_symbol_type *) sym)->internal_elf_sym.st_size > 0)
|
||||||
|
{
|
||||||
|
/* Sym is a function symbol with a size associated
|
||||||
|
with it. Turn on automatic disassembly for the
|
||||||
|
next VALUE bytes. */
|
||||||
|
stop_offset = addr_offset
|
||||||
|
+ ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
|
||||||
|
loop_until = stop_offset_reached;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise we need to tell the loop heuristic to
|
||||||
|
loop until the next function symbol is encountered. */
|
||||||
|
loop_until = function_sym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise loop until the next symbol is encountered. */
|
||||||
|
loop_until = next_sym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free (alloc);
|
||||||
}
|
}
|
||||||
do_print = streq (name, paux->symbol);
|
|
||||||
free (alloc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! prefix_addresses && do_print)
|
if (! prefix_addresses && do_print)
|
||||||
|
@ -2438,13 +2507,9 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||||
insns = FALSE;
|
insns = FALSE;
|
||||||
|
|
||||||
if (do_print)
|
if (do_print)
|
||||||
{
|
disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
|
||||||
disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
|
addr_offset, nextstop_offset,
|
||||||
addr_offset, nextstop_offset,
|
rel_offset, &rel_pp, rel_ppend);
|
||||||
rel_offset, &rel_pp, rel_ppend);
|
|
||||||
if (paux->symbol)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_offset = nextstop_offset;
|
addr_offset = nextstop_offset;
|
||||||
sym = nextsym;
|
sym = nextsym;
|
||||||
|
|
24
binutils/testsuite/binutils-all/disasm.s
Normal file
24
binutils/testsuite/binutils-all/disasm.s
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
.text
|
||||||
|
|
||||||
|
.globl start_of_text
|
||||||
|
start_of_text:
|
||||||
|
.type start_of_text, "function"
|
||||||
|
.long 1
|
||||||
|
.size start_of_text, . - start_of_text
|
||||||
|
|
||||||
|
.globl func
|
||||||
|
func:
|
||||||
|
.type func, "function"
|
||||||
|
.long 2
|
||||||
|
.global global_non_func_sym
|
||||||
|
global_non_func_sym:
|
||||||
|
.long 3
|
||||||
|
local_non_func_sym:
|
||||||
|
.long 4
|
||||||
|
.size func, . - func
|
||||||
|
|
||||||
|
.globl next_func
|
||||||
|
next_func:
|
||||||
|
.type next_func, "function"
|
||||||
|
.long 5
|
||||||
|
.size next_func, . - next_func
|
|
@ -62,7 +62,7 @@ if [regexp $want $got] then {
|
||||||
|
|
||||||
|
|
||||||
if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
|
if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
|
||||||
fail "objdump (assembling)"
|
fail "objdump (assembling bintest.s)"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest2.o]} then {
|
if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest2.o]} then {
|
||||||
|
@ -280,8 +280,95 @@ proc test_objdump_d_sym { testfile dumpfile } {
|
||||||
}
|
}
|
||||||
|
|
||||||
test_objdump_d_sym $testfile $testfile
|
test_objdump_d_sym $testfile $testfile
|
||||||
if { [ remote_file host exists $testarchive ] } then {
|
|
||||||
test_objdump_d_sym $testarchive bintest2.o
|
proc test_objdump_d_func_sym { testfile dumpfile } {
|
||||||
|
global OBJDUMP
|
||||||
|
global OBJDUMPFLAGS
|
||||||
|
|
||||||
|
set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS --disassemble=func --disassemble-zeroes $testfile"]
|
||||||
|
|
||||||
|
set want "$dumpfile:.*Disassembly of section"
|
||||||
|
if ![regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=func $testfile: No disassembly title"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+0 <start_of_text>"
|
||||||
|
if [regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=func $testfile: First symbol displayed, when it should be absent"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+. <func>"
|
||||||
|
if ![regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=func $testfile: Disassembly does not start at function symbol"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+. <global_non_func_sym>"
|
||||||
|
if ![regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=func $testfile: Non function symbol not displayed"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+. <next_func>"
|
||||||
|
if [regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=func $testfile: Disassembly did not stop at the next function"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pass "objdump --disassemble=func $testfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc test_objdump_d_non_func_sym { testfile dumpfile } {
|
||||||
|
global OBJDUMP
|
||||||
|
global OBJDUMPFLAGS
|
||||||
|
|
||||||
|
set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS --disassemble=global_non_func_sym $testfile"]
|
||||||
|
|
||||||
|
set want "$dumpfile:.*Disassembly of section"
|
||||||
|
if ![regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=non_func $testfile: No disassembly title"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+0 <start_of_text>"
|
||||||
|
if [regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=non_func $testfile: First symbol displayed, when it should be absent"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+. <global_non_func_sym>"
|
||||||
|
if ![regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=non_func $testfile: Non function symbol not displayed"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set want "$dumpfile:.*00+. <local_non_func_sym>"
|
||||||
|
if [regexp $want $got] then {
|
||||||
|
fail "objdump --disassemble=non_func $testfile: Disassembly did not stop at the next symbol"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pass "objdump --disassemble=non_func $testfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extra test for ELF format - check that --disassemble=func disassembles
|
||||||
|
# all of func, and does not stop at the next symbol.
|
||||||
|
if { [is_elf_format] } then {
|
||||||
|
|
||||||
|
if {![binutils_assemble $srcdir/$subdir/disasm.s tmpdir/disasm.o]} then {
|
||||||
|
fail "objdump --disassemble=func (assembling disasm.s)"
|
||||||
|
} else {
|
||||||
|
if [is_remote host] {
|
||||||
|
set elftestfile [remote_download host tmpdir/disasm.o]
|
||||||
|
} else {
|
||||||
|
set elftestfile tmpdir/disasm.o
|
||||||
|
}
|
||||||
|
|
||||||
|
test_objdump_d_func_sym $elftestfile $elftestfile
|
||||||
|
test_objdump_d_non_func_sym $elftestfile $elftestfile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue