X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fobjdump.c;h=3cc7aec1873763a783054e2ea98f65323db0d7bd;hb=eb7b504651ff7b44a7328cd967629d8f1d114a4b;hp=33d5d72d3d55d496b8f866a818d8004e68869c0e;hpb=a1c110a3fe02f5cb8de18137f6615005288e849e;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objdump.c b/binutils/objdump.c index 33d5d72d3d..3cc7aec187 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -147,7 +147,6 @@ static int include_path_count; struct objdump_disasm_info { bfd * abfd; - asection * sec; bfd_boolean require_sec; arelent ** dynrelbuf; long dynrelcount; @@ -264,7 +263,7 @@ usage (FILE *stream, int status) -w, --wide Format output for more than 80 columns\n\ -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\ --start-address=ADDR Only process data whose address is >= ADDR\n\ - --stop-address=ADDR Only process data whose address is <= ADDR\n\ + --stop-address=ADDR Only process data whose address is < ADDR\n\ --prefix-addresses Print complete address alongside disassembly\n\ --[no-]show-raw-insn Display hex alongside symbolic disassembly\n\ --insn-width=WIDTH Display WIDTH bytes on a single line for -d\n\ @@ -532,7 +531,7 @@ static void dump_section_header (bfd *abfd, asection *section, void *data) { char *comma = ""; - unsigned int opb = bfd_octets_per_byte (abfd); + unsigned int opb = bfd_octets_per_byte (abfd, section); int longest_section_name = *((int *) data); /* Ignore linker created section. See elfNN_ia64_object_p in @@ -545,13 +544,13 @@ dump_section_header (bfd *abfd, asection *section, void *data) return; printf ("%3d %-*s %08lx ", section->index, longest_section_name, - sanitize_string (bfd_get_section_name (abfd, section)), - (unsigned long) bfd_section_size (abfd, section) / opb); - bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section)); + sanitize_string (bfd_section_name (section)), + (unsigned long) bfd_section_size (section) / opb); + bfd_printf_vma (abfd, bfd_section_vma (section)); printf (" "); bfd_printf_vma (abfd, section->lma); printf (" %08lx 2**%u", (unsigned long) section->filepos, - bfd_get_section_alignment (abfd, section)); + bfd_section_alignment (section)); if (! wide_output) printf ("\n "); printf (" "); @@ -584,7 +583,10 @@ dump_section_header (bfd *abfd, asection *section, void *data) PF (SEC_COFF_NOREAD, "NOREAD"); } else if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - PF (SEC_ELF_PURECODE, "PURECODE"); + { + PF (SEC_ELF_OCTETS, "OCTETS"); + PF (SEC_ELF_PURECODE, "PURECODE"); + } PF (SEC_THREAD_LOCAL, "THREAD_LOCAL"); PF (SEC_GROUP, "GROUP"); if (bfd_get_arch (abfd) == bfd_arch_mep) @@ -631,7 +633,8 @@ dump_section_header (bfd *abfd, asection *section, void *data) DATA which contains the string length of the longest section name. */ static void -find_longest_section_name (bfd *abfd, asection *section, void *data) +find_longest_section_name (bfd *abfd ATTRIBUTE_UNUSED, + asection *section, void *data) { int *longest_so_far = (int *) data; const char *name; @@ -645,7 +648,7 @@ find_longest_section_name (bfd *abfd, asection *section, void *data) if (! process_section_p (section)) return; - name = bfd_get_section_name (abfd, section); + name = bfd_section_name (section); len = (int) strlen (name); if (len > *longest_so_far) *longest_so_far = len; @@ -800,6 +803,8 @@ remove_useless_symbols (asymbol **symbols, long count) return out_ptr - symbols; } +static const asection *compare_section; + /* Sort symbols into value order. */ static int @@ -811,8 +816,7 @@ compare_symbols (const void *ap, const void *bp) const char *bn; size_t anl; size_t bnl; - bfd_boolean af; - bfd_boolean bf; + bfd_boolean as, af, bs, bf; flagword aflags; flagword bflags; @@ -821,10 +825,16 @@ compare_symbols (const void *ap, const void *bp) else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) return -1; - if (a->section > b->section) - return 1; - else if (a->section < b->section) + /* 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; + if (as && !bs) return -1; + if (!as && bs) + return 1; an = bfd_asymbol_name (a); bn = bfd_asymbol_name (b); @@ -850,7 +860,8 @@ compare_symbols (const void *ap, const void *bp) #define file_symbol(s, sn, snl) \ (((s)->flags & BSF_FILE) != 0 \ - || ((sn)[(snl) - 2] == '.' \ + || ((snl) > 2 \ + && (sn)[(snl) - 2] == '.' \ && ((sn)[(snl) - 1] == 'o' \ || (sn)[(snl) - 1] == 'a'))) @@ -862,8 +873,8 @@ compare_symbols (const void *ap, const void *bp) if (! af && bf) return -1; - /* Try to sort global symbols before local symbols before function - symbols before debugging symbols. */ + /* Sort function and object symbols before global symbols before + local symbols before section symbols before debugging symbols. */ aflags = a->flags; bflags = b->flags; @@ -875,6 +886,13 @@ compare_symbols (const void *ap, const void *bp) else return -1; } + if ((aflags & BSF_SECTION_SYM) != (bflags & BSF_SECTION_SYM)) + { + if ((aflags & BSF_SECTION_SYM) != 0) + return 1; + else + return -1; + } if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION)) { if ((aflags & BSF_FUNCTION) != 0) @@ -882,6 +900,13 @@ compare_symbols (const void *ap, const void *bp) else return 1; } + if ((aflags & BSF_OBJECT) != (bflags & BSF_OBJECT)) + { + if ((aflags & BSF_OBJECT) != 0) + return -1; + else + return 1; + } if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) { if ((aflags & BSF_LOCAL) != 0) @@ -995,7 +1020,7 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf, if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0) version_string = bfd_get_symbol_version_string (abfd, sym, &hidden); - if (bfd_is_und_section (bfd_get_section (sym))) + if (bfd_is_und_section (bfd_asymbol_section (sym))) hidden = TRUE; name = sanitize_string (name); @@ -1034,8 +1059,8 @@ sym_ok (bfd_boolean want_section, 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 (abfd, sorted_syms[place]->section), - bfd_section_name (abfd, sec)) != 0) + if (strcmp (bfd_section_name (sorted_syms[place]->section), + bfd_section_name (sec)) != 0) return FALSE; } @@ -1074,7 +1099,7 @@ find_symbol_for_address (bfd_vma vma, aux = (struct objdump_disasm_info *) inf->application_data; abfd = aux->abfd; - sec = aux->sec; + sec = inf->section; opb = inf->octets_per_byte; /* Perform a binary search looking for the closest symbol to the @@ -1099,14 +1124,11 @@ find_symbol_for_address (bfd_vma vma, /* The symbol we want is now in min, the low end of the range we were searching. If there are several symbols with the same - value, we want the first (non-section/non-debugging) one. */ + value, we want the first one. */ thisplace = min; while (thisplace > 0 && (bfd_asymbol_value (sorted_syms[thisplace]) - == bfd_asymbol_value (sorted_syms[thisplace - 1])) - && ((sorted_syms[thisplace - 1]->flags - & (BSF_SECTION_SYM | BSF_DEBUGGING)) == 0) - ) + == bfd_asymbol_value (sorted_syms[thisplace - 1]))) --thisplace; /* Prefer a symbol in the current section if we have multple symbols @@ -1141,9 +1163,9 @@ find_symbol_for_address (bfd_vma vma, Also give the target a chance to reject symbols. */ want_section = (aux->require_sec || ((abfd->flags & HAS_RELOC) != 0 - && vma >= bfd_get_section_vma (abfd, sec) - && vma < (bfd_get_section_vma (abfd, sec) - + bfd_section_size (abfd, sec) / opb))); + && vma >= bfd_section_vma (sec) + && vma < (bfd_section_vma (sec) + + bfd_section_size (sec) / opb))); if (! sym_ok (want_section, abfd, thisplace, sec, inf)) { @@ -1267,8 +1289,8 @@ objdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym, bfd_vma secaddr; (*inf->fprintf_func) (inf->stream, " <%s", - sanitize_string (bfd_get_section_name (abfd, sec))); - secaddr = bfd_get_section_vma (abfd, sec); + sanitize_string (bfd_section_name (sec))); + secaddr = bfd_section_vma (sec); if (vma < secaddr) { (*inf->fprintf_func) (inf->stream, "-0x"); @@ -1338,7 +1360,8 @@ objdump_print_addr (bfd_vma vma, if (display_file_offsets) inf->fprintf_func (inf->stream, _(" (File Offset: 0x%lx)"), - (long int)(aux->sec->filepos + (vma - aux->sec->vma))); + (long int) (inf->section->filepos + + (vma - inf->section->vma))); return; } @@ -1351,14 +1374,14 @@ objdump_print_addr (bfd_vma vma, /* Adjust the vma to the reloc. */ vma += bfd_asymbol_value (sym); - if (bfd_is_und_section (bfd_get_section (sym))) + if (bfd_is_und_section (bfd_asymbol_section (sym))) skip_find = TRUE; } if (!skip_find) sym = find_symbol_for_address (vma, inf, NULL); - objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, inf, + objdump_print_addr_with_sym (aux->abfd, inf->section, sym, vma, inf, skip_zeroes); } @@ -1836,6 +1859,12 @@ objdump_sprintf (SFILE *f, const char *format, ...) #define DEFAULT_SKIP_ZEROES_AT_END 3 +static int +null_print (const void * stream ATTRIBUTE_UNUSED, const char * format ATTRIBUTE_UNUSED, ...) +{ + return 1; +} + /* Disassemble some data in memory between given values. */ static void @@ -1861,7 +1890,7 @@ disassemble_bytes (struct disassemble_info * inf, SFILE sfile; aux = (struct objdump_disasm_info *) inf->application_data; - section = aux->sec; + section = inf->section; sfile.alloc = 120; sfile.buffer = (char *) xmalloc (sfile.alloc); @@ -1903,10 +1932,7 @@ disassemble_bytes (struct disassemble_info * inf, { bfd_vma z; bfd_boolean need_nl = FALSE; - int previous_octets; - /* Remember the length of the previous instruction. */ - previous_octets = octets; octets = 0; /* Make sure we don't use relocs from previous instructions. */ @@ -1990,26 +2016,46 @@ disassemble_bytes (struct disassemble_info * inf, && *relppp < relppend) { bfd_signed_vma distance_to_rel; + int insn_size = 0; + int max_reloc_offset + = aux->abfd->arch_info->max_reloc_offset_into_insn; + + distance_to_rel = ((**relppp)->address - rel_offset + - addr_offset); - distance_to_rel = (**relppp)->address - - (rel_offset + addr_offset); + if (distance_to_rel > 0 + && (max_reloc_offset < 0 + || distance_to_rel <= max_reloc_offset)) + { + /* This reloc *might* apply to the current insn, + starting somewhere inside it. Discover the length + of the current insn so that the check below will + work. */ + if (insn_width) + insn_size = insn_width; + else + { + /* We find the length by calling the dissassembler + function with a dummy print handler. This should + work unless the disassembler is not expecting to + be called multiple times for the same address. + + This does mean disassembling the instruction + twice, but we only do this when there is a high + probability that there is a reloc that will + affect the instruction. */ + inf->fprintf_func = (fprintf_ftype) null_print; + insn_size = disassemble_fn (section->vma + + addr_offset, inf); + inf->fprintf_func = (fprintf_ftype) objdump_sprintf; + } + } /* Check to see if the current reloc is associated with the instruction that we are about to disassemble. */ if (distance_to_rel == 0 - /* FIXME: This is wrong. We are trying to catch - relocs that are addressed part way through the - current instruction, as might happen with a packed - VLIW instruction. Unfortunately we do not know the - length of the current instruction since we have not - disassembled it yet. Instead we take a guess based - upon the length of the previous instruction. The - proper solution is to have a new target-specific - disassembler function which just returns the length - of an instruction at a given address without trying - to display its disassembly. */ || (distance_to_rel > 0 - && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb))) + && distance_to_rel < insn_size / (int) opb)) { inf->flags |= INSN_HAS_RELOC; aux->reloc = **relppp; @@ -2211,8 +2257,8 @@ disassemble_bytes (struct disassemble_info * inf, { asection *sym_sec; - sym_sec = bfd_get_section (*q->sym_ptr_ptr); - sym_name = bfd_get_section_name (aux->abfd, sym_sec); + sym_sec = bfd_asymbol_section (*q->sym_ptr_ptr); + sym_name = bfd_section_name (sym_sec); if (sym_name == NULL || *sym_name == '\0') sym_name = "*unknown*"; printf ("%s", sanitize_string (sym_name)); @@ -2285,7 +2331,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf) if (! process_section_p (section)) return; - datasize = bfd_get_section_size (section); + datasize = bfd_section_size (section); if (datasize == 0) return; @@ -2357,12 +2403,15 @@ disassemble_section (bfd *abfd, asection *section, void *inf) return; } - paux->sec = section; pinfo->buffer = data; pinfo->buffer_vma = section->vma; pinfo->buffer_length = datasize; pinfo->section = section; + /* Sort the symbols into value and section order. */ + compare_section = section; + qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); + /* Skip over the relocs belonging to addresses below the start address. */ while (rel_pp < rel_ppend @@ -2515,7 +2564,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf) else { #define is_valid_next_sym(SYM) \ - (strcmp (bfd_section_name (abfd, (SYM)->section), bfd_section_name (abfd, section)) == 0 \ + (strcmp (bfd_section_name ((SYM)->section), bfd_section_name (section)) == 0 \ && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \ && pinfo->symbol_is_valid (SYM, pinfo)) @@ -2606,9 +2655,6 @@ disassemble_data (bfd *abfd) ++sorted_symcount; } - /* Sort the symbols into section and symbol order. */ - qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); - init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf); disasm_info.application_data = (void *) &aux; @@ -2658,7 +2704,7 @@ disassemble_data (bfd *abfd) disasm_info.arch = bfd_get_arch (abfd); disasm_info.mach = bfd_get_mach (abfd); disasm_info.disassembler_options = disassembler_options; - disasm_info.octets_per_byte = bfd_octets_per_byte (abfd); + disasm_info.octets_per_byte = bfd_octets_per_byte (abfd, NULL); disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES; disasm_info.skip_zeroes_at_end = DEFAULT_SKIP_ZEROES_AT_END; disasm_info.disassembler_needs_relocs = FALSE; @@ -2704,6 +2750,7 @@ disassemble_data (bfd *abfd) if (aux.dynrelbuf != NULL) free (aux.dynrelbuf); free (sorted_syms); + disassemble_free_target (&disasm_info); } static bfd_boolean @@ -2727,9 +2774,9 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->filename = bfd_get_filename (abfd); section->reloc_info = NULL; section->num_relocs = 0; - section->address = bfd_get_section_vma (abfd, sec); + section->address = bfd_section_vma (sec); section->user_data = sec; - section->size = bfd_get_section_size (sec); + section->size = bfd_section_size (sec); /* PR 24360: On 32-bit hosts sizeof (size_t) < sizeof (bfd_size_type). */ alloced = amt = section->size + 1; if (alloced != amt || alloced == 0) @@ -2902,7 +2949,7 @@ static void dump_dwarf_section (bfd *abfd, asection *section, void *arg ATTRIBUTE_UNUSED) { - const char *name = bfd_get_section_name (abfd, section); + const char *name = bfd_section_name (section); const char *match; int i; @@ -2948,44 +2995,8 @@ dump_dwarf (bfd *abfd) return; } - eh_addr_size = bfd_arch_bits_per_address (abfd) / 8; - switch (bfd_get_arch (abfd)) { - case bfd_arch_i386: - switch (bfd_get_mach (abfd)) - { - case bfd_mach_x86_64: - case bfd_mach_x86_64_intel_syntax: - case bfd_mach_x86_64_nacl: - case bfd_mach_x64_32: - case bfd_mach_x64_32_intel_syntax: - case bfd_mach_x64_32_nacl: - init_dwarf_regnames_x86_64 (); - break; - - default: - init_dwarf_regnames_i386 (); - break; - } - break; - - case bfd_arch_iamcu: - init_dwarf_regnames_iamcu (); - break; - - case bfd_arch_aarch64: - init_dwarf_regnames_aarch64(); - break; - - case bfd_arch_s390: - 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. */ @@ -2993,9 +3004,13 @@ dump_dwarf (bfd *abfd) break; default: + eh_addr_size = bfd_arch_bits_per_address (abfd) / 8; break; } + init_dwarf_regnames_by_bfd_arch_and_mach (bfd_get_arch (abfd), + bfd_get_mach (abfd)); + bfd_map_over_sections (abfd, dump_dwarf_section, NULL); } @@ -3027,7 +3042,7 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr, return NULL; } - *size_ptr = bfd_section_size (abfd, stabsect); + *size_ptr = bfd_section_size (stabsect); if (entsize_ptr) *entsize_ptr = stabsect->entsize; @@ -3258,19 +3273,27 @@ static int dump_ctf_archive_member (ctf_file_t *ctf, const char *name, void *arg) { ctf_file_t *parent = (ctf_file_t *) arg; - const char *things[] = {"Labels", "Data objects", "Function objects", - "Variables", "Types", "Strings", ""}; + const char *things[] = {"Header", "Labels", "Data objects", + "Function objects", "Variables", "Types", "Strings", + ""}; const char **thing; size_t i; /* Only print out the name of non-default-named archive members. The name .ctf appears everywhere, even for things that aren't - really archives, so printing it out is liable to be confusing. */ + really archives, so printing it out is liable to be confusing. + + The parent, if there is one, is the default-owned archive member: + avoid importing it into itself. (This does no harm, but looks + confusing.) */ + if (strcmp (name, ".ctf") != 0) - printf (_("\nCTF archive member: %s:\n"), sanitize_string (name)); + { + printf (_("\nCTF archive member: %s:\n"), sanitize_string (name)); + ctf_import (ctf, parent); + } - ctf_import (ctf, parent); - for (i = 1, thing = things; *thing[0]; thing++, i++) + for (i = 0, thing = things; *thing[0]; thing++, i++) { ctf_dump_state_t *s = NULL; char *item; @@ -3298,7 +3321,7 @@ dump_ctf_archive_member (ctf_file_t *ctf, const char *name, void *arg) static void dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name) { - ctf_archive_t *ctfa, *parenta = NULL; + ctf_archive_t *ctfa, *parenta = NULL, *lookparent; bfd_byte *ctfdata, *parentdata = NULL; bfd_size_type ctfsize, parentsize; ctf_sect_t ctfsect; @@ -3331,14 +3354,18 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name) bfd_fatal (bfd_get_filename (abfd)); } - /* Assume that the applicable parent archive member is the default one. - (This is what all known implementations are expected to do, if they - put CTFs and their parents in archives together.) */ - if ((parent = ctf_arc_open_by_name (parenta, NULL, &err)) == NULL) - { - non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err)); - bfd_fatal (bfd_get_filename (abfd)); - } + lookparent = parenta; + } + else + lookparent = ctfa; + + /* Assume that the applicable parent archive member is the default one. + (This is what all known implementations are expected to do, if they + put CTFs and their parents in archives together.) */ + if ((parent = ctf_arc_open_by_name (lookparent, NULL, &err)) == NULL) + { + non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err)); + bfd_fatal (bfd_get_filename (abfd)); } printf (_("Contents of CTF section %s:\n"), sanitize_string (sect_name)); @@ -3423,7 +3450,7 @@ dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) bfd_vma addr_offset; bfd_vma start_offset; bfd_vma stop_offset; - unsigned int opb = bfd_octets_per_byte (abfd); + unsigned int opb = bfd_octets_per_byte (abfd, section); /* Bytes per line. */ const int onaline = 16; char buf[64]; @@ -3436,7 +3463,7 @@ dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) if (! process_section_p (section)) return; - if ((datasize = bfd_section_size (abfd, section)) == 0) + if ((datasize = bfd_section_size (section)) == 0) return; /* Compute the address range to display. */ @@ -4512,11 +4539,11 @@ main (int argc, char **argv) case OPTION_DWARF_CHECK: dwarf_check = TRUE; break; - case OPTION_CTF: - dump_ctf_section_info = TRUE; - dump_ctf_section_name = xstrdup (optarg); - seenflag = TRUE; - break; + case OPTION_CTF: + dump_ctf_section_info = TRUE; + dump_ctf_section_name = xstrdup (optarg); + seenflag = TRUE; + break; case OPTION_CTF_PARENT: dump_ctf_parent_name = xstrdup (optarg); break;