diff options
-rw-r--r-- | binutils/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/objdump.c | 266 |
2 files changed, 192 insertions, 80 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 68e98dfab5..951d45642c 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +Mon Jul 22 08:46:15 1996 Stu Grossman (grossman@lisa.cygnus.com) + + * objdump.c (dump_section_stabs): Fix test for stabs sections + ending with numbers. This fixes a problem with .stab being + confused with .stab.index. + Wed Jul 10 13:32:28 1996 Ian Lance Taylor <ian@cygnus.com> * stabs.c (stab_demangle_fund_type): Return a void * for a diff --git a/binutils/objdump.c b/binutils/objdump.c index 7fbe1353e4..74d8f4b8be 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -42,32 +42,32 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ extern int fprintf PARAMS ((FILE *, const char *, ...)); #endif -char *default_target = NULL; /* default at runtime */ +static char *default_target = NULL; /* default at runtime */ extern char *program_version; -int show_version = 0; /* show the version number */ -int dump_section_contents; /* -s */ -int dump_section_headers; /* -h */ -boolean dump_file_header; /* -f */ -int dump_symtab; /* -t */ -int dump_dynamic_symtab; /* -T */ -int dump_reloc_info; /* -r */ -int dump_dynamic_reloc_info; /* -R */ -int dump_ar_hdrs; /* -a */ -int dump_private_headers; /* -p */ -int with_line_numbers; /* -l */ -boolean with_source_code; /* -S */ -int show_raw_insn; /* --show-raw-insn */ -int dump_stab_section_info; /* --stabs */ -boolean disassemble; /* -d */ -boolean disassemble_all; /* -D */ -boolean formats_info; /* -i */ -char *only; /* -j secname */ -int wide_output; /* -w */ -bfd_vma start_address = (bfd_vma) -1; /* --start-address */ -bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ -int dump_debugging; /* --debugging */ +static int show_version = 0; /* show the version number */ +static int dump_section_contents; /* -s */ +static int dump_section_headers; /* -h */ +static boolean dump_file_header; /* -f */ +static int dump_symtab; /* -t */ +static int dump_dynamic_symtab; /* -T */ +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 int with_line_numbers; /* -l */ +static boolean with_source_code; /* -S */ +static int show_raw_insn; /* --show-raw-insn */ +static int dump_stab_section_info; /* --stabs */ +static boolean disassemble; /* -d */ +static boolean disassemble_all; /* -D */ +static boolean formats_info; /* -i */ +static char *only; /* -j secname */ +static int wide_output; /* -w */ +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 */ /* Extra info to pass to the disassembler address printing function. */ struct objdump_disasm_info { @@ -77,25 +77,28 @@ struct objdump_disasm_info { }; /* Architecture to disassemble for, or default if NULL. */ -char *machine = (char *) NULL; +static char *machine = (char *) NULL; + +/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN. */ +static enum bfd_endian endian = BFD_ENDIAN_UNKNOWN; /* The symbol table. */ -asymbol **syms; +static asymbol **syms; /* Number of symbols in `syms'. */ -long symcount = 0; +static long symcount = 0; /* The sorted symbol table. */ -asymbol **sorted_syms; +static asymbol **sorted_syms; /* Number of symbols in `sorted_syms'. */ -long sorted_symcount = 0; +static long sorted_symcount = 0; /* The dynamic symbol table. */ -asymbol **dynsyms; +static asymbol **dynsyms; /* Number of symbols in `dynsyms'. */ -long dynsymcount = 0; +static long dynsymcount = 0; /* Forward declarations. */ @@ -112,7 +115,7 @@ static void dump_dynamic_relocs PARAMS ((bfd * abfd)); static void -dump_reloc_set PARAMS ((bfd *, arelent **, long)); +dump_reloc_set PARAMS ((bfd *, asection *, arelent **, long)); static void dump_symbols PARAMS ((bfd *abfd, boolean dynamic)); @@ -132,7 +135,7 @@ show_line PARAMS ((bfd *, asection *, bfd_vma)); static const char * endian_string PARAMS ((enum bfd_endian)); -void +static void usage (stream, status) FILE *stream; int status; @@ -148,7 +151,7 @@ Usage: %s [-ahifdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\ [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\ [--wide] [--version] [--help] [--private-headers]\n\ [--start-address=addr] [--stop-address=addr]\n\ - [--show-raw-insn] objfile...\n\ + [--show-raw-insn] [-EB|-EL] [--endian={big|little}] objfile...\n\ at least one option besides -l (--line-numbers) must be given\n"); list_supported_targets (program_name, stream); exit (status); @@ -156,7 +159,8 @@ at least one option besides -l (--line-numbers) must be given\n"); /* 150 isn't special; it's just an arbitrary non-ASCII char value. */ -#define OPTION_START_ADDRESS (150) +#define OPTION_ENDIAN (150) +#define OPTION_START_ADDRESS (OPTION_ENDIAN + 1) #define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1) static struct option long_options[]= @@ -170,6 +174,7 @@ static struct option long_options[]= {"disassemble-all", no_argument, NULL, 'D'}, {"dynamic-reloc", no_argument, NULL, 'R'}, {"dynamic-syms", no_argument, NULL, 'T'}, + {"endian", required_argument, NULL, OPTION_ENDIAN}, {"file-headers", no_argument, NULL, 'f'}, {"full-contents", no_argument, NULL, 's'}, {"headers", no_argument, NULL, 'h'}, @@ -347,7 +352,7 @@ slurp_dynamic_symtab (abfd) COUNT is the number of elements in SYMBOLS. Return the number of useful symbols. */ -long +static long remove_useless_symbols (symbols, count) asymbol **symbols; long count; @@ -905,7 +910,7 @@ objdump_sprintf (va_alist) } #endif -void +static void disassemble_data (abfd) bfd *abfd; { @@ -950,6 +955,16 @@ disassemble_data (abfd) abfd->arch_info = info; } + if (endian != BFD_ENDIAN_UNKNOWN) + { + struct bfd_target *xvec; + + xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target)); + memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); + xvec->byteorder = endian; + abfd->xvec = xvec; + } + disassemble_fn = disassembler (abfd); if (!disassemble_fn) { @@ -1050,8 +1065,13 @@ disassemble_data (abfd) int bytes; boolean need_nl = false; - if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && - data[i + 3] == 0) + if (data[i] == 0 + && (i + 1 >= stop + || (data[i + 1] == 0 + && (i + 2 >= stop + || (data[i + 2] == 0 + && (i + 3 >= stop + || data[i + 3] == 0)))))) { if (done_dot == false) { @@ -1166,14 +1186,13 @@ disassemble_data (abfd) could be a direct-mapped table, but instead we build one the first time we need it. */ -void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name, - char *strsect_name)); +static void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name, + char *strsect_name)); /* Dump the stabs sections from an object file that has a section that - uses Sun stabs encoding. It has to use some hooks into BFD because - string table sections are not normally visible to BFD callers. */ + uses Sun stabs encoding. */ -void +static void dump_stabs (abfd) bfd *abfd; { @@ -1183,7 +1202,7 @@ dump_stabs (abfd) dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); } -static struct internal_nlist *stabs; +static bfd_byte *stabs; static bfd_size_type stab_size; static char *strtab; @@ -1194,7 +1213,7 @@ static bfd_size_type stabstr_size; If the section exists and was read, allocate the space and return true. Otherwise return false. */ -boolean +static boolean read_section_stabs (abfd, stabsect_name, strsect_name) bfd *abfd; char *stabsect_name; @@ -1220,7 +1239,7 @@ read_section_stabs (abfd, stabsect_name, strsect_name) stab_size = bfd_section_size (abfd, stabsect); stabstr_size = bfd_section_size (abfd, stabstrsect); - stabs = (struct internal_nlist *) xmalloc (stab_size); + stabs = (bfd_byte *) xmalloc (stab_size); strtab = (char *) xmalloc (stabstr_size); if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_size)) @@ -1247,20 +1266,25 @@ read_section_stabs (abfd, stabsect_name, strsect_name) return true; } -#define SWAP_SYMBOL(symp, abfd) \ -{ \ - (symp)->n_strx = bfd_h_get_32(abfd, \ - (unsigned char *)&(symp)->n_strx); \ - (symp)->n_desc = bfd_h_get_16 (abfd, \ - (unsigned char *)&(symp)->n_desc); \ - (symp)->n_value = bfd_h_get_32 (abfd, \ - (unsigned char *)&(symp)->n_value); \ -} +/* Stabs entries use a 12 byte format: + 4 byte string table index + 1 byte stab type + 1 byte stab other field + 2 byte stab desc field + 4 byte stab value + FIXME: This will have to change for a 64 bit object format. */ + +#define STRDXOFF (0) +#define TYPEOFF (4) +#define OTHEROFF (5) +#define DESCOFF (6) +#define VALOFF (8) +#define STABSIZE (12) /* Print ABFD's stabs section STABSECT_NAME (in `stabs'), using string table section STRSECT_NAME (in `strtab'). */ -void +static void print_section_stabs (abfd, stabsect_name, strsect_name) bfd *abfd; char *stabsect_name; @@ -1268,8 +1292,10 @@ print_section_stabs (abfd, stabsect_name, strsect_name) { int i; unsigned file_string_table_offset = 0, next_file_string_table_offset = 0; - struct internal_nlist *stabp = stabs, - *stabs_end = (struct internal_nlist *) (stab_size + (char *) stabs); + bfd_byte *stabp, *stabs_end; + + stabp = stabs; + stabs_end = stabp + stab_size; printf ("Contents of %s section:\n\n", stabsect_name); printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); @@ -1279,41 +1305,50 @@ print_section_stabs (abfd, stabsect_name, strsect_name) We start the index at -1 because there is a dummy symbol on the front of stabs-in-{coff,elf} sections that supplies sizes. */ - for (i = -1; stabp < stabs_end; stabp++, i++) + for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++) { const char *name; + unsigned long strx; + unsigned char type, other; + unsigned short desc; + bfd_vma value; + + strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); + type = bfd_h_get_8 (abfd, stabp + TYPEOFF); + other = bfd_h_get_8 (abfd, stabp + OTHEROFF); + desc = bfd_h_get_16 (abfd, stabp + DESCOFF); + value = bfd_h_get_32 (abfd, stabp + VALOFF); - SWAP_SYMBOL (stabp, abfd); printf ("\n%-6d ", i); /* Either print the stab name, or, if unnamed, print its number again (makes consistent formatting for tools like awk). */ - name = bfd_get_stab_name (stabp->n_type); + name = bfd_get_stab_name (type); if (name != NULL) printf ("%-6s", name); - else if (stabp->n_type == N_UNDF) + else if (type == N_UNDF) printf ("HdrSym"); else - printf ("%-6d", stabp->n_type); - printf (" %-6d %-6d ", stabp->n_other, stabp->n_desc); - printf_vma (stabp->n_value); - printf (" %-6lu", stabp->n_strx); + printf ("%-6d", type); + printf (" %-6d %-6d ", other, desc); + printf_vma (value); + printf (" %-6lu", strx); /* Symbols with type == 0 (N_UNDF) specify the length of the string table associated with this file. We use that info to know how to relocate the *next* file's string table indices. */ - if (stabp->n_type == N_UNDF) + if (type == N_UNDF) { file_string_table_offset = next_file_string_table_offset; - next_file_string_table_offset += stabp->n_value; + next_file_string_table_offset += value; } else { /* Using the (possibly updated) string table offset, print the string (if any) associated with this symbol. */ - if ((stabp->n_strx + file_string_table_offset) < stabstr_size) - printf (" %s", &strtab[stabp->n_strx + file_string_table_offset]); + if ((strx + file_string_table_offset) < stabstr_size) + printf (" %s", &strtab[strx + file_string_table_offset]); else printf (" *"); } @@ -1321,7 +1356,7 @@ print_section_stabs (abfd, stabsect_name, strsect_name) printf ("\n\n"); } -void +static void dump_section_stabs (abfd, stabsect_name, strsect_name) bfd *abfd; char *stabsect_name; @@ -1335,8 +1370,15 @@ dump_section_stabs (abfd, stabsect_name, strsect_name) s != NULL; s = s->next) { - if (strncmp (stabsect_name, s->name, strlen (stabsect_name)) == 0 - && strncmp (strsect_name, s->name, strlen (strsect_name)) != 0) + int len; + + len = strlen (stabsect_name); + +/* If the prefix matches, and the files section name ends with a nul or a digit, + then we match. Ie: we want either an exact match or a a section followed by + a number. */ + if (strncmp (stabsect_name, s->name, len) == 0 + && (s->name[len] == '\000' || isdigit (s->name[len]))) { if (read_section_stabs (abfd, s->name, strsect_name)) { @@ -1381,6 +1423,7 @@ bfd *abfd; { bfd_print_private_bfd_data (abfd, stdout); } + static void display_bfd (abfd) bfd *abfd; @@ -1679,7 +1722,7 @@ dump_relocs (abfd) else { printf ("\n"); - dump_reloc_set (abfd, relpp, relcount); + dump_reloc_set (abfd, a, relpp, relcount); printf ("\n\n"); } free (relpp); @@ -1718,7 +1761,7 @@ dump_dynamic_relocs (abfd) else { printf ("\n"); - dump_reloc_set (abfd, relpp, relcount); + dump_reloc_set (abfd, (asection *) NULL, relpp, relcount); printf ("\n\n"); } free (relpp); @@ -1726,12 +1769,15 @@ dump_dynamic_relocs (abfd) } static void -dump_reloc_set (abfd, relpp, relcount) +dump_reloc_set (abfd, sec, relpp, relcount) bfd *abfd; + asection *sec; arelent **relpp; long relcount; { arelent **p; + char *last_filename, *last_functionname; + unsigned int last_line; /* Get column headers lined up reasonably. */ { @@ -1745,11 +1791,17 @@ dump_reloc_set (abfd, relpp, relcount) printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, ""); } + last_filename = NULL; + last_functionname = NULL; + last_line = 0; + for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--) { arelent *q = *p; - CONST char *sym_name; - CONST char *section_name; + const char *filename, *functionname; + unsigned int line; + const char *sym_name; + const char *section_name; if (start_address != (bfd_vma) -1 && q->address < start_address) @@ -1758,6 +1810,37 @@ dump_reloc_set (abfd, relpp, relcount) && q->address > stop_address) continue; + if (with_line_numbers + && sec != NULL + && bfd_find_nearest_line (abfd, sec, syms, q->address, + &filename, &functionname, &line)) + { + if (functionname != NULL + && (last_functionname == NULL + || strcmp (functionname, last_functionname) != 0)) + { + printf ("%s():\n", functionname); + if (last_functionname != NULL) + free (last_functionname); + last_functionname = xstrdup (functionname); + } + if (line > 0 + && (line != last_line + || (filename != NULL + && last_filename != NULL + && strcmp (filename, last_filename) != 0))) + { + printf ("%s:%u\n", filename == NULL ? "???" : filename, line); + last_line = line; + if (last_filename != NULL) + free (last_filename); + if (filename == NULL) + last_filename = NULL; + else + last_filename = xstrdup (filename); + } + } + if (q->sym_ptr_ptr && *q->sym_ptr_ptr) { sym_name = (*(q->sym_ptr_ptr))->name; @@ -1989,8 +2072,8 @@ main (argc, argv) bfd_init (); - while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:w", long_options, - (int *) 0)) + while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:wE:", + long_options, (int *) 0)) != EOF) { if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS) @@ -2073,6 +2156,29 @@ main (argc, argv) case OPTION_STOP_ADDRESS: stop_address = parse_vma (optarg, "--stop-address"); break; + case 'E': + if (strcmp (optarg, "B") == 0) + endian = BFD_ENDIAN_BIG; + else if (strcmp (optarg, "L") == 0) + endian = BFD_ENDIAN_LITTLE; + else + { + fprintf (stderr, "%s: unrecognized -E option\n", program_name); + usage (stderr, 1); + } + break; + case OPTION_ENDIAN: + if (strncmp (optarg, "big", strlen (optarg)) == 0) + endian = BFD_ENDIAN_BIG; + else if (strncmp (optarg, "little", strlen (optarg)) == 0) + endian = BFD_ENDIAN_LITTLE; + else + { + fprintf (stderr, "%s: unrecognized --endian type `%s'\n", + program_name, optarg); + usage (stderr, 1); + } + break; default: usage (stderr, 1); } |