X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fobjdump.c;h=f468fcdb59907a2ddb149b88f619e67f490f127d;hb=3391569f218cd5d05e96769f47559d5828be3acd;hp=f61968b9d5c4c3f58cfdabb05fdf80d539b51012;hpb=2571583aed598dd3f9651b53434e5f177a0e3cf7;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objdump.c b/binutils/objdump.c index f61968b9d5..f468fcdb59 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -1,5 +1,5 @@ /* 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. @@ -117,6 +117,7 @@ static bfd_boolean display_file_offsets;/* -F */ static const char *prefix; /* --prefix */ static int prefix_strip; /* --prefix-strip */ static size_t prefix_length; +static bfd_boolean unwind_inlines; /* --inlines. */ /* A structure to record the sections mentioned in -j switches. */ struct only @@ -180,7 +181,7 @@ static long dynsymcount = 0; static bfd_byte *stabs; static bfd_size_type stab_size; -static char *strtab; +static bfd_byte *strtab; static bfd_size_type stabstr_size; static bfd_boolean is_relocatable = FALSE; @@ -213,11 +214,11 @@ usage (FILE *stream, int status) -g, --debugging Display debug information in object file\n\ -e, --debugging-tags Display debug information using ctags style\n\ -G, --stabs Display (in raw form) any STABS info in the file\n\ - -W[lLiaprmfFsoRt] or\n\ + -W[lLiaprmfFsoRtUuTgAckK] or\n\ --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,\n\ =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\ =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,\n\ - =addr,=cu_index]\n\ + =addr,=cu_index,=links,=follow-links]\n\ Display DWARF info in the file\n\ -t, --syms Display the contents of the symbol table(s)\n\ -T, --dynamic-syms Display the contents of the dynamic symbol table\n\ @@ -257,6 +258,7 @@ usage (FILE *stream, int status) --insn-width=WIDTH Display WIDTH bytes on a single line for -d\n\ --adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\ --special-syms Include special symbols in symbol dumps\n\ + --inlines Print all inlines for source line (with -l)\n\ --prefix=PREFIX Add PREFIX to absolute paths for -S\n\ --prefix-strip=LEVEL Strip initial directory names for -S\n")); fprintf (stream, _("\ @@ -296,7 +298,8 @@ enum option_values OPTION_ADJUST_VMA, OPTION_DWARF_DEPTH, OPTION_DWARF_CHECK, - OPTION_DWARF_START + OPTION_DWARF_START, + OPTION_INLINES }; static struct option long_options[]= @@ -345,9 +348,10 @@ static struct option long_options[]= {"prefix", required_argument, NULL, OPTION_PREFIX}, {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP}, {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH}, - {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH}, - {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, - {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, + {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH}, + {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, + {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, + {"inlines", no_argument, 0, OPTION_INLINES}, {0, no_argument, 0, 0} }; @@ -438,11 +442,11 @@ free_only_list (void) static void -dump_section_header (bfd *abfd, asection *section, - void *ignored ATTRIBUTE_UNUSED) +dump_section_header (bfd *abfd, asection *section, void *data) { char *comma = ""; unsigned int opb = bfd_octets_per_byte (abfd); + int longest_section_name = *((int *) data); /* Ignore linker created section. See elfNN_ia64_object_p in bfd/elfxx-ia64.c. */ @@ -453,7 +457,7 @@ dump_section_header (bfd *abfd, asection *section, if (! process_section_p (section)) return; - printf ("%3d %-13s %08lx ", section->index, + printf ("%3d %-*s %08lx ", section->index, longest_section_name, bfd_get_section_name (abfd, section), (unsigned long) bfd_section_size (abfd, section) / opb); bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section)); @@ -536,26 +540,64 @@ dump_section_header (bfd *abfd, asection *section, #undef PF } +/* Called on each SECTION in ABFD, update the int variable pointed to by + DATA which contains the string length of the longest section name. */ + +static void +find_longest_section_name (bfd *abfd, asection *section, void *data) +{ + int *longest_so_far = (int *) data; + const char *name; + int len; + + /* Ignore linker created section. */ + if (section->flags & SEC_LINKER_CREATED) + return; + + /* Skip sections that we are ignoring. */ + if (! process_section_p (section)) + return; + + name = bfd_get_section_name (abfd, section); + len = (int) strlen (name); + if (len > *longest_so_far) + *longest_so_far = len; +} + static void dump_headers (bfd *abfd) { - printf (_("Sections:\n")); + /* The default width of 13 is just an arbitrary choice. */ + int max_section_name_length = 13; + int bfd_vma_width; #ifndef BFD64 - printf (_("Idx Name Size VMA LMA File off Algn")); + bfd_vma_width = 10; #else /* With BFD64, non-ELF returns -1 and wants always 64 bit addresses. */ if (bfd_get_arch_size (abfd) == 32) - printf (_("Idx Name Size VMA LMA File off Algn")); + bfd_vma_width = 10; else - printf (_("Idx Name Size VMA LMA File off Algn")); + bfd_vma_width = 18; #endif + printf (_("Sections:\n")); + + if (wide_output) + bfd_map_over_sections (abfd, find_longest_section_name, + &max_section_name_length); + + printf (_("Idx %-*s Size %-*s%-*sFile off Algn"), + max_section_name_length, "Name", + bfd_vma_width, "VMA", + bfd_vma_width, "LMA"); + if (wide_output) printf (_(" Flags")); printf ("\n"); - bfd_map_over_sections (abfd, dump_section_header, NULL); + bfd_map_over_sections (abfd, dump_section_header, + &max_section_name_length); } static asymbol ** @@ -622,9 +664,7 @@ slurp_dynamic_symtab (bfd *abfd) 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. @@ -757,10 +797,10 @@ compare_symbols (const void *ap, const void *bp) bfd_vma asz, bsz; asz = 0; - if ((a->flags & BSF_SYNTHETIC) == 0) + if ((a->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0) asz = ((elf_symbol_type *) a)->internal_elf_sym.st_size; bsz = 0; - if ((b->flags & BSF_SYNTHETIC) == 0) + if ((b->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0) bsz = ((elf_symbol_type *) b)->internal_elf_sym.st_size; if (asz != bsz) return asz > bsz ? -1 : 1; @@ -846,7 +886,7 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf, name = alloc; } - if ((sym->flags & BSF_SYNTHETIC) == 0) + 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))) @@ -895,6 +935,7 @@ find_symbol_for_address (bfd_vma vma, asection *sec; unsigned int opb; bfd_boolean want_section; + long rel_count; if (sorted_symcount < 1) return NULL; @@ -1023,33 +1064,57 @@ find_symbol_for_address (bfd_vma vma, 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; } } @@ -1225,24 +1290,23 @@ static struct print_file_list *print_files; /* Read a complete file into memory. */ static const char * -slurp_file (const char *fn, size_t *size) +slurp_file (const char *fn, size_t *size, struct stat *fst) { #ifdef HAVE_MMAP int ps = getpagesize (); size_t msize; #endif const char *map; - struct stat st; int fd = open (fn, O_RDONLY | O_BINARY); if (fd < 0) return NULL; - if (fstat (fd, &st) < 0) + if (fstat (fd, fst) < 0) { close (fd); return NULL; } - *size = st.st_size; + *size = fst->st_size; #ifdef HAVE_MMAP msize = (*size + ps - 1) & ~(ps - 1); map = mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0); @@ -1322,13 +1386,13 @@ index_file (const char *map, size_t size, unsigned int *maxline) linked list and returns that node. Returns NULL on failure. */ static struct print_file_list * -try_print_file_open (const char *origname, const char *modname) +try_print_file_open (const char *origname, const char *modname, struct stat *fst) { struct print_file_list *p; p = (struct print_file_list *) xmalloc (sizeof (struct print_file_list)); - p->map = slurp_file (modname, &p->mapsize); + p->map = slurp_file (modname, &p->mapsize, fst); if (p->map == NULL) { free (p); @@ -1351,36 +1415,47 @@ try_print_file_open (const char *origname, const char *modname) If found, add location to print_files linked list. */ static struct print_file_list * -update_source_path (const char *filename) +update_source_path (const char *filename, bfd *abfd) { struct print_file_list *p; const char *fname; + struct stat fst; int i; - p = try_print_file_open (filename, filename); - if (p != NULL) - return p; + p = try_print_file_open (filename, filename, &fst); + if (p == NULL) + { + if (include_path_count == 0) + return NULL; - if (include_path_count == 0) - return NULL; + /* Get the name of the file. */ + fname = lbasename (filename); - /* Get the name of the file. */ - fname = lbasename (filename); + /* If file exists under a new path, we need to add it to the list + so that show_line knows about it. */ + for (i = 0; i < include_path_count; i++) + { + char *modname = concat (include_paths[i], "/", fname, + (const char *) 0); - /* If file exists under a new path, we need to add it to the list - so that show_line knows about it. */ - for (i = 0; i < include_path_count; i++) - { - char *modname = concat (include_paths[i], "/", fname, (const char *) 0); + p = try_print_file_open (filename, modname, &fst); + if (p) + break; - p = try_print_file_open (filename, modname); - if (p) - return p; + free (modname); + } + } + + if (p != NULL) + { + long mtime = bfd_get_mtime (abfd); - free (modname); + if (fst.st_mtime > mtime) + warn (_("source file %s is more recent than object file\n"), + filename); } - return NULL; + return p; } /* Print a source file line. */ @@ -1432,8 +1507,8 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) return; if (! bfd_find_nearest_line_discriminator (abfd, section, syms, addr_offset, - &filename, &functionname, - &linenumber, &discriminator)) + &filename, &functionname, + &linenumber, &discriminator)) return; if (filename != NULL && *filename == '\0') @@ -1485,16 +1560,33 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) if (functionname != NULL && (prev_functionname == NULL || strcmp (functionname, prev_functionname) != 0)) - printf ("%s():\n", functionname); - if (linenumber > 0 && (linenumber != prev_line || - (discriminator != prev_discriminator))) - { - if (discriminator > 0) - printf ("%s:%u (discriminator %u)\n", filename == NULL ? "???" : filename, - linenumber, discriminator); - else - printf ("%s:%u\n", filename == NULL ? "???" : filename, linenumber); - } + { + printf ("%s():\n", functionname); + prev_line = -1; + } + if (linenumber > 0 + && (linenumber != prev_line + || discriminator != prev_discriminator)) + { + if (discriminator > 0) + printf ("%s:%u (discriminator %u)\n", + filename == NULL ? "???" : filename, + linenumber, discriminator); + else + printf ("%s:%u\n", filename == NULL ? "???" : filename, + linenumber); + } + if (unwind_inlines) + { + const char *filename2; + const char *functionname2; + unsigned line2; + + while (bfd_find_inliner_info (abfd, &filename2, &functionname2, + &line2)) + printf ("inlined by %s:%u (%s)\n", filename2, line2, + functionname2); + } } if (with_source_code @@ -1513,7 +1605,7 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) { if (reloc) filename = xstrdup (filename); - p = update_source_path (filename); + p = update_source_path (filename, abfd); } if (p != NULL && linenumber != p->last_line) @@ -1855,20 +1947,23 @@ disassemble_bytes (struct disassemble_info * inf, for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc) { - int k; - - if (bpc > 1 && inf->display_endian == BFD_ENDIAN_LITTLE) + /* PR 21580: Check for a buffer ending early. */ + if (j + bpc <= stop_offset * opb) { - for (k = bpc - 1; k >= 0; k--) - printf ("%02x", (unsigned) data[j + k]); - putchar (' '); - } - else - { - for (k = 0; k < bpc; k++) - printf ("%02x", (unsigned) data[j + k]); - putchar (' '); + int k; + + if (inf->display_endian == BFD_ENDIAN_LITTLE) + { + for (k = bpc - 1; k >= 0; k--) + printf ("%02x", (unsigned) data[j + k]); + } + else + { + for (k = 0; k < bpc; k++) + printf ("%02x", (unsigned) data[j + k]); + } } + putchar (' '); } for (; pb < octets_per_line; pb += bpc) @@ -1916,20 +2011,23 @@ disassemble_bytes (struct disassemble_info * inf, pb = octets; for (; j < addr_offset * opb + pb; j += bpc) { - int k; - - if (bpc > 1 && inf->display_endian == BFD_ENDIAN_LITTLE) + /* PR 21619: Check for a buffer ending early. */ + if (j + bpc <= stop_offset * opb) { - for (k = bpc - 1; k >= 0; k--) - printf ("%02x", (unsigned) data[j + k]); - putchar (' '); - } - else - { - for (k = 0; k < bpc; k++) - printf ("%02x", (unsigned) data[j + k]); - putchar (' '); + int k; + + if (inf->display_endian == BFD_ENDIAN_LITTLE) + { + for (k = bpc - 1; k >= 0; k--) + printf ("%02x", (unsigned) data[j + k]); + } + else + { + for (k = 0; k < bpc; k++) + printf ("%02x", (unsigned) data[j + k]); + } } + putchar (' '); } } } @@ -2109,9 +2207,12 @@ disassemble_section (bfd *abfd, asection *section, void *inf) } rel_ppend = rel_pp + rel_count; - data = (bfd_byte *) xmalloc (datasize); - - bfd_get_section_contents (abfd, section, data, 0, datasize); + if (!bfd_malloc_and_get_section (abfd, section, &data)) + { + non_fatal (_("Reading section %s failed because: %s"), + section->name, bfd_errmsg (bfd_get_error ())); + return; + } paux->sec = section; pinfo->buffer = data; @@ -2318,7 +2419,9 @@ disassemble_data (bfd *abfd) } /* Use libopcodes to locate a suitable disassembler. */ - aux.disassemble_fn = disassembler (abfd); + aux.disassemble_fn = disassembler (bfd_get_arch (abfd), + bfd_big_endian (abfd), + bfd_get_mach (abfd), abfd); if (!aux.disassemble_fn) { non_fatal (_("can't disassemble for architecture %s\n"), @@ -2379,36 +2482,48 @@ disassemble_data (bfd *abfd) free (sorted_syms); } -static int +static bfd_boolean load_specific_debug_section (enum dwarf_section_display_enum debug, asection *sec, void *file) { struct dwarf_section *section = &debug_displays [debug].section; bfd *abfd = (bfd *) file; - bfd_boolean ret; + bfd_byte *contents; + bfd_size_type amt; - /* If it is already loaded, do nothing. */ if (section->start != NULL) - return 1; + { + /* If it is already loaded, do nothing. */ + if (streq (section->filename, bfd_get_filename (abfd))) + return TRUE; + free (section->start); + } + section->filename = bfd_get_filename (abfd); section->reloc_info = NULL; section->num_relocs = 0; section->address = bfd_get_section_vma (abfd, sec); section->size = bfd_get_section_size (sec); - section->start = NULL; + amt = section->size + 1; + section->start = contents = malloc (amt); section->user_data = sec; - ret = bfd_get_full_section_contents (abfd, sec, §ion->start); - - if (! ret) + if (amt == 0 + || section->start == NULL + || !bfd_get_full_section_contents (abfd, sec, &contents)) { free_debug_section (debug); printf (_("\nCan't get contents for section '%s'.\n"), section->name); - return 0; + return FALSE; } + /* Ensure any string section has a terminating NUL. */ + section->start[section->size] = 0; if (is_relocatable && debug_displays [debug].relocate) { + long reloc_size; + bfd_boolean ret; + bfd_cache_section_contents (sec, section->start); ret = bfd_simple_get_relocated_section_contents (abfd, @@ -2421,11 +2536,9 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, free_debug_section (debug); printf (_("\nCan't get contents for section '%s'.\n"), section->name); - return 0; + return FALSE; } - long reloc_size; - reloc_size = bfd_get_reloc_upper_bound (abfd, sec); if (reloc_size > 0) { @@ -2445,7 +2558,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, } } - return 1; + return TRUE; } bfd_boolean @@ -2466,7 +2579,7 @@ reloc_at (struct dwarf_section * dsec, dwarf_vma offset) return FALSE; } -int +bfd_boolean load_debug_section (enum dwarf_section_display_enum debug, void *file) { struct dwarf_section *section = &debug_displays [debug].section; @@ -2475,7 +2588,10 @@ load_debug_section (enum dwarf_section_display_enum debug, void *file) /* If it is already loaded, do nothing. */ if (section->start != NULL) - return 1; + { + if (streq (section->filename, bfd_get_filename (abfd))) + return TRUE; + } /* Locate the debug section. */ sec = bfd_get_section_by_name (abfd, section->uncompressed_name); @@ -2488,7 +2604,7 @@ load_debug_section (enum dwarf_section_display_enum debug, void *file) section->name = section->compressed_name; } if (sec == NULL) - return 0; + return FALSE; return load_specific_debug_section (debug, sec, file); } @@ -2524,6 +2640,29 @@ free_debug_section (enum dwarf_section_display_enum debug) section->size = 0; } +void +close_debug_file (void * file) +{ + bfd * abfd = (bfd *) file; + + bfd_close (abfd); +} + +void * +open_debug_file (const char * pathname) +{ + bfd * data; + + data = bfd_openr (pathname, NULL); + if (data == NULL) + return NULL; + + if (! bfd_check_format (data, bfd_object)) + return NULL; + + return data; +} + static void dump_dwarf_section (bfd *abfd, asection *section, void *arg ATTRIBUTE_UNUSED) @@ -2566,6 +2705,8 @@ dump_dwarf_section (bfd *abfd, asection *section, static void dump_dwarf (bfd *abfd) { + bfd * separates; + is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0; eh_addr_size = bfd_arch_bits_per_address (abfd) / 8; @@ -2614,24 +2755,32 @@ dump_dwarf (bfd *abfd) init_dwarf_regnames_s390 (); break; + case bfd_arch_riscv: + init_dwarf_regnames_riscv (); + break; + default: break; } + separates = load_separate_debug_file (abfd, bfd_get_filename (abfd)); + bfd_map_over_sections (abfd, dump_dwarf_section, NULL); + if (separates) + bfd_map_over_sections (separates, dump_dwarf_section, NULL); + free_debug_memory (); } /* Read ABFD's stabs section STABSECT_NAME, and return a pointer to it. Return NULL on failure. */ -static char * +static bfd_byte * read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) { asection *stabsect; - bfd_size_type size; - char *contents; + bfd_byte *contents; stabsect = bfd_get_section_by_name (abfd, sect_name); if (stabsect == NULL) @@ -2640,10 +2789,7 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) return FALSE; } - size = bfd_section_size (abfd, stabsect); - contents = (char *) xmalloc (size); - - if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size)) + if (!bfd_malloc_and_get_section (abfd, stabsect, &contents)) { non_fatal (_("reading %s section of %s failed: %s"), sect_name, bfd_get_filename (abfd), @@ -2653,7 +2799,7 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) return NULL; } - *size_ptr = size; + *size_ptr = bfd_section_size (abfd, stabsect); return contents; } @@ -2780,8 +2926,7 @@ find_stabs_section (bfd *abfd, asection *section, void *names) if (strtab) { - stabs = (bfd_byte *) read_section_stabs (abfd, section->name, - &stab_size); + stabs = read_section_stabs (abfd, section->name, &stab_size); if (stabs) print_section_stabs (abfd, section->name, &sought->string_offset); } @@ -2909,7 +3054,7 @@ dump_target_specific (bfd *abfd) static void dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) { - bfd_byte *data = 0; + bfd_byte *data = NULL; bfd_size_type datasize; bfd_vma addr_offset; bfd_vma start_offset; @@ -3311,6 +3456,23 @@ dump_relocs_in_section (bfd *abfd, return; } + if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0 + && (((ufile_ptr) relsize > 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); + bfd_set_error (bfd_error_file_truncated); + bfd_fatal (bfd_get_filename (abfd)); + } + relpp = (arelent **) xmalloc (relsize); relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); @@ -3420,7 +3582,7 @@ dump_bfd (bfd *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) @@ -3484,8 +3646,8 @@ dump_bfd (bfd *abfd) 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 (); @@ -3616,7 +3778,7 @@ display_any_bfd (bfd *file, int level) } static void -display_file (char *filename, char *target) +display_file (char *filename, char *target, bfd_boolean last_file) { bfd *file; @@ -3635,7 +3797,18 @@ display_file (char *filename, char *target) display_any_bfd (file, 0); - bfd_close (file); + /* This is an optimization to improve the speed of objdump, especially when + dumping a file with lots of associated debug informatiom. Calling + bfd_close on such a file can take a non-trivial amount of time as there + are lots of lists to walk and buffers to free. This is only really + necessary however if we are about to load another file and we need the + memory back. Otherwise, if we are about to exit, then we can save (a lot + of) time by only doing a quick close, and allowing the OS to reclaim the + memory for us. */ + if (! last_file) + bfd_close (file); + else + bfd_close_all_done (file); } int @@ -3679,12 +3852,16 @@ main (int argc, char **argv) machine = optarg; break; case 'M': - if (disassembler_options) - /* Ignore potential memory leak for now. */ - disassembler_options = concat (disassembler_options, ",", - optarg, (const char *) NULL); - else - disassembler_options = optarg; + { + char *options; + if (disassembler_options) + /* Ignore potential memory leak for now. */ + options = concat (disassembler_options, ",", + optarg, (const char *) NULL); + else + options = optarg; + disassembler_options = remove_whitespace_and_extra_commas (options); + } break; case 'j': add_only (optarg); @@ -3713,7 +3890,7 @@ main (int argc, char **argv) } break; case 'w': - wide_output = TRUE; + do_wide = wide_output = TRUE; break; case OPTION_ADJUST_VMA: adjust_section_vma = parse_vma (optarg, "--adjust-vma"); @@ -3745,6 +3922,9 @@ main (int argc, char **argv) if (insn_width <= 0) fatal (_("error: instruction width must be positive")); break; + case OPTION_INLINES: + unwind_inlines = TRUE; + break; case 'E': if (strcmp (optarg, "B") == 0) endian = BFD_ENDIAN_BIG; @@ -3913,10 +4093,13 @@ main (int argc, char **argv) else { if (optind == argc) - display_file ("a.out", target); + display_file ("a.out", target, TRUE); else for (; optind < argc;) - display_file (argv[optind++], target); + { + display_file (argv[optind], target, optind == argc - 1); + optind++; + } } free_only_list ();