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 {
};
/* 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. */
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));
static const char *
endian_string PARAMS ((enum bfd_endian));
\f
-void
+static void
usage (stream, status)
FILE *stream;
int status;
[--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);
/* 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[]=
{"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'},
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;
}
#endif
-void
+static void
disassemble_data (abfd)
bfd *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)
{
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)
{
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;
{
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;
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;
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))
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;
{
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");
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 (" *");
}
printf ("\n\n");
}
-void
+static void
dump_section_stabs (abfd, stabsect_name, strsect_name)
bfd *abfd;
char *stabsect_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))
{
{
bfd_print_private_bfd_data (abfd, stdout);
}
+
static void
display_bfd (abfd)
bfd *abfd;
else
{
printf ("\n");
- dump_reloc_set (abfd, relpp, relcount);
+ dump_reloc_set (abfd, a, relpp, relcount);
printf ("\n\n");
}
free (relpp);
else
{
printf ("\n");
- dump_reloc_set (abfd, relpp, relcount);
+ dump_reloc_set (abfd, (asection *) NULL, relpp, relcount);
printf ("\n\n");
}
free (relpp);
}
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. */
{
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)
&& 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;
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)
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);
}