X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/2fa0b342a5cd580781d2b9348a87f33a92d363fa..6cfbdb50e6f3b1ba38be0c8d72c98467c87aed1a:/binutils/nm.c diff --git a/binutils/nm.c b/binutils/nm.c index ac490f7259..4fe3e58eb5 100644 --- a/binutils/nm.c +++ b/binutils/nm.c @@ -1,21 +1,44 @@ -/*** nm.c -- Describe symbol table of a rel file. */ -#include "sysdep.h" +/* nm.c -- Describe symbol table of a rel file. + Copyright 1991, 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include "bfd.h" +#include "sysdep.h" +#include "bucomm.h" #include "getopt.h" -#include "stab.gnu.h" -#include +#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, bfd *archive)); +static unsigned int +filter_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount)); -PROTO(static boolean, display_file, (char *filename)); -PROTO(static boolean, 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, + bfd *archive)); -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. */ @@ -27,6 +50,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. */ @@ -34,28 +58,35 @@ 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", 0, &print_debug_syms, 1}, - {"extern-only", 0, &external_only, 1}, - {"no-sort", 0, &no_sort, 1}, - {"numeric-sort", 0, &sort_numerically, 1}, - {"print-armap", 0, &print_armap, 1}, - {"print-file-name", 0, &file_on_each_line, 1}, - {"reverse-sort", 0, &reverse_sort, 1}, - {"target", 2, NULL, NULL}, - {"undefined-only", 0, &undefined_only, 1}, - {0, 0, 0, 0} + {"debug-syms", no_argument, &print_debug_syms, 1}, + {"extern-only", no_argument, &external_only, 1}, + {"no-sort", no_argument, &no_sort, 1}, + {"numeric-sort", no_argument, &sort_numerically, 1}, + {"print-armap", no_argument, &print_armap, 1}, + {"print-file-name", no_argument, &file_on_each_line, 1}, + {"reverse-sort", no_argument, &reverse_sort, 1}, + {"target", optional_argument, 0, 200}, + {"undefined-only", no_argument, &undefined_only, 1}, + {"version", no_argument, &show_version, 1}, + {0, no_argument, 0, 0} }; + +int show_names = 0; /* Some error-reporting functions */ void usage () { - fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n", + fprintf(stderr, "nm %s\n\ +Usage: %s [-agnoprsuV] [--debug-syms] [--extern-only] [--print-armap]\n\ + [--print-file-name] [--numeric-sort] [--no-sort] [--reverse-sort]\n\ + [--undefined-only] [--target=bfdname] [file...]\n", program_version, program_name); - exit(0); + exit(1); } int @@ -63,13 +94,13 @@ main (argc, argv) int argc; char **argv; { - int c; /* sez which option char */ - int ind = 0; /* used by getopt and ignored by us */ - extern int optind; /* steps thru options */ - + int c; /* sez which option char */ + int retval; program_name = *argv; - - while ((c = getopt_long(argc, argv, "agnoprsu", long_options, &ind)) != EOF) { + + bfd_init(); + + while ((c = getopt_long(argc, argv, "agnoprsuvABV", long_options, (int *) 0)) != EOF) { switch (c) { case 'a': print_debug_syms = 1; break; case 'g': external_only = 1; break; @@ -79,33 +110,46 @@ main (argc, argv) case 'r': reverse_sort = 1; break; case 's': print_armap = 1; break; case 'u': undefined_only = 1; break; - - case 0: - if (!strcmp("target",(long_options[option_index]).name)) { - target = optarg; - } - - break; /* we've been given a long option */ - + case 'v': + case 'V': show_version = 1; break; + + /* For MIPS compatibility, -A selects System V style output, -B + selects BSD style output. These are not implemented. When + they are, they should be added to usage (). */ + case 'A': break; + case 'B': break; + + case 200: /* --target */ + target = optarg; + break; + 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 (optind == argc) return !display_file ("a.out"); - + + retval = 0; + show_names = (argc -optind)>1; /* We were given several filenames to do: */ - while (optind < argc) - if (!display_file (argv[optind++])) return 1; + while (optind < argc) { + if (!display_file (argv[optind++])) { + retval++; + } + } - return 0; + return retval; } -/** Display a file's stats */ +/* Display a file's stats */ /* goto here is marginally cleaner than the nested if syntax */ @@ -113,44 +157,56 @@ static boolean display_file (filename) char *filename; { - boolean retval = false; + boolean retval = true; bfd *file; bfd *arfile = NULL; - + file = bfd_openr(filename, target); if (file == NULL) { - bfd_fatal (filename); + fprintf (stderr, "%s: ", program_name); + bfd_perror (filename); + return false; } - if (bfd_check_format(file, bfd_object)) { - retval = do_one_rel_file (file); - goto closer; - } + if (bfd_check_format(file, bfd_object)) + { + if (show_names) { + printf ("\n%s:\n",filename); + } + do_one_rel_file (file, NULL); + } + else if (bfd_check_format (file, bfd_archive)) { + if (!bfd_check_format (file, bfd_archive)) { + fprintf (stderr, "%s: %s: unknown format\n", program_name, filename); + retval = false; + goto closer; + } - if (!bfd_check_format (file, bfd_archive)) { - fprintf (stderr, "%s: %s: unknown format.\n", program_name, filename); - retval = false; - goto closer; - } + if (!file_on_each_line) + printf("\n%s:\n", filename); + if (print_armap) print_symdef_entry (file); + for (;;) { + arfile = bfd_openr_next_archived_file (file, arfile); - printf("In archive %s:\n", filename); - if (print_armap) print_symdef_entry (file); - for (;;) { - arfile = bfd_openr_next_archived_file (file, arfile); + if (arfile == NULL) { + if (bfd_error != no_more_archived_files) + bfd_fatal (filename); + goto closer; + } - if (arfile == NULL) { - if (bfd_error != no_more_archived_files) - bfd_fatal (filename); - goto closer; - } - - if (!bfd_check_format(arfile, bfd_object)) - printf("%s: not an object file\n", arfile->filename); - else { - printf ("\n%s:\n", arfile->filename); - if (!do_one_rel_file (arfile)) return false; + if (!bfd_check_format(arfile, bfd_object)) + printf("%s: not an object file\n", arfile->filename); + else { + if (!file_on_each_line) + printf ("\n%s:\n", arfile->filename); + do_one_rel_file (arfile, file) ; + } } } + else { + fprintf (stderr, "\n%s: %s: unknown format\n", program_name, filename); + retval = false; + } closer: if (bfd_close(file) == false) @@ -159,10 +215,53 @@ 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)); +} -static boolean -do_one_rel_file (abfd) +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, archive_bfd) bfd *abfd; + bfd *archive_bfd; /* If non-NULL: archive containing abfd. */ { unsigned int storage; asymbol **syms; @@ -170,16 +269,15 @@ do_one_rel_file (abfd) if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) { (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); - return true; + return; } - storage = get_symtab_upper_bound (abfd); if (storage == 0) { nosymz: fprintf (stderr, "%s: Symflags set but there are none?\n", bfd_get_filename (abfd)); - exit (1); + return; } syms = (asymbol **) xmalloc (storage); @@ -192,65 +290,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); - return true; -} - -/* Symbol-sorting predicates */ -#define valueof(x) ((x)->section ? (x)->section->vma + (x)->value : (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; -{ - char *xn = (*(asymbol **) x)->name; - 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)); + print_symbols (abfd, syms, symcount, archive_bfd); + free (syms); } - -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. */ @@ -262,20 +313,24 @@ 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 flags; + flagword flags = (from[src_count])->flags; + sym = from[src_count]; if (undefined_only) { - keep = (flags & BSF_UNDEFINED); + keep = sym->section == &bfd_und_section; } else if (external_only) { - keep = ((flags & BSF_GLOBAL) || (flags & BSF_UNDEFINED) || - (flags & BSF_FORT_COMM)); + keep = ((flags & BSF_GLOBAL) + || (sym->section == &bfd_und_section) + || (bfd_is_com_section (sym->section))); } else { keep = 1; } - + if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) { keep = 0; } @@ -284,81 +339,36 @@ filter_symbols (abfd, syms, symcount) to[dst_count++] = from[src_count]; } } - + return dst_count; } - -/* Return a lower-case character corresponding to the symbol class of sym */ -char -decode_symclass (sym) - asymbol *sym; -{ - flagword flags = sym->flags; - - if ((sym->value == 0) && (sym->section != NULL)) - /* Huh? All section names don't begin with "." */ - return (sym->section->name)[1]; - - if (flags & BSF_FORT_COMM) return 'C'; - if (flags & BSF_UNDEFINED) return 'U'; - if (flags & BSF_ABSOLUTE) return 'a'; - - - if ( (flags & BSF_GLOBAL) || (flags & BSF_LOCAL) ){ - if ( !strcmp(sym->section->name, ".text") ){ - return 't'; - } else if ( !strcmp(sym->section->name, ".data") ){ - return 'd'; - } else if ( !strcmp(sym->section->name, ".bss") ){ - return 'b'; - } else { - return 'o'; - } - } - - /* We don't have to handle these cases just yet, but we will soon: - N_SETV: 'v'; - N_SETA: 'l'; - N_SETT: 'x'; - N_SETD: 'z'; - N_SETB: 's'; - N_INDR: 'i'; - */ - - return '?'; -} - static void -print_symbols (abfd, syms, symcount) +print_symbols (abfd, syms, symcount, archive_bfd) bfd *abfd; asymbol **syms; unsigned long symcount; + bfd *archive_bfd; { asymbol **sym = syms, **end = syms + symcount; - char class; for (; sym < end; ++sym) { - if (file_on_each_line) printf("%s:", bfd_get_filename(abfd)); + if (file_on_each_line) { + if (archive_bfd) + printf("%s:", bfd_get_filename(archive_bfd)); + printf("%s:", bfd_get_filename(abfd)); + } if (undefined_only) { - if ((*sym)->flags & BSF_UNDEFINED) + if ((*sym)->section == &bfd_und_section) puts ((*sym)->name); } else { asymbol *p = *sym; if (p) { - class = decode_symclass (p); - - if (p->flags & BSF_GLOBAL) - class = toupper (class); - - if (p->value || ((p->flags & BSF_UNDEFINED) != BSF_UNDEFINED)) - printf ("%08lx ", (p->section ? p->value + p->section->vma : p->value)); - else fputs (" ", stdout); - - printf ("%c %s\n", class, p->name); - } + bfd_print_symbol(abfd, stdout, p, bfd_print_symbol_nm); + putchar('\n'); + } } } } @@ -381,7 +391,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)); + } } }