summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/objdump.c266
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);
}
OpenPOWER on IntegriCloud