Added +version (-V) option to print version number.

This commit is contained in:
Rob Savoye 1992-08-19 03:25:51 +00:00
parent 8fb94c7a78
commit 249c6fc0d6
2 changed files with 155 additions and 111 deletions

View File

@ -1,5 +1,5 @@
/* 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.
@ -24,17 +24,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#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));
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 unsigned int
filter_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_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount));
static void
print_symdef_entry PARAMS ((bfd * abfd));
/* Command options. */
@ -46,6 +49,7 @@ int print_armap = 0; /* describe __.SYMDEF data in archive files. */
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. */
@ -53,6 +57,7 @@ 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},
@ -64,6 +69,7 @@ struct option long_options[] = {
{"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}
};
@ -74,7 +80,7 @@ int show_names = 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);
}
@ -86,12 +92,12 @@ main (argc, argv)
{
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;
@ -101,25 +107,29 @@ main (argc, argv)
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: */
@ -132,7 +142,7 @@ main (argc, argv)
return retval;
}
/** Display a file's stats */
/* Display a file's stats */
/* goto here is marginally cleaner than the nested if syntax */
@ -143,23 +153,19 @@ display_file (filename)
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)) {
@ -178,7 +184,7 @@ display_file (filename)
bfd_fatal (filename);
goto closer;
}
if (!bfd_check_format(arfile, bfd_object))
printf("%s: not an object file\n", arfile->filename);
else {
@ -192,7 +198,6 @@ display_file (filename)
retval = false;
}
closer:
if (bfd_close(file) == false)
bfd_fatal (filename);
@ -200,7 +205,49 @@ display_file (filename)
return retval;
}
/* 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},
};
static void
do_one_rel_file (abfd)
bfd *abfd;
@ -214,7 +261,6 @@ do_one_rel_file (abfd)
return;
}
storage = get_symtab_upper_bound (abfd);
if (storage == 0) {
nosymz:
@ -233,65 +279,18 @@ do_one_rel_file (abfd)
(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);
}
/* 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},
};
/* Choose which symbol entries to print;
compact them downward to get rid of the rest.
Return the number of symbols to be printed. */
@ -304,26 +303,23 @@ filter_symbols (abfd, syms, symcount)
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;
}
@ -332,7 +328,7 @@ filter_symbols (abfd, syms, symcount)
to[dst_count++] = from[src_count];
}
}
return dst_count;
}
@ -379,7 +375,7 @@ print_symdef_entry (abfd)
}
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));
}
}
}

View File

@ -45,8 +45,10 @@ char *xmalloc ();
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 */
@ -94,6 +96,7 @@ static struct option long_options[]=
{"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
@ -476,6 +479,8 @@ struct stab_print stab_print[] = {
{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. */
@ -484,10 +489,7 @@ void
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)
@ -508,19 +510,35 @@ dump_elf_stabs (abfd)
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;
}
@ -531,8 +549,8 @@ dump_elf_stabs (abfd)
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;
}
@ -541,8 +559,8 @@ dump_elf_stabs (abfd)
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;
}
@ -557,11 +575,17 @@ dump_elf_stabs (abfd)
(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);
@ -569,14 +593,29 @@ dump_elf_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 */
void
display_bfd (abfd)
bfd *abfd;
{
@ -610,6 +649,7 @@ display_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);
}
@ -881,7 +921,9 @@ DEFUN (display_info_table, (first, last),
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);
@ -909,7 +951,7 @@ DEFUN_VOID (display_info)
{
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");
@ -952,7 +994,7 @@ main (argc, argv)
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;
@ -1003,11 +1045,17 @@ main (argc, argv)
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 ();