mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-11 11:23:35 +08:00
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
@ -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>
|
||||
Nelson Chu <nelson@andestech.com>
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
* Objdump's --disassemble option can now take a parameter, specifying the
|
||||
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 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
|
||||
input file. This option only disassembles those sections which are
|
||||
expected to contain instructions. If the optional @var{symbol}
|
||||
argument is given, then display the assembler mnemonics only from
|
||||
@var{symbol} up to next symbol. If there are no matches for
|
||||
@var{symbol} then nothing will be displayed.
|
||||
argument is given, then display the assembler mnemonics starting at
|
||||
@var{symbol}. If @var{symbol} is a function name then disassembly
|
||||
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
|
||||
@itemx --disassemble-all
|
||||
|
@ -2211,6 +2211,13 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||
long rel_count;
|
||||
bfd_vma rel_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
|
||||
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
|
||||
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. */
|
||||
do_print = paux->symbol == NULL;
|
||||
loop_until = stop_offset_reached;
|
||||
|
||||
while (addr_offset < stop_offset)
|
||||
{
|
||||
bfd_vma addr;
|
||||
asymbol *nextsym;
|
||||
bfd_vma nextstop_offset;
|
||||
bfd_boolean insns;
|
||||
bfd_boolean do_print = TRUE;
|
||||
|
||||
addr = section->vma + addr_offset;
|
||||
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;
|
||||
}
|
||||
|
||||
/* If we are only disassembling from a specific symbol,
|
||||
check to see if we should start or stop displaying. */
|
||||
if (sym && paux->symbol)
|
||||
{
|
||||
const char *name = bfd_asymbol_name (sym);
|
||||
char *alloc = NULL;
|
||||
|
||||
if (do_demangle && name[0] != '\0')
|
||||
if (do_print)
|
||||
{
|
||||
/* Demangle the name. */
|
||||
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||
if (alloc != NULL)
|
||||
name = alloc;
|
||||
/* See if we should stop printing. */
|
||||
switch (loop_until)
|
||||
{
|
||||
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)
|
||||
@ -2438,13 +2507,9 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||
insns = FALSE;
|
||||
|
||||
if (do_print)
|
||||
{
|
||||
disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
|
||||
addr_offset, nextstop_offset,
|
||||
rel_offset, &rel_pp, rel_ppend);
|
||||
if (paux->symbol)
|
||||
break;
|
||||
}
|
||||
disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
|
||||
addr_offset, nextstop_offset,
|
||||
rel_offset, &rel_pp, rel_ppend);
|
||||
|
||||
addr_offset = nextstop_offset;
|
||||
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 {
|
||||
fail "objdump (assembling)"
|
||||
fail "objdump (assembling bintest.s)"
|
||||
return
|
||||
}
|
||||
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
|
||||
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…
Reference in New Issue
Block a user