* objdump.c (dump_section_stabs): Fix test for stabs sections

ending with numbers.  This fixes a problem with .stab being
	confused with .stab.index.
This commit is contained in:
Stu Grossman 1996-07-22 15:49:34 +00:00
parent 396bf873e9
commit 18f39dfa12
2 changed files with 192 additions and 80 deletions

View file

@ -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> Wed Jul 10 13:32:28 1996 Ian Lance Taylor <ian@cygnus.com>
* stabs.c (stab_demangle_fund_type): Return a void * for a * stabs.c (stab_demangle_fund_type): Return a void * for a

View file

@ -42,32 +42,32 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern int fprintf PARAMS ((FILE *, const char *, ...)); extern int fprintf PARAMS ((FILE *, const char *, ...));
#endif #endif
char *default_target = NULL; /* default at runtime */ static char *default_target = NULL; /* default at runtime */
extern char *program_version; extern char *program_version;
int show_version = 0; /* show the version number */ static int show_version = 0; /* show the version number */
int dump_section_contents; /* -s */ static int dump_section_contents; /* -s */
int dump_section_headers; /* -h */ static int dump_section_headers; /* -h */
boolean dump_file_header; /* -f */ static boolean dump_file_header; /* -f */
int dump_symtab; /* -t */ static int dump_symtab; /* -t */
int dump_dynamic_symtab; /* -T */ static int dump_dynamic_symtab; /* -T */
int dump_reloc_info; /* -r */ static int dump_reloc_info; /* -r */
int dump_dynamic_reloc_info; /* -R */ static int dump_dynamic_reloc_info; /* -R */
int dump_ar_hdrs; /* -a */ static int dump_ar_hdrs; /* -a */
int dump_private_headers; /* -p */ static int dump_private_headers; /* -p */
int with_line_numbers; /* -l */ static int with_line_numbers; /* -l */
boolean with_source_code; /* -S */ static boolean with_source_code; /* -S */
int show_raw_insn; /* --show-raw-insn */ static int show_raw_insn; /* --show-raw-insn */
int dump_stab_section_info; /* --stabs */ static int dump_stab_section_info; /* --stabs */
boolean disassemble; /* -d */ static boolean disassemble; /* -d */
boolean disassemble_all; /* -D */ static boolean disassemble_all; /* -D */
boolean formats_info; /* -i */ static boolean formats_info; /* -i */
char *only; /* -j secname */ static char *only; /* -j secname */
int wide_output; /* -w */ static int wide_output; /* -w */
bfd_vma start_address = (bfd_vma) -1; /* --start-address */ static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
int dump_debugging; /* --debugging */ static int dump_debugging; /* --debugging */
/* Extra info to pass to the disassembler address printing function. */ /* Extra info to pass to the disassembler address printing function. */
struct objdump_disasm_info { struct objdump_disasm_info {
@ -77,25 +77,28 @@ struct objdump_disasm_info {
}; };
/* Architecture to disassemble for, or default if NULL. */ /* 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. */ /* The symbol table. */
asymbol **syms; static asymbol **syms;
/* Number of symbols in `syms'. */ /* Number of symbols in `syms'. */
long symcount = 0; static long symcount = 0;
/* The sorted symbol table. */ /* The sorted symbol table. */
asymbol **sorted_syms; static asymbol **sorted_syms;
/* Number of symbols in `sorted_syms'. */ /* Number of symbols in `sorted_syms'. */
long sorted_symcount = 0; static long sorted_symcount = 0;
/* The dynamic symbol table. */ /* The dynamic symbol table. */
asymbol **dynsyms; static asymbol **dynsyms;
/* Number of symbols in `dynsyms'. */ /* Number of symbols in `dynsyms'. */
long dynsymcount = 0; static long dynsymcount = 0;
/* Forward declarations. */ /* Forward declarations. */
@ -112,7 +115,7 @@ static void
dump_dynamic_relocs PARAMS ((bfd * abfd)); dump_dynamic_relocs PARAMS ((bfd * abfd));
static void static void
dump_reloc_set PARAMS ((bfd *, arelent **, long)); dump_reloc_set PARAMS ((bfd *, asection *, arelent **, long));
static void static void
dump_symbols PARAMS ((bfd *abfd, boolean dynamic)); dump_symbols PARAMS ((bfd *abfd, boolean dynamic));
@ -132,7 +135,7 @@ show_line PARAMS ((bfd *, asection *, bfd_vma));
static const char * static const char *
endian_string PARAMS ((enum bfd_endian)); endian_string PARAMS ((enum bfd_endian));
void static void
usage (stream, status) usage (stream, status)
FILE *stream; FILE *stream;
int status; 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\ [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\
[--wide] [--version] [--help] [--private-headers]\n\ [--wide] [--version] [--help] [--private-headers]\n\
[--start-address=addr] [--stop-address=addr]\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"); at least one option besides -l (--line-numbers) must be given\n");
list_supported_targets (program_name, stream); list_supported_targets (program_name, stream);
exit (status); 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. */ /* 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) #define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1)
static struct option long_options[]= static struct option long_options[]=
@ -170,6 +174,7 @@ static struct option long_options[]=
{"disassemble-all", no_argument, NULL, 'D'}, {"disassemble-all", no_argument, NULL, 'D'},
{"dynamic-reloc", no_argument, NULL, 'R'}, {"dynamic-reloc", no_argument, NULL, 'R'},
{"dynamic-syms", no_argument, NULL, 'T'}, {"dynamic-syms", no_argument, NULL, 'T'},
{"endian", required_argument, NULL, OPTION_ENDIAN},
{"file-headers", no_argument, NULL, 'f'}, {"file-headers", no_argument, NULL, 'f'},
{"full-contents", no_argument, NULL, 's'}, {"full-contents", no_argument, NULL, 's'},
{"headers", no_argument, NULL, 'h'}, {"headers", no_argument, NULL, 'h'},
@ -347,7 +352,7 @@ slurp_dynamic_symtab (abfd)
COUNT is the number of elements in SYMBOLS. COUNT is the number of elements in SYMBOLS.
Return the number of useful symbols. */ Return the number of useful symbols. */
long static long
remove_useless_symbols (symbols, count) remove_useless_symbols (symbols, count)
asymbol **symbols; asymbol **symbols;
long count; long count;
@ -905,7 +910,7 @@ objdump_sprintf (va_alist)
} }
#endif #endif
void static void
disassemble_data (abfd) disassemble_data (abfd)
bfd *abfd; bfd *abfd;
{ {
@ -950,6 +955,16 @@ disassemble_data (abfd)
abfd->arch_info = info; 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); disassemble_fn = disassembler (abfd);
if (!disassemble_fn) if (!disassemble_fn)
{ {
@ -1050,8 +1065,13 @@ disassemble_data (abfd)
int bytes; int bytes;
boolean need_nl = false; boolean need_nl = false;
if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && if (data[i] == 0
data[i + 3] == 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) if (done_dot == false)
{ {
@ -1166,14 +1186,13 @@ disassemble_data (abfd)
could be a direct-mapped table, but instead we build one the first could be a direct-mapped table, but instead we build one the first
time we need it. */ time we need it. */
void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name, static void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name,
char *strsect_name)); char *strsect_name));
/* Dump the stabs sections from an object file that has a section that /* 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 uses Sun stabs encoding. */
string table sections are not normally visible to BFD callers. */
void static void
dump_stabs (abfd) dump_stabs (abfd)
bfd *abfd; bfd *abfd;
{ {
@ -1183,7 +1202,7 @@ dump_stabs (abfd)
dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$");
} }
static struct internal_nlist *stabs; static bfd_byte *stabs;
static bfd_size_type stab_size; static bfd_size_type stab_size;
static char *strtab; 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. If the section exists and was read, allocate the space and return true.
Otherwise return false. */ Otherwise return false. */
boolean static boolean
read_section_stabs (abfd, stabsect_name, strsect_name) read_section_stabs (abfd, stabsect_name, strsect_name)
bfd *abfd; bfd *abfd;
char *stabsect_name; char *stabsect_name;
@ -1220,7 +1239,7 @@ read_section_stabs (abfd, stabsect_name, strsect_name)
stab_size = bfd_section_size (abfd, stabsect); stab_size = bfd_section_size (abfd, stabsect);
stabstr_size = bfd_section_size (abfd, stabstrsect); 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); strtab = (char *) xmalloc (stabstr_size);
if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_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; return true;
} }
#define SWAP_SYMBOL(symp, abfd) \ /* Stabs entries use a 12 byte format:
{ \ 4 byte string table index
(symp)->n_strx = bfd_h_get_32(abfd, \ 1 byte stab type
(unsigned char *)&(symp)->n_strx); \ 1 byte stab other field
(symp)->n_desc = bfd_h_get_16 (abfd, \ 2 byte stab desc field
(unsigned char *)&(symp)->n_desc); \ 4 byte stab value
(symp)->n_value = bfd_h_get_32 (abfd, \ FIXME: This will have to change for a 64 bit object format. */
(unsigned char *)&(symp)->n_value); \
} #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'), /* Print ABFD's stabs section STABSECT_NAME (in `stabs'),
using string table section STRSECT_NAME (in `strtab'). */ using string table section STRSECT_NAME (in `strtab'). */
void static void
print_section_stabs (abfd, stabsect_name, strsect_name) print_section_stabs (abfd, stabsect_name, strsect_name)
bfd *abfd; bfd *abfd;
char *stabsect_name; char *stabsect_name;
@ -1268,8 +1292,10 @@ print_section_stabs (abfd, stabsect_name, strsect_name)
{ {
int i; int i;
unsigned file_string_table_offset = 0, next_file_string_table_offset = 0; unsigned file_string_table_offset = 0, next_file_string_table_offset = 0;
struct internal_nlist *stabp = stabs, bfd_byte *stabp, *stabs_end;
*stabs_end = (struct internal_nlist *) (stab_size + (char *) stabs);
stabp = stabs;
stabs_end = stabp + stab_size;
printf ("Contents of %s section:\n\n", stabsect_name); printf ("Contents of %s section:\n\n", stabsect_name);
printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); 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 We start the index at -1 because there is a dummy symbol on
the front of stabs-in-{coff,elf} sections that supplies sizes. */ 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; 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); printf ("\n%-6d ", i);
/* Either print the stab name, or, if unnamed, print its number /* Either print the stab name, or, if unnamed, print its number
again (makes consistent formatting for tools like awk). */ 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) if (name != NULL)
printf ("%-6s", name); printf ("%-6s", name);
else if (stabp->n_type == N_UNDF) else if (type == N_UNDF)
printf ("HdrSym"); printf ("HdrSym");
else else
printf ("%-6d", stabp->n_type); printf ("%-6d", type);
printf (" %-6d %-6d ", stabp->n_other, stabp->n_desc); printf (" %-6d %-6d ", other, desc);
printf_vma (stabp->n_value); printf_vma (value);
printf (" %-6lu", stabp->n_strx); printf (" %-6lu", strx);
/* Symbols with type == 0 (N_UNDF) specify the length of the /* Symbols with type == 0 (N_UNDF) specify the length of the
string table associated with this file. We use that info string table associated with this file. We use that info
to know how to relocate the *next* file's string table indices. */ 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; file_string_table_offset = next_file_string_table_offset;
next_file_string_table_offset += stabp->n_value; next_file_string_table_offset += value;
} }
else else
{ {
/* Using the (possibly updated) string table offset, print the /* Using the (possibly updated) string table offset, print the
string (if any) associated with this symbol. */ string (if any) associated with this symbol. */
if ((stabp->n_strx + file_string_table_offset) < stabstr_size) if ((strx + file_string_table_offset) < stabstr_size)
printf (" %s", &strtab[stabp->n_strx + file_string_table_offset]); printf (" %s", &strtab[strx + file_string_table_offset]);
else else
printf (" *"); printf (" *");
} }
@ -1321,7 +1356,7 @@ print_section_stabs (abfd, stabsect_name, strsect_name)
printf ("\n\n"); printf ("\n\n");
} }
void static void
dump_section_stabs (abfd, stabsect_name, strsect_name) dump_section_stabs (abfd, stabsect_name, strsect_name)
bfd *abfd; bfd *abfd;
char *stabsect_name; char *stabsect_name;
@ -1335,8 +1370,15 @@ dump_section_stabs (abfd, stabsect_name, strsect_name)
s != NULL; s != NULL;
s = s->next) s = s->next)
{ {
if (strncmp (stabsect_name, s->name, strlen (stabsect_name)) == 0 int len;
&& strncmp (strsect_name, s->name, strlen (strsect_name)) != 0)
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)) if (read_section_stabs (abfd, s->name, strsect_name))
{ {
@ -1381,6 +1423,7 @@ bfd *abfd;
{ {
bfd_print_private_bfd_data (abfd, stdout); bfd_print_private_bfd_data (abfd, stdout);
} }
static void static void
display_bfd (abfd) display_bfd (abfd)
bfd *abfd; bfd *abfd;
@ -1679,7 +1722,7 @@ dump_relocs (abfd)
else else
{ {
printf ("\n"); printf ("\n");
dump_reloc_set (abfd, relpp, relcount); dump_reloc_set (abfd, a, relpp, relcount);
printf ("\n\n"); printf ("\n\n");
} }
free (relpp); free (relpp);
@ -1718,7 +1761,7 @@ dump_dynamic_relocs (abfd)
else else
{ {
printf ("\n"); printf ("\n");
dump_reloc_set (abfd, relpp, relcount); dump_reloc_set (abfd, (asection *) NULL, relpp, relcount);
printf ("\n\n"); printf ("\n\n");
} }
free (relpp); free (relpp);
@ -1726,12 +1769,15 @@ dump_dynamic_relocs (abfd)
} }
static void static void
dump_reloc_set (abfd, relpp, relcount) dump_reloc_set (abfd, sec, relpp, relcount)
bfd *abfd; bfd *abfd;
asection *sec;
arelent **relpp; arelent **relpp;
long relcount; long relcount;
{ {
arelent **p; arelent **p;
char *last_filename, *last_functionname;
unsigned int last_line;
/* Get column headers lined up reasonably. */ /* 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, ""); 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--) for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--)
{ {
arelent *q = *p; arelent *q = *p;
CONST char *sym_name; const char *filename, *functionname;
CONST char *section_name; unsigned int line;
const char *sym_name;
const char *section_name;
if (start_address != (bfd_vma) -1 if (start_address != (bfd_vma) -1
&& q->address < start_address) && q->address < start_address)
@ -1758,6 +1810,37 @@ dump_reloc_set (abfd, relpp, relcount)
&& q->address > stop_address) && q->address > stop_address)
continue; 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) if (q->sym_ptr_ptr && *q->sym_ptr_ptr)
{ {
sym_name = (*(q->sym_ptr_ptr))->name; sym_name = (*(q->sym_ptr_ptr))->name;
@ -1989,8 +2072,8 @@ main (argc, argv)
bfd_init (); bfd_init ();
while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:w", long_options, while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:wE:",
(int *) 0)) long_options, (int *) 0))
!= EOF) != EOF)
{ {
if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS) if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS)
@ -2073,6 +2156,29 @@ main (argc, argv)
case OPTION_STOP_ADDRESS: case OPTION_STOP_ADDRESS:
stop_address = parse_vma (optarg, "--stop-address"); stop_address = parse_vma (optarg, "--stop-address");
break; 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: default:
usage (stderr, 1); usage (stderr, 1);
} }