|
|
@ -1,5 +1,5 @@ |
|
|
/* nm.c -- Describe symbol table of a rel file.
|
|
|
/* 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. |
|
|
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/stab_gnu.h" |
|
|
#include "aout/ranlib.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)); |
|
|
static void |
|
|
PROTO(static void, do_one_rel_file, (bfd *file)); |
|
|
print_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount)); |
|
|
PROTO(static unsigned int, filter_symbols, (bfd *file, asymbol **syms, |
|
|
|
|
|
unsigned long symcount)); |
|
|
|
|
|
|
|
|
|
|
|
PROTO(static void, print_symbols, (bfd *file, asymbol **syms, |
|
|
static void |
|
|
unsigned long symcount)); |
|
|
print_symdef_entry PARAMS ((bfd * abfd)); |
|
|
extern PROTO(int, (*sorters[2][2]), (char *x, char *y)); |
|
|
|
|
|
PROTO(static void, print_symdef_entry, (bfd * abfd)); |
|
|
|
|
|
|
|
|
|
|
|
/* Command options. */ |
|
|
/* 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 reverse_sort = 0; /* sort in downward(alpha or numeric) order */ |
|
|
int sort_numerically = 0; /* sort in numeric rather than alpha order */ |
|
|
int sort_numerically = 0; /* sort in numeric rather than alpha order */ |
|
|
int undefined_only = 0; /* print undefined symbols only */ |
|
|
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. */ |
|
|
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_name; |
|
|
extern char *program_version; |
|
|
extern char *program_version; |
|
|
extern char *target; |
|
|
extern char *target; |
|
|
|
|
|
extern int print_version; |
|
|
|
|
|
|
|
|
struct option long_options[] = { |
|
|
struct option long_options[] = { |
|
|
{"debug-syms", no_argument, &print_debug_syms, 1}, |
|
|
{"debug-syms", no_argument, &print_debug_syms, 1}, |
|
|
@ -64,6 +69,7 @@ struct option long_options[] = { |
|
|
{"reverse-sort", no_argument, &reverse_sort, 1}, |
|
|
{"reverse-sort", no_argument, &reverse_sort, 1}, |
|
|
{"target", optional_argument, (int *)NULL, 0}, |
|
|
{"target", optional_argument, (int *)NULL, 0}, |
|
|
{"undefined-only", no_argument, &undefined_only, 1}, |
|
|
{"undefined-only", no_argument, &undefined_only, 1}, |
|
|
|
|
|
{"version", no_argument, &show_version, 1}, |
|
|
{0, no_argument, 0, 0} |
|
|
{0, no_argument, 0, 0} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
@ -74,7 +80,7 @@ int show_names = 0; |
|
|
void |
|
|
void |
|
|
usage () |
|
|
usage () |
|
|
{ |
|
|
{ |
|
|
fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n", |
|
|
fprintf(stderr, "nm %s\nUsage: %s [-agnoprsuV] filename...\n", |
|
|
program_version, program_name); |
|
|
program_version, program_name); |
|
|
exit(0); |
|
|
exit(0); |
|
|
} |
|
|
} |
|
|
@ -91,7 +97,7 @@ main (argc, argv) |
|
|
|
|
|
|
|
|
bfd_init(); |
|
|
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) { |
|
|
switch (c) { |
|
|
case 'a': print_debug_syms = 1; break; |
|
|
case 'a': print_debug_syms = 1; break; |
|
|
case 'g': external_only = 1; break; |
|
|
case 'g': external_only = 1; break; |
|
|
@ -101,6 +107,7 @@ main (argc, argv) |
|
|
case 'r': reverse_sort = 1; break; |
|
|
case 'r': reverse_sort = 1; break; |
|
|
case 's': print_armap = 1; break; |
|
|
case 's': print_armap = 1; break; |
|
|
case 'u': undefined_only = 1; break; |
|
|
case 'u': undefined_only = 1; break; |
|
|
|
|
|
case 'V': show_version = 1; break; |
|
|
|
|
|
|
|
|
case 0: |
|
|
case 0: |
|
|
if (!strcmp("target",(long_options[option_index]).name)) { |
|
|
if (!strcmp("target",(long_options[option_index]).name)) { |
|
|
@ -114,6 +121,9 @@ main (argc, argv) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (show_version) |
|
|
|
|
|
printf ("%s version %s\n", program_name, program_version); |
|
|
|
|
|
|
|
|
/* Strangely, for the shell you should return only a nonzero value
|
|
|
/* Strangely, for the shell you should return only a nonzero value
|
|
|
on sucess -- the inverse of the C sense. */ |
|
|
on sucess -- the inverse of the C sense. */ |
|
|
|
|
|
|
|
|
@ -132,7 +142,7 @@ main (argc, argv) |
|
|
return retval; |
|
|
return retval; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** Display a file's stats */ |
|
|
/* Display a file's stats */ |
|
|
|
|
|
|
|
|
/* goto here is marginally cleaner than the nested if syntax */ |
|
|
/* goto here is marginally cleaner than the nested if syntax */ |
|
|
|
|
|
|
|
|
@ -148,18 +158,14 @@ display_file (filename) |
|
|
if (file == NULL) { |
|
|
if (file == NULL) { |
|
|
fprintf (stderr, "\n%s: can't open '%s'.\n", program_name, filename); |
|
|
fprintf (stderr, "\n%s: can't open '%s'.\n", program_name, filename); |
|
|
return false; |
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (bfd_check_format(file, bfd_object)) |
|
|
if (bfd_check_format(file, bfd_object)) |
|
|
{ |
|
|
{ |
|
|
if (show_names) { |
|
|
if (show_names) { |
|
|
printf ("\n%s:\n",filename); |
|
|
printf ("\n%s:\n",filename); |
|
|
} |
|
|
} |
|
|
do_one_rel_file (file); |
|
|
do_one_rel_file (file); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
else if (bfd_check_format (file, bfd_archive)) { |
|
|
else if (bfd_check_format (file, bfd_archive)) { |
|
|
if (!bfd_check_format (file, bfd_archive)) { |
|
|
if (!bfd_check_format (file, bfd_archive)) { |
|
|
@ -192,7 +198,6 @@ display_file (filename) |
|
|
retval = false; |
|
|
retval = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
closer: |
|
|
closer: |
|
|
if (bfd_close(file) == false) |
|
|
if (bfd_close(file) == false) |
|
|
bfd_fatal (filename); |
|
|
bfd_fatal (filename); |
|
|
@ -200,7 +205,49 @@ display_file (filename) |
|
|
return retval; |
|
|
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 |
|
|
static void |
|
|
do_one_rel_file (abfd) |
|
|
do_one_rel_file (abfd) |
|
|
bfd *abfd; |
|
|
bfd *abfd; |
|
|
@ -214,7 +261,6 @@ do_one_rel_file (abfd) |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
storage = get_symtab_upper_bound (abfd); |
|
|
storage = get_symtab_upper_bound (abfd); |
|
|
if (storage == 0) { |
|
|
if (storage == 0) { |
|
|
nosymz: |
|
|
nosymz: |
|
|
@ -243,55 +289,8 @@ do_one_rel_file (abfd) |
|
|
|
|
|
|
|
|
print_symbols (abfd, syms, symcount); |
|
|
print_symbols (abfd, syms, symcount); |
|
|
free (syms); |
|
|
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;
|
|
|
/* Choose which symbol entries to print;
|
|
|
compact them downward to get rid of the rest. |
|
|
compact them downward to get rid of the rest. |
|
|
Return the number of symbols to be printed. */ |
|
|
Return the number of symbols to be printed. */ |
|
|
@ -309,8 +308,6 @@ filter_symbols (abfd, syms, symcount) |
|
|
for (from = to = syms, src_count = 0; src_count <symcount; src_count++) { |
|
|
for (from = to = syms, src_count = 0; src_count <symcount; src_count++) { |
|
|
int keep = 0; |
|
|
int keep = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
flagword flags = (from[src_count])->flags; |
|
|
flagword flags = (from[src_count])->flags; |
|
|
sym = from[src_count]; |
|
|
sym = from[src_count]; |
|
|
if (undefined_only) { |
|
|
if (undefined_only) { |
|
|
@ -319,7 +316,6 @@ filter_symbols (abfd, syms, symcount) |
|
|
keep = ((flags & BSF_GLOBAL) |
|
|
keep = ((flags & BSF_GLOBAL) |
|
|
|| (sym->section == &bfd_und_section) |
|
|
|| (sym->section == &bfd_und_section) |
|
|
|| (sym->section == &bfd_com_section)); |
|
|
|| (sym->section == &bfd_com_section)); |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
keep = 1; |
|
|
keep = 1; |
|
|
} |
|
|
} |
|
|
|