X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fobjdump.c;h=9164d83f700cdc415ae7f3024ad81a96906285a8;hb=8f7adb5a6c563a1111e869da758433aa0e0f280d;hp=b05c384717abae5fd7173d8040ccfae6e64fd9e5;hpb=4cb93e3bbe07704a803fa04e562bcd822764d1af;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objdump.c b/binutils/objdump.c index b05c384717..9164d83f70 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -1,7 +1,7 @@ /* objdump.c -- dump information about an object file. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -55,6 +55,7 @@ #include "elf-bfd.h" #include "progress.h" #include "bucomm.h" +#include "elfcomm.h" #include "dwarf.h" #include "getopt.h" #include "safe-ctype.h" @@ -64,13 +65,12 @@ #include "filenames.h" #include "debug.h" #include "budbg.h" +#include "objdump.h" #ifdef HAVE_MMAP #include #endif -#include - /* Internal headers for the ELF .stab-dump code - sorry. */ #define BYTES_IN_WORD 32 #include "aout/aout64.h" @@ -92,6 +92,7 @@ static int dump_reloc_info; /* -r */ static int dump_dynamic_reloc_info; /* -R */ static int dump_ar_hdrs; /* -a */ static int dump_private_headers; /* -p */ +static char *dump_private_options; /* -P */ static int prefix_addresses; /* --prefix-addresses */ static int with_line_numbers; /* -l */ static bfd_boolean with_source_code; /* -S */ @@ -104,10 +105,12 @@ static bfd_boolean disassemble_all; /* -D */ static int disassemble_zeroes; /* --disassemble-zeroes */ static bfd_boolean formats_info; /* -i */ static int wide_output; /* -w */ +static int insn_width; /* --insn-width */ static bfd_vma start_address = (bfd_vma) -1; /* --start-address */ static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ static int dump_debugging; /* --debugging */ static int dump_debugging_tags; /* --debugging-tags */ +static int suppress_bfd_header; static int dump_special_syms = 0; /* --special-syms */ static bfd_vma adjust_section_vma = 0; /* --adjust-vma */ static int file_start_context = 0; /* --file-start-context */ @@ -116,13 +119,16 @@ static const char *prefix; /* --prefix */ static int prefix_strip; /* --prefix-strip */ static size_t prefix_length; -/* Pointer to an array of section names provided by - one or more "-j secname" command line options. */ -static char **only; -/* The total number of slots in the only[] array. */ -static size_t only_size = 0; -/* The number of occupied slots in the only[] array. */ -static size_t only_used = 0; +/* A structure to record the sections mentioned in -j switches. */ +struct only +{ + const char * name; /* The name of the section. */ + bfd_boolean seen; /* A flag to indicate that the section has been found in one or more input files. */ + struct only * next; /* Pointer to the next structure in the list. */ +}; +/* Pointer to an array of 'only' structures. + This pointer is NULL if the -j switch has not been used. */ +static struct only * only_list = NULL; /* Variables for handling include file path table. */ static const char **include_paths; @@ -179,6 +185,13 @@ static char *strtab; static bfd_size_type stabstr_size; static bfd_boolean is_relocatable = FALSE; + +/* Handlers for -P/--private. */ +static const struct objdump_private_desc * const objdump_private_vectors[] = + { + OBJDUMP_PRIVATE_VECTORS + NULL + }; static void usage (FILE *stream, int status) @@ -190,6 +203,7 @@ usage (FILE *stream, int status) -a, --archive-headers Display archive header information\n\ -f, --file-headers Display the contents of the overall file header\n\ -p, --private-headers Display object format specific file header contents\n\ + -P, --private=OPT,OPT... Display object format specific contents\n\ -h, --[section-]headers Display the contents of the section headers\n\ -x, --all-headers Display the contents of all headers\n\ -d, --disassemble Display assembler contents of executable sections\n\ @@ -199,8 +213,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[lLiaprmfFsoR] or\n\ - --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\ + -W[lLiaprmfFsoRt] 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\ 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\ @@ -213,6 +230,8 @@ usage (FILE *stream, int status) ")); if (status != 2) { + const struct objdump_private_desc * const *desc; + fprintf (stream, _("\n The following switches are optional:\n")); fprintf (stream, _("\ -b, --target=BFDNAME Specify the target object format as BFDNAME\n\ @@ -235,15 +254,29 @@ usage (FILE *stream, int status) --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\ --adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\ --special-syms Include special symbols in symbol dumps\n\ --prefix=PREFIX Add PREFIX to absolute paths for -S\n\ - --prefix-strip=LEVEL Strip initial directory names for -S\n\ -\n")); + --prefix-strip=LEVEL Strip initial directory names for -S\n")); + fprintf (stream, _("\ + --dwarf-depth=N Do not display DIEs at depth N or greater\n\ + --dwarf-start=N Display DIEs starting with N, at the same depth\n\ + or deeper\n\ + --dwarf-check Make additional dwarf internal consistency checks.\ + \n\n")); list_supported_targets (program_name, stream); list_supported_architectures (program_name, stream); disassembler_usage (stream); + + if (objdump_private_vectors[0] != NULL) + { + fprintf (stream, + _("\nOptions supported for -P/--private switch:\n")); + for (desc = objdump_private_vectors; *desc != NULL; desc++) + (*desc)->help (stream); + } } if (REPORT_BUGS_TO[0] && status == 0) fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO); @@ -259,7 +292,11 @@ enum option_values OPTION_DWARF, OPTION_PREFIX, OPTION_PREFIX_STRIP, - OPTION_ADJUST_VMA + OPTION_INSN_WIDTH, + OPTION_ADJUST_VMA, + OPTION_DWARF_DEPTH, + OPTION_DWARF_CHECK, + OPTION_DWARF_START }; static struct option long_options[]= @@ -267,6 +304,7 @@ static struct option long_options[]= {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA}, {"all-headers", no_argument, NULL, 'x'}, {"private-headers", no_argument, NULL, 'p'}, + {"private", required_argument, NULL, 'P'}, {"architecture", required_argument, NULL, 'm'}, {"archive-headers", no_argument, NULL, 'a'}, {"debugging", no_argument, NULL, 'g'}, @@ -306,6 +344,10 @@ static struct option long_options[]= {"wide", no_argument, NULL, 'w'}, {"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}, {0, no_argument, 0, 0} }; @@ -315,6 +357,85 @@ nonfatal (const char *msg) bfd_nonfatal (msg); exit_status = 1; } + +/* Returns TRUE if the specified section should be dumped. */ + +static bfd_boolean +process_section_p (asection * section) +{ + struct only * only; + + if (only_list == NULL) + return TRUE; + + for (only = only_list; only; only = only->next) + if (strcmp (only->name, section->name) == 0) + { + only->seen = TRUE; + return TRUE; + } + + return FALSE; +} + +/* Add an entry to the 'only' list. */ + +static void +add_only (char * name) +{ + struct only * only; + + /* First check to make sure that we do not + already have an entry for this name. */ + for (only = only_list; only; only = only->next) + if (strcmp (only->name, name) == 0) + return; + + only = xmalloc (sizeof * only); + only->name = name; + only->seen = FALSE; + only->next = only_list; + only_list = only; +} + +/* Release the memory used by the 'only' list. + PR 11225: Issue a warning message for unseen sections. + Only do this if none of the sections were seen. This is mainly to support + tools like the GAS testsuite where an object file is dumped with a list of + generic section names known to be present in a range of different file + formats. */ + +static void +free_only_list (void) +{ + bfd_boolean at_least_one_seen = FALSE; + struct only * only; + struct only * next; + + if (only_list == NULL) + return; + + for (only = only_list; only; only = only->next) + if (only->seen) + { + at_least_one_seen = TRUE; + break; + } + + for (only = only_list; only; only = next) + { + if (! at_least_one_seen) + { + non_fatal (_("section '%s' mentioned in a -j option, " + "but not found in any input file"), + only->name); + exit_status = 1; + } + next = only->next; + free (only); + } +} + static void dump_section_header (bfd *abfd, asection *section, @@ -328,6 +449,10 @@ dump_section_header (bfd *abfd, asection *section, if (section->flags & SEC_LINKER_CREATED) return; + /* PR 10413: Skip sections that we are ignoring. */ + if (! process_section_p (section)) + return; + printf ("%3d %-13s %08lx ", section->index, bfd_get_section_name (abfd, section), (unsigned long) bfd_section_size (abfd, section) / opb); @@ -419,8 +544,6 @@ dump_headers (bfd *abfd) if (wide_output) printf (_(" Flags")); - if (abfd->flags & HAS_LOAD_PAGE) - printf (_(" Pg")); printf ("\n"); bfd_map_over_sections (abfd, dump_section_header, NULL); @@ -442,7 +565,7 @@ slurp_symtab (bfd *abfd) if (storage < 0) bfd_fatal (bfd_get_filename (abfd)); if (storage) - sy = xmalloc (storage); + sy = (asymbol **) xmalloc (storage); symcount = bfd_canonicalize_symtab (abfd, sy); if (symcount < 0) @@ -464,6 +587,7 @@ slurp_dynamic_symtab (bfd *abfd) if (!(bfd_get_file_flags (abfd) & DYNAMIC)) { non_fatal (_("%s: not a dynamic object"), bfd_get_filename (abfd)); + exit_status = 1; dynsymcount = 0; return NULL; } @@ -471,7 +595,7 @@ slurp_dynamic_symtab (bfd *abfd) bfd_fatal (bfd_get_filename (abfd)); } if (storage) - sy = xmalloc (storage); + sy = (asymbol **) xmalloc (storage); dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy); if (dynsymcount < 0) @@ -641,14 +765,14 @@ compare_relocs (const void *ap, const void *bp) If SKIP_ZEROES is TRUE, omit leading zeroes. */ static void -objdump_print_value (bfd_vma vma, struct disassemble_info *info, +objdump_print_value (bfd_vma vma, struct disassemble_info *inf, bfd_boolean skip_zeroes) { char buf[30]; char *p; struct objdump_disasm_info *aux; - aux = (struct objdump_disasm_info *) info->application_data; + aux = (struct objdump_disasm_info *) inf->application_data; bfd_sprintf_vma (aux->abfd, buf, vma); if (! skip_zeroes) p = buf; @@ -659,13 +783,13 @@ objdump_print_value (bfd_vma vma, struct disassemble_info *info, if (*p == '\0') --p; } - (*info->fprintf_func) (info->stream, "%s", p); + (*inf->fprintf_func) (inf->stream, "%s", p); } /* Print the name of a symbol. */ static void -objdump_print_symname (bfd *abfd, struct disassemble_info *info, +objdump_print_symname (bfd *abfd, struct disassemble_info *inf, asymbol *sym) { char *alloc; @@ -681,8 +805,8 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *info, name = alloc; } - if (info != NULL) - (*info->fprintf_func) (info->stream, "%s", name); + if (inf != NULL) + (*inf->fprintf_func) (inf->stream, "%s", name); else printf ("%s", name); @@ -698,7 +822,7 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *info, static asymbol * find_symbol_for_address (bfd_vma vma, - struct disassemble_info *info, + struct disassemble_info *inf, long *place) { /* @@ Would it speed things up to cache the last two symbols returned, @@ -708,7 +832,7 @@ find_symbol_for_address (bfd_vma vma, /* Indices in `sorted_syms'. */ long min = 0; - long max = sorted_symcount; + long max_count = sorted_symcount; long thisplace; struct objdump_disasm_info *aux; bfd *abfd; @@ -719,22 +843,22 @@ find_symbol_for_address (bfd_vma vma, if (sorted_symcount < 1) return NULL; - aux = (struct objdump_disasm_info *) info->application_data; + aux = (struct objdump_disasm_info *) inf->application_data; abfd = aux->abfd; sec = aux->sec; - opb = bfd_octets_per_byte (abfd); + opb = inf->octets_per_byte; /* Perform a binary search looking for the closest symbol to the - required value. We are searching the range (min, max]. */ - while (min + 1 < max) + required value. We are searching the range (min, max_count]. */ + while (min + 1 < max_count) { asymbol *sym; - thisplace = (max + min) / 2; + thisplace = (max_count + min) / 2; sym = sorted_syms[thisplace]; if (bfd_asymbol_value (sym) > vma) - max = thisplace; + max_count = thisplace; else if (bfd_asymbol_value (sym) < vma) min = thisplace; else @@ -757,12 +881,12 @@ find_symbol_for_address (bfd_vma vma, with the same value, as can occur with overlays or zero size sections. */ min = thisplace; - while (min < max + while (min < max_count && (bfd_asymbol_value (sorted_syms[min]) == bfd_asymbol_value (sorted_syms[thisplace]))) { if (sorted_syms[min]->section == sec - && info->symbol_is_valid (sorted_syms[min], info)) + && inf->symbol_is_valid (sorted_syms[min], inf)) { thisplace = min; @@ -790,7 +914,7 @@ find_symbol_for_address (bfd_vma vma, && vma < (bfd_get_section_vma (abfd, sec) + bfd_section_size (abfd, sec) / opb))); if ((sorted_syms[thisplace]->section != sec && want_section) - || !info->symbol_is_valid (sorted_syms[thisplace], info)) + || ! inf->symbol_is_valid (sorted_syms[thisplace], inf)) { long i; long newplace = sorted_symcount; @@ -798,7 +922,7 @@ find_symbol_for_address (bfd_vma vma, for (i = min - 1; i >= 0; i--) { if ((sorted_syms[i]->section == sec || !want_section) - && info->symbol_is_valid (sorted_syms[i], info)) + && inf->symbol_is_valid (sorted_syms[i], inf)) { if (newplace == sorted_symcount) newplace = i; @@ -822,7 +946,7 @@ find_symbol_for_address (bfd_vma vma, for (i = thisplace + 1; i < sorted_symcount; i++) { if ((sorted_syms[i]->section == sec || !want_section) - && info->symbol_is_valid (sorted_syms[i], info)) + && inf->symbol_is_valid (sorted_syms[i], inf)) { thisplace = i; break; @@ -831,7 +955,7 @@ find_symbol_for_address (bfd_vma vma, } if ((sorted_syms[thisplace]->section != sec && want_section) - || !info->symbol_is_valid (sorted_syms[thisplace], info)) + || ! inf->symbol_is_valid (sorted_syms[thisplace], inf)) /* There is no suitable symbol. */ return NULL; } @@ -846,49 +970,49 @@ find_symbol_for_address (bfd_vma vma, static void objdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym, - bfd_vma vma, struct disassemble_info *info, + bfd_vma vma, struct disassemble_info *inf, bfd_boolean skip_zeroes) { - objdump_print_value (vma, info, skip_zeroes); + objdump_print_value (vma, inf, skip_zeroes); if (sym == NULL) { bfd_vma secaddr; - (*info->fprintf_func) (info->stream, " <%s", - bfd_get_section_name (abfd, sec)); + (*inf->fprintf_func) (inf->stream, " <%s", + bfd_get_section_name (abfd, sec)); secaddr = bfd_get_section_vma (abfd, sec); if (vma < secaddr) { - (*info->fprintf_func) (info->stream, "-0x"); - objdump_print_value (secaddr - vma, info, TRUE); + (*inf->fprintf_func) (inf->stream, "-0x"); + objdump_print_value (secaddr - vma, inf, TRUE); } else if (vma > secaddr) { - (*info->fprintf_func) (info->stream, "+0x"); - objdump_print_value (vma - secaddr, info, TRUE); + (*inf->fprintf_func) (inf->stream, "+0x"); + objdump_print_value (vma - secaddr, inf, TRUE); } - (*info->fprintf_func) (info->stream, ">"); + (*inf->fprintf_func) (inf->stream, ">"); } else { - (*info->fprintf_func) (info->stream, " <"); - objdump_print_symname (abfd, info, sym); + (*inf->fprintf_func) (inf->stream, " <"); + objdump_print_symname (abfd, inf, sym); if (bfd_asymbol_value (sym) > vma) { - (*info->fprintf_func) (info->stream, "-0x"); - objdump_print_value (bfd_asymbol_value (sym) - vma, info, TRUE); + (*inf->fprintf_func) (inf->stream, "-0x"); + objdump_print_value (bfd_asymbol_value (sym) - vma, inf, TRUE); } else if (vma > bfd_asymbol_value (sym)) { - (*info->fprintf_func) (info->stream, "+0x"); - objdump_print_value (vma - bfd_asymbol_value (sym), info, TRUE); + (*inf->fprintf_func) (inf->stream, "+0x"); + objdump_print_value (vma - bfd_asymbol_value (sym), inf, TRUE); } - (*info->fprintf_func) (info->stream, ">"); + (*inf->fprintf_func) (inf->stream, ">"); } if (display_file_offsets) - info->fprintf_func (info->stream, _(" (File Offset: 0x%lx)"), + inf->fprintf_func (inf->stream, _(" (File Offset: 0x%lx)"), (long int)(sec->filepos + (vma - sec->vma))); } @@ -897,23 +1021,23 @@ objdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym, static void objdump_print_addr (bfd_vma vma, - struct disassemble_info *info, + struct disassemble_info *inf, bfd_boolean skip_zeroes) { struct objdump_disasm_info *aux; asymbol *sym = NULL; bfd_boolean skip_find = FALSE; - aux = (struct objdump_disasm_info *) info->application_data; + aux = (struct objdump_disasm_info *) inf->application_data; if (sorted_symcount < 1) { - (*info->fprintf_func) (info->stream, "0x"); - objdump_print_value (vma, info, skip_zeroes); + (*inf->fprintf_func) (inf->stream, "0x"); + objdump_print_value (vma, inf, skip_zeroes); if (display_file_offsets) - info->fprintf_func (info->stream, _(" (File Offset: 0x%lx)"), - (long int)(aux->sec->filepos + (vma - aux->sec->vma))); + inf->fprintf_func (inf->stream, _(" (File Offset: 0x%lx)"), + (long int)(aux->sec->filepos + (vma - aux->sec->vma))); return; } @@ -931,9 +1055,9 @@ objdump_print_addr (bfd_vma vma, } if (!skip_find) - sym = find_symbol_for_address (vma, info, NULL); + sym = find_symbol_for_address (vma, inf, NULL); - objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info, + objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, inf, skip_zeroes); } @@ -941,19 +1065,19 @@ objdump_print_addr (bfd_vma vma, routine. */ static void -objdump_print_address (bfd_vma vma, struct disassemble_info *info) +objdump_print_address (bfd_vma vma, struct disassemble_info *inf) { - objdump_print_addr (vma, info, ! prefix_addresses); + objdump_print_addr (vma, inf, ! prefix_addresses); } /* Determine if the given address has a symbol associated with it. */ static int -objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info) +objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * inf) { asymbol * sym; - sym = find_symbol_for_address (vma, info, NULL); + sym = find_symbol_for_address (vma, inf, NULL); return (sym != NULL && (bfd_asymbol_value (sym) == vma)); } @@ -963,6 +1087,7 @@ objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info) static char *prev_functionname; static unsigned int prev_line; +static unsigned int prev_discriminator; /* We keep a list of all files that we have seen when doing a disassembly with source, so that we know how much of the file to @@ -1004,25 +1129,28 @@ slurp_file (const char *fn, size_t *size) if (fd < 0) return NULL; if (fstat (fd, &st) < 0) - return NULL; + { + close (fd); + return NULL; + } *size = st.st_size; #ifdef HAVE_MMAP msize = (*size + ps - 1) & ~(ps - 1); map = mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0); - if (map != (char *)-1L) + if (map != (char *) -1L) { - close(fd); - return map; + close (fd); + return map; } #endif - map = malloc (*size); - if (!map || (size_t) read (fd, (char *)map, *size) != *size) - { - free ((void *)map); + map = (const char *) malloc (*size); + if (!map || (size_t) read (fd, (char *) map, *size) != *size) + { + free ((void *) map); map = NULL; } close (fd); - return map; + return map; } #define line_map_decrease 5 @@ -1070,7 +1198,7 @@ index_file (const char *map, size_t size, unsigned int *maxline) if (line_map_size < lineno + 1) line_map_size = lineno + 1; newsize = line_map_size * sizeof (char *); - linemap = xrealloc (linemap, newsize); + linemap = (const char **) xrealloc (linemap, newsize); } linemap[lineno++] = lstart; @@ -1089,7 +1217,7 @@ try_print_file_open (const char *origname, const char *modname) { struct print_file_list *p; - p = xmalloc (sizeof (struct print_file_list)); + p = (struct print_file_list *) xmalloc (sizeof (struct print_file_list)); p->map = slurp_file (modname, &p->mapsize); if (p->map == NULL) @@ -1108,7 +1236,7 @@ try_print_file_open (const char *origname, const char *modname) return p; } -/* If the the source file, as described in the symtab, is not found +/* If the source file, as described in the symtab, is not found try to locate it in one of the paths specified with -I If found, add location to print_files linked list. */ @@ -1119,9 +1247,6 @@ update_source_path (const char *filename) const char *fname; int i; - if (filename == NULL) - return NULL; - p = try_print_file_open (filename, filename); if (p != NULL) return p; @@ -1130,21 +1255,7 @@ update_source_path (const char *filename) return NULL; /* Get the name of the file. */ - fname = strrchr (filename, '/'); -#ifdef HAVE_DOS_BASED_FILE_SYSTEM - { - /* We could have a mixed forward/back slash case. */ - char *backslash = strrchr (filename, '\\'); - if (fname == NULL || (backslash != NULL && backslash > fname)) - fname = backslash; - if (fname == NULL && filename[0] != '\0' && filename[1] == ':') - fname = filename + 1; - } -#endif - if (fname == NULL) - fname = filename; - else - ++fname; + 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. */ @@ -1165,15 +1276,15 @@ update_source_path (const char *filename) /* Print a source file line. */ static void -print_line (struct print_file_list *p, unsigned int line) +print_line (struct print_file_list *p, unsigned int linenum) { const char *l; size_t len; - --line; - if (line >= p->maxline) + --linenum; + if (linenum >= p->maxline) return; - l = p->linemap [line]; + l = p->linemap [linenum]; /* Test fwrite return value to quiet glibc warning. */ len = strcspn (l, "\n\r"); if (len == 0 || fwrite (l, len, 1, stdout) == 1) @@ -1202,14 +1313,16 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) { const char *filename; const char *functionname; - unsigned int line; + unsigned int linenumber; + unsigned int discriminator; bfd_boolean reloc; if (! with_line_numbers && ! with_source_code) return; - if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, - &functionname, &line)) + if (! bfd_find_nearest_line_discriminator (abfd, section, syms, addr_offset, + &filename, &functionname, + &linenumber, &discriminator)) return; if (filename != NULL && *filename == '\0') @@ -1261,19 +1374,26 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) && (prev_functionname == NULL || strcmp (functionname, prev_functionname) != 0)) printf ("%s():\n", functionname); - if (line > 0 && line != prev_line) - printf ("%s:%u\n", filename == NULL ? "???" : filename, line); + 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 (with_source_code && filename != NULL - && line > 0) + && linenumber > 0) { struct print_file_list **pp, *p; unsigned l; for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) - if (strcmp ((*pp)->filename, filename) == 0) + if (filename_cmp ((*pp)->filename, filename) == 0) break; p = *pp; @@ -1284,20 +1404,20 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) p = update_source_path (filename); } - if (p != NULL && line != p->last_line) + if (p != NULL && linenumber != p->last_line) { if (file_start_context && p->first) l = 1; else { - l = line - SHOW_PRECEDING_CONTEXT_LINES; - if (l >= line) + l = linenumber - SHOW_PRECEDING_CONTEXT_LINES; + if (l >= linenumber) l = 1; - if (p->last_line >= l && p->last_line <= line) + if (p->last_line >= l && p->last_line <= linenumber) l = p->last_line + 1; } - dump_lines (p, l, line); - p->last_line = line; + dump_lines (p, l, linenumber); + p->last_line = linenumber; p->first = 0; } } @@ -1308,12 +1428,15 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset) { if (prev_functionname != NULL) free (prev_functionname); - prev_functionname = xmalloc (strlen (functionname) + 1); + prev_functionname = (char *) xmalloc (strlen (functionname) + 1); strcpy (prev_functionname, functionname); } - if (line > 0 && line != prev_line) - prev_line = line; + if (linenumber > 0 && linenumber != prev_line) + prev_line = linenumber; + + if (discriminator != prev_discriminator) + prev_discriminator = discriminator; } /* Pseudo FILE object for strings. */ @@ -1344,31 +1467,13 @@ objdump_sprintf (SFILE *f, const char *format, ...) break; f->alloc = (f->alloc + n) * 2; - f->buffer = xrealloc (f->buffer, f->alloc); + f->buffer = (char *) xrealloc (f->buffer, f->alloc); } f->pos += n; return n; } -/* Returns TRUE if the specified section should be dumped. */ - -static bfd_boolean -process_section_p (asection * section) -{ - size_t i; - - if (only == NULL) - return TRUE; - - for (i = 0; i < only_used; i++) - if (strcmp (only [i], section->name) == 0) - return TRUE; - - return FALSE; -} - - /* The number of zeroes we want to see before we start skipping them. The number is arbitrarily chosen. */ @@ -1386,7 +1491,7 @@ process_section_p (asection * section) /* Disassemble some data in memory between given values. */ static void -disassemble_bytes (struct disassemble_info * info, +disassemble_bytes (struct disassemble_info * inf, disassembler_ftype disassemble_fn, bfd_boolean insns, bfd_byte * data, @@ -1399,23 +1504,24 @@ disassemble_bytes (struct disassemble_info * info, struct objdump_disasm_info *aux; asection *section; int octets_per_line; - bfd_boolean done_dot; int skip_addr_chars; bfd_vma addr_offset; - unsigned int opb = info->octets_per_byte; - unsigned int skip_zeroes = info->skip_zeroes; - unsigned int skip_zeroes_at_end = info->skip_zeroes_at_end; + unsigned int opb = inf->octets_per_byte; + unsigned int skip_zeroes = inf->skip_zeroes; + unsigned int skip_zeroes_at_end = inf->skip_zeroes_at_end; int octets = opb; SFILE sfile; - aux = (struct objdump_disasm_info *) info->application_data; + aux = (struct objdump_disasm_info *) inf->application_data; section = aux->sec; sfile.alloc = 120; - sfile.buffer = xmalloc (sfile.alloc); + sfile.buffer = (char *) xmalloc (sfile.alloc); sfile.pos = 0; - if (insns) + if (insn_width) + octets_per_line = insn_width; + else if (insns) octets_per_line = 4; else octets_per_line = 16; @@ -1442,9 +1548,8 @@ disassemble_bytes (struct disassemble_info * info, skip_addr_chars = (skip_addr_chars - 1) & -4; } - info->insn_info_valid = 0; + inf->insn_info_valid = 0; - done_dot = FALSE; addr_offset = start_offset; while (addr_offset < stop_offset) { @@ -1456,14 +1561,17 @@ disassemble_bytes (struct disassemble_info * info, previous_octets = octets; octets = 0; + /* Make sure we don't use relocs from previous instructions. */ + aux->reloc = NULL; + /* If we see more than SKIP_ZEROES octets of zeroes, we just print `...'. */ for (z = addr_offset * opb; z < stop_offset * opb; z++) if (data[z] != 0) break; if (! disassemble_zeroes - && (info->insn_info_valid == 0 - || info->branch_delay_insns == 0) + && (inf->insn_info_valid == 0 + || inf->branch_delay_insns == 0) && (z - addr_offset * opb >= skip_zeroes || (z == stop_offset * opb && z - addr_offset * opb < skip_zeroes_at_end))) @@ -1494,8 +1602,6 @@ disassemble_bytes (struct disassemble_info * info, int bpc = 0; int pb = 0; - done_dot = FALSE; - if (with_line_numbers || with_source_code) show_line (aux->abfd, section, addr_offset); @@ -1513,7 +1619,7 @@ disassemble_bytes (struct disassemble_info * info, else { aux->require_sec = TRUE; - objdump_print_address (section->vma + addr_offset, info); + objdump_print_address (section->vma + addr_offset, inf); aux->require_sec = FALSE; putchar (' '); } @@ -1521,13 +1627,15 @@ disassemble_bytes (struct disassemble_info * info, if (insns) { sfile.pos = 0; - info->fprintf_func = (fprintf_ftype) objdump_sprintf; - info->stream = &sfile; - info->bytes_per_line = 0; - info->bytes_per_chunk = 0; - info->flags = 0; - - if (info->disassembler_needs_relocs + inf->fprintf_func = (fprintf_ftype) objdump_sprintf; + inf->stream = &sfile; + inf->bytes_per_line = 0; + inf->bytes_per_chunk = 0; + inf->flags = disassemble_all ? DISASSEMBLE_DATA : 0; + if (machine) + inf->flags |= USER_SPECIFIED_MACHINE_TYPE; + + if (inf->disassembler_needs_relocs && (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0 && (bfd_get_file_flags (aux->abfd) & DYNAMIC) == 0 && *relppp < relppend) @@ -1554,22 +1662,26 @@ disassemble_bytes (struct disassemble_info * info, || (distance_to_rel > 0 && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb))) { - info->flags = INSN_HAS_RELOC; + inf->flags |= INSN_HAS_RELOC; aux->reloc = **relppp; } - else - aux->reloc = NULL; } - octets = (*disassemble_fn) (section->vma + addr_offset, info); - info->fprintf_func = (fprintf_ftype) fprintf; - info->stream = stdout; - if (info->bytes_per_line != 0) - octets_per_line = info->bytes_per_line; - if (octets < 0) + octets = (*disassemble_fn) (section->vma + addr_offset, inf); + inf->fprintf_func = (fprintf_ftype) fprintf; + inf->stream = stdout; + if (insn_width == 0 && inf->bytes_per_line != 0) + octets_per_line = inf->bytes_per_line; + if (octets < (int) opb) { if (sfile.pos) printf ("%s\n", sfile.buffer); + if (octets >= 0) + { + non_fatal (_("disassemble_fn returned length %d"), + octets); + exit_status = 1; + } break; } } @@ -1603,8 +1715,8 @@ disassemble_bytes (struct disassemble_info * info, if (pb > octets_per_line && ! prefix_addresses && ! wide_output) pb = octets_per_line; - if (info->bytes_per_chunk) - bpc = info->bytes_per_chunk; + if (inf->bytes_per_chunk) + bpc = inf->bytes_per_chunk; else bpc = 1; @@ -1612,7 +1724,7 @@ disassemble_bytes (struct disassemble_info * info, { int k; - if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) + if (bpc > 1 && inf->display_endian == BFD_ENDIAN_LITTLE) { for (k = bpc - 1; k >= 0; k--) printf ("%02x", (unsigned) data[j + k]); @@ -1673,7 +1785,7 @@ disassemble_bytes (struct disassemble_info * info, { int k; - if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) + if (bpc > 1 && inf->display_endian == BFD_ENDIAN_LITTLE) { for (k = bpc - 1; k >= 0; k--) printf ("%02x", (unsigned) data[j + k]); @@ -1710,7 +1822,7 @@ disassemble_bytes (struct disassemble_info * info, printf ("\t\t\t"); objdump_print_value (section->vma - rel_offset + q->address, - info, TRUE); + inf, TRUE); if (q->howto == NULL) printf (": *unknown*\t"); @@ -1727,7 +1839,7 @@ disassemble_bytes (struct disassemble_info * info, sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); if (sym_name != NULL && *sym_name != '\0') - objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr); + objdump_print_symname (aux->abfd, inf, *q->sym_ptr_ptr); else { asection *sym_sec; @@ -1742,8 +1854,15 @@ disassemble_bytes (struct disassemble_info * info, if (q->addend) { - printf ("+0x"); - objdump_print_value (q->addend, info, TRUE); + bfd_signed_vma addend = q->addend; + if (addend < 0) + { + printf ("-0x"); + addend = -addend; + } + else + printf ("+0x"); + objdump_print_value (addend, inf, TRUE); } printf ("\n"); @@ -1762,11 +1881,11 @@ disassemble_bytes (struct disassemble_info * info, } static void -disassemble_section (bfd *abfd, asection *section, void *info) +disassemble_section (bfd *abfd, asection *section, void *inf) { const struct elf_backend_data * bed; bfd_vma sign_adjust = 0; - struct disassemble_info * pinfo = (struct disassemble_info *) info; + struct disassemble_info * pinfo = (struct disassemble_info *) inf; struct objdump_disasm_info * paux; unsigned int opb = pinfo->octets_per_byte; bfd_byte * data = NULL; @@ -1784,7 +1903,7 @@ disassemble_section (bfd *abfd, asection *section, void *info) /* Sections that do not contain machine code are not normally disassembled. */ if (! disassemble_all - && only == NULL + && only_list == NULL && ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS)) != (SEC_CODE | SEC_HAS_CONTENTS))) return; @@ -1824,7 +1943,7 @@ disassemble_section (bfd *abfd, asection *section, void *info) if (relsize > 0) { - rel_ppstart = rel_pp = xmalloc (relsize); + rel_ppstart = rel_pp = (arelent **) xmalloc (relsize); rel_count = bfd_canonicalize_reloc (abfd, section, rel_pp, syms); if (rel_count < 0) bfd_fatal (bfd_get_filename (abfd)); @@ -1836,7 +1955,7 @@ disassemble_section (bfd *abfd, asection *section, void *info) } rel_ppend = rel_pp + rel_count; - data = xmalloc (datasize); + data = (bfd_byte *) xmalloc (datasize); bfd_get_section_contents (abfd, section, data, 0, datasize); @@ -1875,16 +1994,18 @@ disassemble_section (bfd *abfd, asection *section, void *info) /* Find the nearest symbol forwards from our current position. */ paux->require_sec = TRUE; - sym = find_symbol_for_address (section->vma + addr_offset, info, &place); + sym = (asymbol *) find_symbol_for_address (section->vma + addr_offset, + (struct disassemble_info *) inf, + &place); paux->require_sec = FALSE; - /* PR 9774: If the target used signed 32-bit addresses then we must make - sure that we sign extend the value that we calculate for 'addr' in the - loop below. */ + /* PR 9774: If the target used signed addresses then we must make + sure that we sign extend the value that we calculate for 'addr' + in the loop below. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && (bed = get_elf_backend_data (abfd)) != NULL && bed->sign_extend_vma) - sign_adjust = 0x80000000; + sign_adjust = (bfd_vma) 1 << (bed->s->arch_size - 1); /* Disassemble a block of instructions up to the address associated with the symbol we have just found. Then print the symbol and find the @@ -1898,7 +2019,7 @@ disassemble_section (bfd *abfd, asection *section, void *info) bfd_boolean insns; addr = section->vma + addr_offset; - addr = (addr ^ sign_adjust) - sign_adjust; + addr = ((addr & ((sign_adjust << 1) - 1)) ^ sign_adjust) - sign_adjust; if (sym != NULL && bfd_asymbol_value (sym) <= addr) { @@ -1961,7 +2082,8 @@ disassemble_section (bfd *abfd, asection *section, void *info) else nextstop_offset = bfd_asymbol_value (nextsym) - section->vma; - if (nextstop_offset > stop_offset) + if (nextstop_offset > stop_offset + || nextstop_offset <= addr_offset) nextstop_offset = stop_offset; /* If a symbol is explicitly marked as being an object @@ -1984,7 +2106,7 @@ disassemble_section (bfd *abfd, asection *section, void *info) disassemble_bytes (pinfo, paux->disassemble_fn, insns, data, addr_offset, nextstop_offset, rel_offset, &rel_pp, rel_ppend); - + addr_offset = nextstop_offset; sym = nextsym; } @@ -2007,11 +2129,13 @@ disassemble_data (bfd *abfd) print_files = NULL; prev_functionname = NULL; prev_line = -1; + prev_discriminator = 0; /* We make a copy of syms to sort. We don't want to sort syms because that will screw up the relocs. */ sorted_symcount = symcount ? symcount : dynsymcount; - sorted_syms = xmalloc ((sorted_symcount + synthcount) * sizeof (asymbol *)); + sorted_syms = (asymbol **) xmalloc ((sorted_symcount + synthcount) + * sizeof (asymbol *)); memcpy (sorted_syms, symcount ? syms : dynsyms, sorted_symcount * sizeof (asymbol *)); @@ -2040,19 +2164,19 @@ disassemble_data (bfd *abfd) if (machine != NULL) { - const bfd_arch_info_type *info = bfd_scan_arch (machine); + const bfd_arch_info_type *inf = bfd_scan_arch (machine); - if (info == NULL) - fatal (_("Can't use supplied machine %s"), machine); + if (inf == NULL) + fatal (_("can't use supplied machine %s"), machine); - abfd->arch_info = info; + abfd->arch_info = inf; } if (endian != BFD_ENDIAN_UNKNOWN) { struct bfd_target *xvec; - xvec = xmalloc (sizeof (struct bfd_target)); + xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target)); memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); xvec->byteorder = endian; abfd->xvec = xvec; @@ -2062,7 +2186,7 @@ disassemble_data (bfd *abfd) aux.disassemble_fn = disassembler (abfd); if (!aux.disassemble_fn) { - non_fatal (_("Can't disassemble for architecture %s\n"), + non_fatal (_("can't disassemble for architecture %s\n"), bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); exit_status = 1; return; @@ -2100,7 +2224,7 @@ disassemble_data (bfd *abfd) if (relsize > 0) { - aux.dynrelbuf = xmalloc (relsize); + aux.dynrelbuf = (arelent **) xmalloc (relsize); aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, aux.dynrelbuf, dynsyms); @@ -2122,45 +2246,22 @@ disassemble_data (bfd *abfd) free (sorted_syms); } -int -load_debug_section (enum dwarf_section_display_enum debug, void *file) +static int +load_specific_debug_section (enum dwarf_section_display_enum debug, + asection *sec, void *file) { struct dwarf_section *section = &debug_displays [debug].section; - bfd *abfd = file; - asection *sec; + bfd *abfd = (bfd *) file; bfd_boolean ret; - int section_is_compressed; /* If it is already loaded, do nothing. */ if (section->start != NULL) return 1; - /* Locate the debug section. */ - sec = bfd_get_section_by_name (abfd, section->uncompressed_name); - if (sec != NULL) - section->name = section->uncompressed_name; - else - { - sec = bfd_get_section_by_name (abfd, section->compressed_name); - if (sec != NULL) - section->name = section->compressed_name; - } - if (sec == NULL) - return 0; - section_is_compressed = section->name == section->compressed_name; - section->address = 0; section->size = bfd_get_section_size (sec); - section->start = xmalloc (section->size); - - if (is_relocatable && debug_displays [debug].relocate) - ret = bfd_simple_get_relocated_section_contents (abfd, - sec, - section->start, - syms) != NULL; - else - ret = bfd_get_section_contents (abfd, sec, section->start, 0, - section->size); + section->start = NULL; + ret = bfd_get_full_section_contents (abfd, sec, §ion->start); if (! ret) { @@ -2170,19 +2271,52 @@ load_debug_section (enum dwarf_section_display_enum debug, void *file) return 0; } - if (section_is_compressed) + if (is_relocatable && debug_displays [debug].relocate) { - bfd_size_type size = section->size; - if (! bfd_uncompress_section_contents (§ion->start, &size)) + bfd_cache_section_contents (sec, section->start); + + ret = bfd_simple_get_relocated_section_contents (abfd, + sec, + section->start, + syms) != NULL; + + if (! ret) { free_debug_section (debug); - printf (_("\nCan't uncompress section '%s'.\n"), section->name); + printf (_("\nCan't get contents for section '%s'.\n"), + section->name); return 0; } - section->size = size; } - return ret; + return 1; +} + +int +load_debug_section (enum dwarf_section_display_enum debug, void *file) +{ + struct dwarf_section *section = &debug_displays [debug].section; + bfd *abfd = (bfd *) file; + asection *sec; + + /* If it is already loaded, do nothing. */ + if (section->start != NULL) + return 1; + + /* Locate the debug section. */ + sec = bfd_get_section_by_name (abfd, section->uncompressed_name); + if (sec != NULL) + section->name = section->uncompressed_name; + else + { + sec = bfd_get_section_by_name (abfd, section->compressed_name); + if (sec != NULL) + section->name = section->compressed_name; + } + if (sec == NULL) + return 0; + + return load_specific_debug_section (debug, sec, file); } void @@ -2205,7 +2339,7 @@ dump_dwarf_section (bfd *abfd, asection *section, { const char *name = bfd_get_section_name (abfd, section); const char *match; - enum dwarf_section_display_enum i; + int i; if (CONST_STRNEQ (name, ".gnu.linkonce.wi.")) match = ".debug_info"; @@ -2218,17 +2352,19 @@ dump_dwarf_section (bfd *abfd, asection *section, && debug_displays [i].enabled != NULL && *debug_displays [i].enabled) { - if (!debug_displays [i].eh_frame) + struct dwarf_section *sec = &debug_displays [i].section; + + if (strcmp (sec->uncompressed_name, match) == 0) + sec->name = sec->uncompressed_name; + else + sec->name = sec->compressed_name; + if (load_specific_debug_section ((enum dwarf_section_display_enum) i, + section, abfd)) { - struct dwarf_section *sec = &debug_displays [i].section; - - if (load_debug_section (i, abfd)) - { - debug_displays [i].display (sec, abfd); - - if (i != info && i != abbrev) - free_debug_section (i); - } + debug_displays [i].display (sec, abfd); + + if (i != info && i != abbrev) + free_debug_section ((enum dwarf_section_display_enum) i); } break; } @@ -2241,9 +2377,7 @@ dump_dwarf (bfd *abfd) { is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0; - /* FIXME: bfd_get_arch_size may return -1. We assume that 64bit - targets will return 64. */ - eh_addr_size = bfd_get_arch_size (abfd) == 64 ? 8 : 4; + eh_addr_size = bfd_arch_bits_per_address (abfd) / 8; if (bfd_big_endian (abfd)) byte_get = byte_get_big_endian; @@ -2252,10 +2386,26 @@ dump_dwarf (bfd *abfd) else abort (); - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) + switch (bfd_get_arch (abfd)) { - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - init_dwarf_regnames (bed->elf_machine_code); + case bfd_arch_i386: + switch (bfd_get_mach (abfd)) + { + case bfd_mach_x86_64: + case bfd_mach_x86_64_intel_syntax: + case bfd_mach_x64_32: + case bfd_mach_x64_32_intel_syntax: + init_dwarf_regnames_x86_64 (); + break; + + default: + init_dwarf_regnames_i386 (); + break; + } + break; + + default: + break; } bfd_map_over_sections (abfd, dump_dwarf_section, NULL); @@ -2281,15 +2431,15 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) } size = bfd_section_size (abfd, stabsect); - contents = xmalloc (size); + contents = (char *) xmalloc (size); if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size)) { - non_fatal (_("Reading %s section of %s failed: %s"), + non_fatal (_("reading %s section of %s failed: %s"), sect_name, bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); - free (contents); exit_status = 1; + free (contents); return NULL; } @@ -2463,7 +2613,7 @@ dump_bfd_header (bfd *abfd) printf (_("architecture: %s, "), bfd_printable_arch_mach (bfd_get_arch (abfd), bfd_get_mach (abfd))); - printf (_("flags 0x%08x:\n"), abfd->flags); + printf (_("flags 0x%08x:\n"), abfd->flags & ~BFD_FLAGS_FOR_BFD_USE_MASK); #define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} PF (HAS_RELOC, "HAS_RELOC"); @@ -2489,6 +2639,57 @@ dump_bfd_private_header (bfd *abfd) bfd_print_private_bfd_data (abfd, stdout); } +static void +dump_target_specific (bfd *abfd) +{ + const struct objdump_private_desc * const *desc; + struct objdump_private_option *opt; + char *e, *b; + + /* Find the desc. */ + for (desc = objdump_private_vectors; *desc != NULL; desc++) + if ((*desc)->filter (abfd)) + break; + + if (desc == NULL) + { + non_fatal (_("option -P/--private not supported by this file")); + return; + } + + /* Clear all options. */ + for (opt = (*desc)->options; opt->name; opt++) + opt->selected = FALSE; + + /* Decode options. */ + b = dump_private_options; + do + { + e = strchr (b, ','); + + if (e) + *e = 0; + + for (opt = (*desc)->options; opt->name; opt++) + if (strcmp (opt->name, b) == 0) + { + opt->selected = TRUE; + break; + } + if (opt->name == NULL) + non_fatal (_("target specific dump '%s' not supported"), b); + + if (e) + { + *e = ','; + b = e + 1; + } + } + while (e != NULL); + + /* Dump. */ + (*desc)->dump (abfd); +} /* Display a section in hexadecimal format with associated characters. Each line prefixed by the zero padded address. */ @@ -2546,9 +2747,11 @@ dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) (unsigned long) (section->filepos + start_offset)); printf ("\n"); - data = xmalloc (datasize); - - bfd_get_section_contents (abfd, section, data, 0, datasize); + if (!bfd_get_full_section_contents (abfd, section, &data)) + { + non_fatal (_("Reading section failed")); + return; + } width = 4; @@ -2632,26 +2835,26 @@ static void dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic) { asymbol **current; - long max; + long max_count; long count; if (dynamic) { current = dynsyms; - max = dynsymcount; + max_count = dynsymcount; printf ("DYNAMIC SYMBOL TABLE:\n"); } else { current = syms; - max = symcount; + max_count = symcount; printf ("SYMBOL TABLE:\n"); } - if (max == 0) + if (max_count == 0) printf (_("no symbols\n")); - for (count = 0; count < max; count++) + for (count = 0; count < max_count; count++) { bfd *cur_bfd; @@ -2703,6 +2906,7 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) arelent **p; char *last_filename, *last_functionname; unsigned int last_line; + unsigned int last_discriminator; /* Get column headers lined up reasonably. */ { @@ -2721,14 +2925,17 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) last_filename = NULL; last_functionname = NULL; last_line = 0; + last_discriminator = 0; for (p = relpp; relcount && *p != NULL; p++, relcount--) { arelent *q = *p; const char *filename, *functionname; - unsigned int line; + unsigned int linenumber; + unsigned int discriminator; const char *sym_name; const char *section_name; + bfd_vma addend2 = 0; if (start_address != (bfd_vma) -1 && q->address < start_address) @@ -2739,8 +2946,9 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) if (with_line_numbers && sec != NULL - && bfd_find_nearest_line (abfd, sec, syms, q->address, - &filename, &functionname, &line)) + && bfd_find_nearest_line_discriminator (abfd, sec, syms, q->address, + &filename, &functionname, + &linenumber, &discriminator)) { if (functionname != NULL && (last_functionname == NULL @@ -2752,14 +2960,20 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) last_functionname = xstrdup (functionname); } - if (line > 0 - && (line != last_line + if (linenumber > 0 + && (linenumber != last_line || (filename != NULL && last_filename != NULL - && strcmp (filename, last_filename) != 0))) + && filename_cmp (filename, last_filename) != 0) + || (discriminator != last_discriminator))) { - printf ("%s:%u\n", filename == NULL ? "???" : filename, line); - last_line = line; + if (discriminator > 0) + printf ("%s:%u\n", filename == NULL ? "???" : filename, linenumber); + else + printf ("%s:%u (discriminator %u)\n", filename == NULL ? "???" : filename, + linenumber, discriminator); + last_line = linenumber; + last_discriminator = discriminator; if (last_filename != NULL) free (last_filename); if (filename == NULL) @@ -2784,7 +2998,37 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) if (q->howto == NULL) printf (" *unknown* "); else if (q->howto->name) - printf (" %-16s ", q->howto->name); + { + const char *name = q->howto->name; + + /* R_SPARC_OLO10 relocations contain two addends. + But because 'arelent' lacks enough storage to + store them both, the 64-bit ELF Sparc backend + records this as two relocations. One R_SPARC_LO10 + and one R_SPARC_13, both pointing to the same + address. This is merely so that we have some + place to store both addend fields. + + Undo this transformation, otherwise the output + will be confusing. */ + if (abfd->xvec->flavour == bfd_target_elf_flavour + && elf_tdata(abfd)->elf_header->e_machine == EM_SPARCV9 + && relcount > 1 + && !strcmp (q->howto->name, "R_SPARC_LO10")) + { + arelent *q2 = *(p + 1); + if (q2 != NULL + && q2->howto + && q->address == q2->address + && !strcmp (q2->howto->name, "R_SPARC_13")) + { + name = "R_SPARC_OLO10"; + addend2 = q2->addend; + p++; + } + } + printf (" %-16s ", name); + } else printf (" %-16d ", q->howto->type); @@ -2800,13 +3044,30 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) } if (q->addend) + { + bfd_signed_vma addend = q->addend; + if (addend < 0) + { + printf ("-0x"); + addend = -addend; + } + else + printf ("+0x"); + bfd_printf_vma (abfd, addend); + } + if (addend2) { printf ("+0x"); - bfd_printf_vma (abfd, q->addend); + bfd_printf_vma (abfd, addend2); } printf ("\n"); } + + if (last_filename != NULL) + free (last_filename); + if (last_functionname != NULL) + free (last_functionname); } static void @@ -2837,7 +3098,7 @@ dump_relocs_in_section (bfd *abfd, return; } - relpp = xmalloc (relsize); + relpp = (arelent **) xmalloc (relsize); relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); if (relcount < 0) @@ -2876,7 +3137,7 @@ dump_dynamic_relocs (bfd *abfd) printf (" (none)\n\n"); else { - relpp = xmalloc (relsize); + relpp = (arelent **) xmalloc (relsize); relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); if (relcount < 0) @@ -2901,8 +3162,8 @@ add_include_path (const char *path) if (path[0] == 0) return; include_path_count++; - include_paths = xrealloc (include_paths, - include_path_count * sizeof (*include_paths)); + include_paths = (const char **) + xrealloc (include_paths, include_path_count * sizeof (*include_paths)); #ifdef HAVE_DOS_BASED_FILE_SYSTEM if (path[1] == ':' && path[2] == 0) path = concat (path, ".", (const char *) 0); @@ -2938,7 +3199,7 @@ dump_bfd (bfd *abfd) bfd_map_over_sections (abfd, adjust_addresses, &has_reloc); } - if (! dump_debugging_tags) + if (! dump_debugging_tags && ! suppress_bfd_header) printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), abfd->xvec->name); if (dump_ar_hdrs) @@ -2947,10 +3208,10 @@ dump_bfd (bfd *abfd) dump_bfd_header (abfd); if (dump_private_headers) dump_bfd_private_header (abfd); - if (! dump_debugging_tags) + if (dump_private_options != NULL) + dump_target_specific (abfd); + if (! dump_debugging_tags && ! suppress_bfd_header) putchar ('\n'); - if (dump_section_headers) - dump_headers (abfd); if (dump_symtab || dump_reloc_info @@ -2958,6 +3219,10 @@ dump_bfd (bfd *abfd) || dump_debugging || dump_dwarf_section_info) syms = slurp_symtab (abfd); + + if (dump_section_headers) + dump_headers (abfd); + if (dump_dynamic_symtab || dump_dynamic_reloc_info || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0)) dynsyms = slurp_dynamic_symtab (abfd); @@ -3006,6 +3271,7 @@ dump_bfd (bfd *abfd) info in the file, try DWARF instead. */ else if (! dump_dwarf_section_info) { + dwarf_select_sections_all (); dump_dwarf (abfd); } } @@ -3034,7 +3300,7 @@ dump_bfd (bfd *abfd) } static void -display_bfd (bfd *abfd) +display_object_bfd (bfd *abfd) { char **matching; @@ -3074,30 +3340,23 @@ display_bfd (bfd *abfd) } static void -display_file (char *filename, char *target) +display_any_bfd (bfd *file, int level) { - bfd *file; - bfd *arfile = NULL; - - if (get_file_size (filename) < 1) - { - exit_status = 1; - return; - } - - file = bfd_openr (filename, target); - if (file == NULL) - { - nonfatal (filename); - return; - } + /* Decompress sections unless dumping the section contents. */ + if (!dump_section_contents) + file->flags |= BFD_DECOMPRESS; /* If the file is an archive, process all of its elements. */ if (bfd_check_format (file, bfd_archive)) { + bfd *arfile = NULL; bfd *last_arfile = NULL; - printf (_("In archive %s:\n"), bfd_get_filename (file)); + if (level == 0) + printf (_("In archive %s:\n"), bfd_get_filename (file)); + else + printf (_("In nested archive %s:\n"), bfd_get_filename (file)); + for (;;) { bfd_set_error (bfd_error_no_error); @@ -3110,7 +3369,7 @@ display_file (char *filename, char *target) break; } - display_bfd (arfile); + display_any_bfd (arfile, level + 1); if (last_arfile != NULL) bfd_close (last_arfile); @@ -3121,7 +3380,28 @@ display_file (char *filename, char *target) bfd_close (last_arfile); } else - display_bfd (file); + display_object_bfd (file); +} + +static void +display_file (char *filename, char *target) +{ + bfd *file; + + if (get_file_size (filename) < 1) + { + exit_status = 1; + return; + } + + file = bfd_openr (filename, target); + if (file == NULL) + { + nonfatal (filename); + return; + } + + display_any_bfd (file, 0); bfd_close (file); } @@ -3154,7 +3434,7 @@ main (int argc, char **argv) set_default_bfd_target (); while ((c = getopt_long (argc, argv, - "pib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::", + "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::", long_options, (int *) 0)) != EOF) { @@ -3174,12 +3454,7 @@ main (int argc, char **argv) disassembler_options = optarg; break; case 'j': - if (only_used == only_size) - { - only_size += 8; - only = xrealloc (only, only_size * sizeof (char *)); - } - only [only_used++] = optarg; + add_only (optarg); break; case 'F': display_file_offsets = TRUE; @@ -3232,6 +3507,11 @@ main (int argc, char **argv) if (prefix_strip < 0) fatal (_("error: prefix strip must be non-negative")); break; + case OPTION_INSN_WIDTH: + insn_width = strtoul (optarg, NULL, 0); + if (insn_width <= 0) + fatal (_("error: instruction width must be positive")); + break; case 'E': if (strcmp (optarg, "B") == 0) endian = BFD_ENDIAN_BIG; @@ -3239,7 +3519,7 @@ main (int argc, char **argv) endian = BFD_ENDIAN_LITTLE; else { - non_fatal (_("unrecognized -E option")); + nonfatal (_("unrecognized -E option")); usage (stderr, 1); } break; @@ -3251,6 +3531,7 @@ main (int argc, char **argv) else { non_fatal (_("unrecognized --endian type `%s'"), optarg); + exit_status = 1; usage (stderr, 1); } break; @@ -3270,6 +3551,10 @@ main (int argc, char **argv) dump_private_headers = TRUE; seenflag = TRUE; break; + case 'P': + dump_private_options = optarg; + seenflag = TRUE; + break; case 'x': dump_private_headers = TRUE; dump_symtab = TRUE; @@ -3330,6 +3615,22 @@ main (int argc, char **argv) else dwarf_select_sections_all (); break; + case OPTION_DWARF_DEPTH: + { + char *cp; + dwarf_cutoff_level = strtoul (optarg, & cp, 0); + } + break; + case OPTION_DWARF_START: + { + char *cp; + dwarf_start_die = strtoul (optarg, & cp, 0); + suppress_bfd_header = 1; + } + break; + case OPTION_DWARF_CHECK: + dwarf_check = TRUE; + break; case 'G': dump_stab_section_info = TRUE; seenflag = TRUE; @@ -3385,6 +3686,8 @@ main (int argc, char **argv) display_file (argv[optind++], target); } + free_only_list (); + END_PROGRESS (program_name); return exit_status;