/* nm.c -- Describe symbol table of a rel file.
- Copyright (C) 1991 Free Software Foundation, Inc.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "aout/stab_gnu.h"
#include "aout/ranlib.h"
+static boolean
+display_file PARAMS ((char *filename));
+
+static void
+do_one_rel_file PARAMS ((bfd *file));
+static unsigned int
+filter_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount));
-PROTO(static boolean, display_file, (char *filename));
-PROTO(static void, do_one_rel_file, (bfd *file));
-PROTO(static unsigned int, filter_symbols, (bfd *file, asymbol **syms,
- unsigned long symcount));
+static void
+print_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount));
-PROTO(static void, print_symbols, (bfd *file, asymbol **syms,
- unsigned long symcount));
-extern PROTO(int, (*sorters[2][2]), (char *x, char *y));
-PROTO(static void, print_symdef_entry, (bfd * abfd));
+static void
+print_symdef_entry PARAMS ((bfd * abfd));
/* Command options. */
int reverse_sort = 0; /* sort in downward(alpha or numeric) order */
int sort_numerically = 0; /* sort in numeric rather than alpha order */
int undefined_only = 0; /* print undefined symbols only */
+int show_version = 0; /* show the version number */
boolean print_each_filename = false; /* Ick. Used in archives. */
extern char *program_name;
extern char *program_version;
extern char *target;
+extern int print_version;
struct option long_options[] = {
{"debug-syms", no_argument, &print_debug_syms, 1},
{"reverse-sort", no_argument, &reverse_sort, 1},
{"target", optional_argument, (int *)NULL, 0},
{"undefined-only", no_argument, &undefined_only, 1},
+ {"version", no_argument, &show_version, 1},
{0, no_argument, 0, 0}
};
void
usage ()
{
- fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n",
+ fprintf(stderr, "nm %s\nUsage: %s [-agnoprsuV] filename...\n",
program_version, program_name);
exit(0);
}
{
int c; /* sez which option char */
int option_index = 0; /* used by getopt and ignored by us */
- int retval;
+ int retval;
program_name = *argv;
bfd_init();
- while ((c = getopt_long(argc, argv, "agnoprsu", long_options, &option_index)) != EOF) {
+ while ((c = getopt_long(argc, argv, "agnoprsuV", long_options, &option_index)) != EOF) {
switch (c) {
case 'a': print_debug_syms = 1; break;
case 'g': external_only = 1; break;
case 'r': reverse_sort = 1; break;
case 's': print_armap = 1; break;
case 'u': undefined_only = 1; break;
-
+ case 'V': show_version = 1; break;
+
case 0:
if (!strcmp("target",(long_options[option_index]).name)) {
target = optarg;
}
-
+
break; /* we've been given a long option */
-
+
default:
usage ();
}
}
-
+
+ if (show_version)
+ printf ("%s version %s\n", program_name, program_version);
+
/* Strangely, for the shell you should return only a nonzero value
on sucess -- the inverse of the C sense. */
-
+
/* OK, all options now parsed. If no filename specified, do a.out. */
if (option_index == argc) return !display_file ("a.out");
-
+
retval = 0;
show_names = (argc -optind)>1;
/* We were given several filenames to do: */
return retval;
}
\f
-/** Display a file's stats */
+/* Display a file's stats */
/* goto here is marginally cleaner than the nested if syntax */
boolean retval = true;
bfd *file;
bfd *arfile = NULL;
-
+
file = bfd_openr(filename, target);
if (file == NULL) {
fprintf (stderr, "\n%s: can't open '%s'.\n", program_name, filename);
return false;
-
-
}
-
- if (bfd_check_format(file, bfd_object))
+ if (bfd_check_format(file, bfd_object))
{
if (show_names) {
printf ("\n%s:\n",filename);
}
do_one_rel_file (file);
-
}
else if (bfd_check_format (file, bfd_archive)) {
if (!bfd_check_format (file, bfd_archive)) {
bfd_fatal (filename);
goto closer;
}
-
+
if (!bfd_check_format(arfile, bfd_object))
printf("%s: not an object file\n", arfile->filename);
else {
retval = false;
}
-
closer:
if (bfd_close(file) == false)
bfd_fatal (filename);
return retval;
}
\f
+/* Symbol-sorting predicates */
+#define valueof(x) ((x)->section->vma + (x)->value)
+int
+numeric_forward (x, y)
+ CONST void *x;
+ CONST void *y;
+{
+ return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y));
+}
+
+int
+numeric_reverse (x, y)
+ CONST void *x;
+ CONST void *y;
+{
+ return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x));
+}
+
+int
+non_numeric_forward (x, y)
+ CONST void *x;
+ CONST void *y;
+{
+ CONST char *xn = (*(asymbol **) x)->name;
+ CONST char *yn = (*(asymbol **) y)->name;
+
+ return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
+ ((yn == NULL) ? 1 : strcmp (xn, yn)));
+}
+
+int
+non_numeric_reverse (x, y)
+ CONST void *x;
+ CONST void *y;
+{
+ return -(non_numeric_forward (x, y));
+}
+int (*(sorters[2][2])) PARAMS ((CONST void *, CONST void *)) = {
+ {non_numeric_forward, non_numeric_reverse},
+ {numeric_forward, numeric_reverse},
+};
+\f
static void
do_one_rel_file (abfd)
bfd *abfd;
return;
}
-
storage = get_symtab_upper_bound (abfd);
if (storage == 0) {
nosymz:
(after printing) */
symcount = filter_symbols (abfd, syms, symcount);
-
- if (!no_sort)
+
+ if (!no_sort)
qsort((char *) syms, symcount, sizeof (asymbol *),
sorters[sort_numerically][reverse_sort]);
if (print_each_filename && !file_on_each_line)
printf("\n%s:\n", bfd_get_filename(abfd));
-
+
print_symbols (abfd, syms, symcount);
free (syms);
-
}
\f
-/* Symbol-sorting predicates */
-#define valueof(x) ((x)->section->vma + (x)->value)
-int
-numeric_forward (x, y)
- char *x;
- char *y;
-{
-
- return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y));;
-}
-
-int
-numeric_reverse (x, y)
- char *x;
- char *y;
-{
- return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x));
-
-}
-
-int
-non_numeric_forward (x, y)
- char *x;
- char *y;
-{
- CONST char *xn = (*(asymbol **) x)->name;
- CONST char *yn = (*(asymbol **) y)->name;
-
- return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
- ((yn == NULL) ? 1 : strcmp (xn, yn)));
-}
-
-int
-non_numeric_reverse (x, y)
- char *x;
- char *y;
-{
- return -(non_numeric_forward (x, y));
-}
-
-int (*sorters[2][2])() = {
- {non_numeric_forward, non_numeric_reverse},
- {numeric_forward, numeric_reverse},
-};
-\f
-
/* Choose which symbol entries to print;
compact them downward to get rid of the rest.
Return the number of symbols to be printed. */
asymbol **from, **to;
unsigned int dst_count = 0;
asymbol *sym;
-
+
unsigned int src_count;
for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
int keep = 0;
-
-
flagword flags = (from[src_count])->flags;
sym = from[src_count];
if (undefined_only) {
keep = sym->section == &bfd_und_section;
} else if (external_only) {
- keep = ((flags & BSF_GLOBAL)
- || (sym->section == &bfd_und_section)
+ keep = ((flags & BSF_GLOBAL)
+ || (sym->section == &bfd_und_section)
|| (sym->section == &bfd_com_section));
-
} else {
keep = 1;
}
-
+
if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) {
keep = 0;
}
to[dst_count++] = from[src_count];
}
}
-
+
return dst_count;
}
\f
}
elt = bfd_get_elt_at_index (abfd, idx);
if (thesym->name != (char *)NULL) {
- printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
-}
+ printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
+ }
}
}
char *default_target = NULL; /* default at runtime */
+extern *program_version;
char *program_name = NULL;
+int show_version = 0; /* show the version number */
int dump_section_contents; /* -s */
int dump_section_headers; /* -h */
boolean dump_file_header; /* -f */
{"syms", no_argument, &dump_symtab, 1},
{"reloc", no_argument, &dump_reloc_info, 1},
{"header", no_argument, &dump_section_headers, 1},
+ {"version", no_argument, &show_version, 1},
#ifdef ELF_STAB_DISPLAY
{"stabs", no_argument, &dump_stab_section_info, 1},
#endif
{0, 0}
};
+void dump_elf_stabs_1 ();
+
/* This is a kludge for dumping the stabs section from an ELF file that
uses Sun stabs encoding. It has to use some hooks into BFD because
string table sections are not normally visible to BFD callers. */
dump_elf_stabs (abfd)
bfd *abfd;
{
- Elf_Internal_Shdr *stab_hdr, *stabstr_hdr;
- char *strtab;
- struct internal_nlist *stabs, *stabs_end;
- int i, j;
+ int i;
/* Initialize stab name array if first time. */
if (stab_name[0][0] == 0)
return;
}
- stab_hdr = bfd_elf_find_section (abfd, ".stab");
+ dump_elf_stabs_1 (abfd, ".stab", ".stabstr");
+ dump_elf_stabs_1 (abfd, ".stab.excl", ".stab.exclstr");
+ dump_elf_stabs_1 (abfd, ".stab.index", ".stab.indexstr");
+}
+
+void
+dump_elf_stabs_1 (abfd, name1, name2)
+ bfd *abfd;
+ char *name1; /* Section name of .stab */
+ char *name2; /* Section name of its string section */
+{
+ Elf_Internal_Shdr *stab_hdr, *stabstr_hdr;
+ char *strtab;
+ struct internal_nlist *stabs, *stabs_end;
+ int i;
+ unsigned file_string_table_offset, next_file_string_table_offset;
+
+ stab_hdr = bfd_elf_find_section (abfd, name1);
if (0 == stab_hdr)
{
- fprintf (stderr, "%s: %s has no .stab section.\n", program_name,
- abfd->filename);
+ printf ("Contents of %s section: none.\n\n", name1);
return;
}
- stabstr_hdr = bfd_elf_find_section (abfd, ".stabstr");
+ stabstr_hdr = bfd_elf_find_section (abfd, name2);
if (0 == stabstr_hdr)
{
- fprintf (stderr, "%s: %s has no .stabstr section.\n", program_name,
- abfd->filename);
+ fprintf (stderr, "%s: %s has no %s section.\n", program_name,
+ abfd->filename, name2);
return;
}
if (bfd_seek (abfd, stab_hdr->sh_offset, L_SET) < 0 ||
stab_hdr->sh_size != bfd_read ((PTR)stabs, stab_hdr->sh_size, 1, abfd))
{
- fprintf (stderr, "%s: reading .stab section of %s failed.\n",
- program_name,
+ fprintf (stderr, "%s: reading %s section of %s failed.\n",
+ program_name, name1,
abfd->filename);
return;
}
stabstr_hdr->sh_size != bfd_read ((PTR)strtab, stabstr_hdr->sh_size,
1, abfd))
{
- fprintf (stderr, "%s: reading .stabstr section of %s failed.\n",
- program_name,
+ fprintf (stderr, "%s: reading %s section of %s failed.\n",
+ program_name, name2,
abfd->filename);
return;
}
(unsigned char *)&(symp)->n_value); \
}
- printf ("Contents of .stab section:\n\n");
+ printf ("Contents of %s section:\n\n", name1);
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
+ file_string_table_offset = 0;
+ next_file_string_table_offset = 0;
+
+ /* Loop through all symbols and print them.
+
+ We start the index at -1 because there is a dummy symbol on
the front of Sun's stabs-in-elf sections. */
+
for (i = -1; stabs < stabs_end; stabs++, i++)
{
SWAP_SYMBOL (stabs, abfd);
stab_name [stabs->n_type],
stabs->n_other, stabs->n_desc, stabs->n_value,
stabs->n_strx);
- if (stabs->n_strx < stabstr_hdr->sh_size)
- printf (" %s", &strtab[stabs->n_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 (stabs->n_type == N_UNDF)
+ {
+ file_string_table_offset = next_file_string_table_offset;
+ next_file_string_table_offset += stabs->n_value;
+ }
+
+ /* Now, using the possibly updated string table offset, print the
+ string (if any) associated with this symbol. */
+
+ if ((stabs->n_strx + file_string_table_offset) < stabstr_hdr->sh_size)
+ printf (" %s", &strtab[stabs->n_strx + file_string_table_offset]);
+ else
+ printf (" *");
}
printf ("\n\n");
}
#endif /* ELF_STAB_DISPLAY */
-\f
-void
+
display_bfd (abfd)
bfd *abfd;
{
PF (DYNAMIC, "DYNAMIC");
PF (WP_TEXT, "WP_TEXT");
PF (D_PAGED, "D_PAGED");
+ PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
printf ("\nstart address 0x");
printf_vma (abfd->start_address);
}
bfd_target *p = target_vector[i];
bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
int l = strlen (p->name);
- int ok = bfd_set_arch_mach (abfd, j, 0);
+ int ok;
+ bfd_set_format (abfd, bfd_object);
+ ok = bfd_set_arch_mach (abfd, j, 0);
if (ok)
printf ("%s ", p->name);
{
bfd_target *p = target_vector[i];
bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
-
+ bfd_set_format (abfd, bfd_object);
printf ("%s\n (header %s, data %s)\n", p->name,
p->header_byteorder_big_p ? "big endian" : "little endian",
p->byteorder_big_p ? "big endian" : "little endian");
bfd_init ();
program_name = *argv;
- while ((c = getopt_long (argc, argv, "ib:m:dlfahrtxsj:", long_options, &ind))
+ while ((c = getopt_long (argc, argv, "ib:m:Vdlfahrtxsj:", long_options, &ind))
!= EOF)
{
seenflag = true;
case 'h':
dump_section_headers = 1;
break;
+ case 'V':
+ show_version = 1;
+ break;
default:
usage ();
}
}
+ if (show_version)
+ printf ("%s version %s\n", program_name, program_version);
+
if (seenflag == false)
usage ();