diff options
Diffstat (limited to 'binutils/objdump.c')
-rw-r--r-- | binutils/objdump.c | 259 |
1 files changed, 158 insertions, 101 deletions
diff --git a/binutils/objdump.c b/binutils/objdump.c index ebe586e..7bb6d76 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -132,7 +132,6 @@ static const char *prefix; /* --prefix */ static int prefix_strip; /* --prefix-strip */ static size_t prefix_length; static bool unwind_inlines; /* --inlines. */ -static const char * disasm_sym; /* Disassembly start symbol. */ static const char * source_comment; /* --source_comment. */ static bool visualize_jumps = false; /* --visualize-jumps. */ static bool color_output = false; /* --visualize-jumps=color. */ @@ -141,6 +140,12 @@ static int process_links = false; /* --process-links. */ static int show_all_symbols; /* --show-all-symbols. */ static bool decompressed_dumps = false; /* -Z, --decompress. */ +static struct symbol_entry + { + const char *name; + struct symbol_entry *next; + } *disasm_sym_list; /* Disassembly start symbol(s). */ + static enum color_selection { on_if_terminal_output, @@ -187,7 +192,7 @@ struct objdump_disasm_info bool require_sec; disassembler_ftype disassemble_fn; arelent *reloc; - const char *symbol; + struct symbol_entry *symbol_list; }; /* Architecture to disassemble for, or default if NULL. */ @@ -1107,6 +1112,28 @@ remove_useless_symbols (asymbol **symbols, long count) return out_ptr - symbols; } +/* Return true iff SEC1 and SEC2 are the same section. + This would just be a simple pointer comparison except that one of + the sections might be from a separate debug info file. */ + +static bool +is_same_section (const asection *sec1, const asection *sec2) +{ + if (sec1 == sec2) + return true; + if (sec1->owner == sec2->owner + || sec1->owner == NULL + || sec2->owner == NULL) + return false; + /* OK, so we have one section in a debug info file. (Or they both + are, but the way this function is currently used sec1 will be in + a normal object.) Compare names, vma and size. This ought to + cover all the usual cases. */ + return (sec1->vma == sec2->vma + && sec1->size == sec2->size + && strcmp (sec1->name, sec2->name) == 0); +} + static const asection *compare_section; /* Sort symbols into value order. */ @@ -1131,10 +1158,9 @@ compare_symbols (const void *ap, const void *bp) /* Prefer symbols from the section currently being disassembled. Don't sort symbols from other sections by section, since there - isn't much reason to prefer one section over another otherwise. - See sym_ok comment for why we compare by section name. */ - as = strcmp (compare_section->name, a->section->name) == 0; - bs = strcmp (compare_section->name, b->section->name) == 0; + isn't much reason to prefer one section over another otherwise. */ + as = is_same_section (compare_section, a->section); + bs = is_same_section (compare_section, b->section); if (as && !bs) return -1; if (!as && bs) @@ -1353,26 +1379,8 @@ sym_ok (bool want_section, asection *sec, struct disassemble_info *inf) { - if (want_section) - { - /* NB: An object file can have different sections with the same - section name. Compare compare section pointers if they have - the same owner. */ - if (sorted_syms[place]->section->owner == sec->owner - && sorted_syms[place]->section != sec) - return false; - - /* Note - we cannot just compare section pointers because they could - be different, but the same... Ie the symbol that we are trying to - find could have come from a separate debug info file. Under such - circumstances the symbol will be associated with a section in the - debug info file, whilst the section we want is in a normal file. - So the section pointers will be different, but the section names - will be the same. */ - if (strcmp (bfd_section_name (sorted_syms[place]->section), - bfd_section_name (sec)) != 0) - return false; - } + if (want_section && !is_same_section (sec, sorted_syms[place]->section)) + return false; return inf->symbol_is_valid (sorted_syms[place], inf); } @@ -3895,7 +3903,7 @@ 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; + do_print = paux->symbol_list == NULL; loop_until = stop_offset_reached; while (addr_offset < stop_offset) @@ -3935,9 +3943,9 @@ disassemble_section (bfd *abfd, asection *section, void *inf) pinfo->symtab_pos = -1; } - /* If we are only disassembling from a specific symbol, + /* If we are only disassembling from specific symbols, check to see if we should start or stop displaying. */ - if (sym && paux->symbol) + if (sym && paux->symbol_list) { if (do_print) { @@ -3954,15 +3962,13 @@ disassemble_section (bfd *abfd, asection *section, void *inf) 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 + + if (!do_print) { const char * name = bfd_asymbol_name (sym); char * alloc = NULL; @@ -3976,8 +3982,16 @@ disassemble_section (bfd *abfd, asection *section, void *inf) } /* We are not currently printing. Check to see - if the current symbol matches the requested symbol. */ - if (streq (name, paux->symbol) + if the current symbol matches any of the requested symbols. */ + for (const struct symbol_entry *ent = paux->symbol_list; + ent; + ent = ent->next) + if (streq (name, ent->name)) + { + do_print = true; + break; + } + if (do_print && bfd_asymbol_value (sym) <= addr) { do_print = true; @@ -4174,7 +4188,7 @@ disassemble_data (bfd *abfd) disasm_info.dynrelbuf = NULL; disasm_info.dynrelcount = 0; aux.reloc = NULL; - aux.symbol = disasm_sym; + aux.symbol_list = disasm_sym_list; disasm_info.print_address_func = objdump_print_address; disasm_info.symbol_at_address_func = objdump_symbol_at_address; @@ -4192,12 +4206,12 @@ disassemble_data (bfd *abfd) abfd->arch_info = inf; } + const struct bfd_target *old_xvec = NULL; if (endian != BFD_ENDIAN_UNKNOWN) { - struct bfd_target *xvec; - - xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target)); - memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); + struct bfd_target *xvec = xmalloc (sizeof (*xvec)); + old_xvec = abfd->xvec; + memcpy (xvec, old_xvec, sizeof (*xvec)); xvec->byteorder = endian; abfd->xvec = xvec; } @@ -4211,8 +4225,7 @@ disassemble_data (bfd *abfd) non_fatal (_("can't disassemble for architecture %s\n"), bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); exit_status = 1; - free (sorted_syms); - return; + goto out; } disasm_info.flavour = bfd_get_flavour (abfd); @@ -4266,8 +4279,15 @@ disassemble_data (bfd *abfd) free (disasm_info.dynrelbuf); disasm_info.dynrelbuf = NULL; - free (sorted_syms); disassemble_free_target (&disasm_info); + out: + free (sorted_syms); + sorted_syms = NULL; + if (old_xvec) + { + free ((void *) abfd->xvec); + abfd->xvec = old_xvec; + } } static bool @@ -4940,7 +4960,10 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name, printf (_("Contents of CTF section %s:\n"), sanitize_string (sect_name)); while ((fp = ctf_archive_next (ctfa, &i, &name, 0, &err)) != NULL) - dump_ctf_archive_member (fp, name, parent, member++); + { + dump_ctf_archive_member (fp, name, parent, member++); + ctf_dict_close (fp); + } if (err != ECTF_NEXT_END) { dump_ctf_errs (NULL); @@ -4964,44 +4987,20 @@ dump_ctf (bfd *abfd ATTRIBUTE_UNUSED, const char *sect_name ATTRIBUTE_UNUSED, #endif static void -dump_section_sframe (bfd *abfd ATTRIBUTE_UNUSED, - const char * sect_name) -{ - asection *sec; - sframe_decoder_ctx *sfd_ctx = NULL; - bfd_size_type sf_size; - bfd_byte *sframe_data; - bfd_vma sf_vma; - int err = 0; - - if (sect_name == NULL) - sect_name = ".sframe"; - - sec = read_section (abfd, sect_name, &sframe_data); - if (sec == NULL) - { - my_bfd_nonfatal (bfd_get_filename (abfd)); - return; - } - sf_size = bfd_section_size (sec); - sf_vma = bfd_section_vma (sec); +dump_sframe_section (bfd *abfd, const char *sect_name, bool is_mainfile) - /* Decode the contents of the section. */ - sfd_ctx = sframe_decode ((const char*)sframe_data, sf_size, &err); - if (!sfd_ctx) +{ + /* Error checking for user provided SFrame section name, if any. */ + if (sect_name) { - my_bfd_nonfatal (bfd_get_filename (abfd)); - free (sframe_data); - return; + asection *sec = bfd_get_section_by_name (abfd, sect_name); + if (sec == NULL) + { + printf (_("No %s section present\n\n"), sanitize_string (sect_name)); + return; + } } - - printf (_("Contents of the SFrame section %s:"), - sanitize_string (sect_name)); - /* Dump the contents as text. */ - dump_sframe (sfd_ctx, sf_vma); - - sframe_decoder_free (&sfd_ctx); - free (sframe_data); + dump_dwarf (abfd, is_mainfile); } @@ -5473,7 +5472,7 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) static void dump_relocs_in_section (bfd *abfd, asection *section, - void *dummy ATTRIBUTE_UNUSED) + void *counter) { arelent **relpp; long relcount; @@ -5522,41 +5521,71 @@ dump_relocs_in_section (bfd *abfd, printf ("\n\n"); } free (relpp); + + * ((unsigned int *) counter) += 1; +} + +static void +is_relr_section (bfd *abfd ATTRIBUTE_UNUSED, + asection * section, void *data) +{ + if (section->flags & SEC_LINKER_CREATED) + return; + + struct bfd_elf_section_data * esd = elf_section_data (section); + if (esd == NULL) + return; + + if (esd->this_hdr.sh_type == SHT_RELR) + * ((bool *) data) = true; +} + +static bool +contains_relr_relocs (bfd *abfd) +{ + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return false; + + bool result = false; + + bfd_map_over_sections (abfd, is_relr_section, &result); + + return result; } static void dump_relocs (bfd *abfd) { - bfd_map_over_sections (abfd, dump_relocs_in_section, NULL); + unsigned int counter = 0; + + bfd_map_over_sections (abfd, dump_relocs_in_section, & counter); + + if (counter == 0 && contains_relr_relocs (abfd)) + { + printf (_("%s: This file does not contain any ordinary relocations.\n"), + sanitize_string (bfd_get_filename (abfd))); + + printf (_("%s: It does however contain RELR relocations. These can be displayed by the readelf program\n"), + sanitize_string (bfd_get_filename (abfd))); + } } static void dump_dynamic_relocs (bfd *abfd) { long relsize; - arelent **relpp; + arelent **relpp = NULL; long relcount; relsize = bfd_get_dynamic_reloc_upper_bound (abfd); printf ("DYNAMIC RELOCATION RECORDS"); - if (relsize == 0) - { - printf (" (none)\n\n"); - return; - } + if (relsize <= 0) + goto none; - if (relsize < 0) - { - relpp = NULL; - relcount = relsize; - } - else - { - relpp = (arelent **) xmalloc (relsize); - relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); - } + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); if (relcount < 0) { @@ -5566,7 +5595,7 @@ dump_dynamic_relocs (bfd *abfd) my_bfd_nonfatal (_("error message was")); } else if (relcount == 0) - printf (" (none)\n\n"); + goto none; else { printf ("\n"); @@ -5574,6 +5603,18 @@ dump_dynamic_relocs (bfd *abfd) printf ("\n\n"); } free (relpp); + return; + + none: + printf (" (none)\n\n"); + + if (contains_relr_relocs (abfd)) + printf (_("%s: contains RELR relocations which are not displayed by %s.\n\ +These can be displayed by the readelf program instead.\n"), + sanitize_string (bfd_get_filename (abfd)), + program_name); + + free (relpp); } /* Creates a table of paths, to search for source files. */ @@ -5781,7 +5822,7 @@ dump_bfd (bfd *abfd, bool is_mainfile) dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name, dump_ctf_parent_section_name); if (dump_sframe_section_info) - dump_section_sframe (abfd, dump_sframe_section_name); + dump_sframe_section (abfd, dump_sframe_section_name, is_mainfile); if (dump_stab_section_info) dump_stabs (abfd); if (dump_reloc_info && ! disassemble) @@ -6183,7 +6224,14 @@ main (int argc, char **argv) case 'd': disassemble = true; seenflag = true; - disasm_sym = optarg; + if (optarg) + { + struct symbol_entry *sym = xmalloc (sizeof (*sym)); + + sym->name = optarg; + sym->next = disasm_sym_list; + disasm_sym_list = sym; + } break; case 'z': disassemble_zeroes = true; @@ -6238,7 +6286,9 @@ main (int argc, char **argv) seenflag = true; if (optarg) { - if (dwarf_select_sections_by_names (optarg)) + if (strcmp (optarg, "sframe-internal-only") == 0) + warn (_("Unrecognized debug option 'sframe-internal-only'\n")); + else if (dwarf_select_sections_by_names (optarg)) dump_dwarf_section_info = true; } else @@ -6279,8 +6329,15 @@ main (int argc, char **argv) #endif case OPTION_SFRAME: dump_sframe_section_info = true; + if (optarg) dump_sframe_section_name = xstrdup (optarg); + + /* Error checking for user-provided section name is done in + dump_sframe_section (). Initialize for now with the default + internal name: "sframe-internal-only". */ + dwarf_select_sections_by_names ("sframe-internal-only"); + seenflag = true; break; case 'G': |