/* objdump.c -- dump information about an object file.
- Copyright (C) 1990-2017 Free Software Foundation, Inc.
+ Copyright (C) 1990-2018 Free Software Foundation, Inc.
This file is part of GNU Binutils.
static int prefix_strip; /* --prefix-strip */
static size_t prefix_length;
static bfd_boolean unwind_inlines; /* --inlines. */
+static const char * disasm_sym; /* Disassembly start symbol. */
/* A structure to record the sections mentioned in -j switches. */
struct only
long dynrelcount;
disassembler_ftype disassemble_fn;
arelent * reloc;
+ const char * symbol;
};
/* Architecture to disassemble for, or default if NULL. */
-x, --all-headers Display the contents of all headers\n\
-d, --disassemble Display assembler contents of executable sections\n\
-D, --disassemble-all Display assembler contents of all sections\n\
+ --disassemble=<sym> Display assembler contents from <sym>\n\
-S, --source Intermix source code with disassembly\n\
-s, --full-contents Display the full contents of all sections requested\n\
-g, --debugging Display debug information in object file\n\
{"debugging", no_argument, NULL, 'g'},
{"debugging-tags", no_argument, NULL, 'e'},
{"demangle", optional_argument, NULL, 'C'},
- {"disassemble", no_argument, NULL, 'd'},
+ {"disassemble", optional_argument, NULL, 'd'},
{"disassemble-all", no_argument, NULL, 'D'},
{"disassembler-options", required_argument, NULL, 'M'},
{"disassemble-zeroes", no_argument, NULL, 'z'},
static bfd_boolean
is_significant_symbol_name (const char * name)
{
- return strcmp (name, ".plt") == 0
- || strcmp (name, ".got") == 0
- || strcmp (name, ".plt.got") == 0;
+ return strncmp (name, ".plt", 4) == 0 || strcmp (name, ".got") == 0;
}
/* Filter out (in place) symbols that are useless for disassembly.
asection *sec;
unsigned int opb;
bfd_boolean want_section;
+ long rel_count;
if (sorted_symcount < 1)
return NULL;
and we have dynamic relocations available, then we can produce
a better result by matching a relocation to the address and
using the symbol associated with that relocation. */
+ rel_count = aux->dynrelcount;
if (!want_section
- && aux->dynrelbuf != NULL
&& sorted_syms[thisplace]->value != vma
+ && rel_count > 0
+ && aux->dynrelbuf != NULL
+ && aux->dynrelbuf[0]->address <= vma
+ && aux->dynrelbuf[rel_count - 1]->address >= vma
/* If we have matched a synthetic symbol, then stick with that. */
&& (sorted_syms[thisplace]->flags & BSF_SYNTHETIC) == 0)
{
- long rel_count;
- arelent ** rel_pp;
+ arelent ** rel_low;
+ arelent ** rel_high;
- for (rel_count = aux->dynrelcount, rel_pp = aux->dynrelbuf;
- rel_count--;)
+ rel_low = aux->dynrelbuf;
+ rel_high = rel_low + rel_count - 1;
+ while (rel_low <= rel_high)
{
- arelent * rel = rel_pp[rel_count];
+ arelent **rel_mid = &rel_low[(rel_high - rel_low) / 2];
+ arelent * rel = *rel_mid;
- if (rel->address == vma
- && rel->sym_ptr_ptr != NULL
- /* Absolute relocations do not provide a more helpful symbolic address. */
- && ! bfd_is_abs_section ((* rel->sym_ptr_ptr)->section))
+ if (rel->address == vma)
{
- if (place != NULL)
- * place = thisplace;
- return * rel->sym_ptr_ptr;
+ /* Absolute relocations do not provide a more helpful
+ symbolic address. Find a non-absolute relocation
+ with the same address. */
+ arelent **rel_vma = rel_mid;
+ for (rel_mid--;
+ rel_mid >= rel_low && rel_mid[0]->address == vma;
+ rel_mid--)
+ rel_vma = rel_mid;
+
+ for (; rel_vma <= rel_high && rel_vma[0]->address == vma;
+ rel_vma++)
+ {
+ rel = *rel_vma;
+ if (rel->sym_ptr_ptr != NULL
+ && ! bfd_is_abs_section ((* rel->sym_ptr_ptr)->section))
+ {
+ if (place != NULL)
+ * place = thisplace;
+ return * rel->sym_ptr_ptr;
+ }
+ }
+ break;
}
- /* We are scanning backwards, so if we go below the target address
- we have failed. */
- if (rel_pp[rel_count]->address < vma)
+ if (vma < rel->address)
+ rel_high = rel_mid;
+ else if (vma >= rel_mid[1]->address)
+ rel_low = rel_mid + 1;
+ else
break;
}
}
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;
pinfo->symtab_pos = -1;
}
- if (! prefix_addresses)
+ if (sym && paux->symbol)
+ {
+ const char *name = bfd_asymbol_name (sym);
+ char *alloc = NULL;
+
+ if (do_demangle && name[0] != '\0')
+ {
+ /* Demangle the name. */
+ alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
+ if (alloc != NULL)
+ name = alloc;
+ }
+ do_print = streq (name, paux->symbol);
+ free (alloc);
+ }
+
+ if (! prefix_addresses && do_print)
{
pinfo->fprintf_func (pinfo->stream, "\n");
objdump_print_addr_with_sym (abfd, section, sym, addr,
else
insns = FALSE;
- disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
- addr_offset, nextstop_offset,
- rel_offset, &rel_pp, rel_ppend);
+ 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;
+ }
addr_offset = nextstop_offset;
sym = nextsym;
aux.dynrelbuf = NULL;
aux.dynrelcount = 0;
aux.reloc = NULL;
+ aux.symbol = disasm_sym;
disasm_info.print_address_func = objdump_print_address;
disasm_info.symbol_at_address_func = objdump_symbol_at_address;
struct dwarf_section *section = &debug_displays [debug].section;
bfd *abfd = (bfd *) file;
bfd_byte *contents;
+ bfd_size_type amt;
if (section->start != NULL)
{
section->num_relocs = 0;
section->address = bfd_get_section_vma (abfd, sec);
section->size = bfd_get_section_size (sec);
- section->start = contents = malloc (section->size + 1);
+ amt = section->size + 1;
+ section->start = contents = malloc (amt);
section->user_data = sec;
- if (section->start == NULL
+ if (amt == 0
+ || section->start == NULL
|| !bfd_get_full_section_contents (abfd, sec, &contents))
{
free_debug_section (debug);
init_dwarf_regnames_s390 ();
break;
+ case bfd_arch_riscv:
+ init_dwarf_regnames_riscv ();
+ break;
+
+ case bfd_arch_s12z:
+ /* S12Z has a 24 bit address space. But the only known
+ producer of dwarf_info encodes addresses into 32 bits. */
+ eh_addr_size = 4;
+ break;
+
default:
break;
}
}
if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0
- && (ufile_ptr) relsize > bfd_get_file_size (abfd))
+ && (/* Check that the size of the relocs is reasonable. Note that some
+ file formats, eg aout, can have relocs whose internal size is
+ larger than their external size, thus we check the size divided
+ by four against the file size. See PR 23931 for an example of
+ this. */
+ ((ufile_ptr) (relsize / 4) > bfd_get_file_size (abfd))
+ /* Also check the section's reloc count since if this is negative
+ (or very large) the computation in bfd_get_reloc_upper_bound
+ may have resulted in returning a small, positive integer.
+ See PR 22508 for a reproducer.
+
+ Note - we check against file size rather than section size as
+ it is possible for there to be more relocs that apply to a
+ section than there are bytes in that section. */
+ || (section->reloc_count > bfd_get_file_size (abfd))))
{
- printf (" (too many: 0x%x)\n", section->reloc_count);
+ printf (" (too many: %#x relocs)\n", section->reloc_count);
bfd_set_error (bfd_error_file_truncated);
bfd_fatal (bfd_get_filename (abfd));
}
printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd),
abfd->xvec->name);
if (dump_ar_hdrs)
- print_arelt_descr (stdout, abfd, TRUE);
+ print_arelt_descr (stdout, abfd, TRUE, FALSE);
if (dump_file_header)
dump_bfd_header (abfd);
if (dump_private_headers)
exit_status = 1;
}
}
- /* PR 6483: If there was no STABS or IEEE debug
- info in the file, try DWARF instead. */
+ /* PR 6483: If there was no STABS debug info in the file, try
+ DWARF instead. */
else if (! dump_dwarf_section_info)
{
dwarf_select_sections_all ();
expandargv (&argc, &argv);
- bfd_init ();
+ if (bfd_init () != BFD_INIT_MAGIC)
+ fatal (_("fatal error: libbfd ABI mismatch"));
set_default_bfd_target ();
while ((c = getopt_long (argc, argv,
case 'd':
disassemble = TRUE;
seenflag = TRUE;
+ disasm_sym = optarg;
break;
case 'z':
disassemble_zeroes = TRUE;