home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / binutils-2.2.1 / binutils / nm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-29  |  10.0 KB  |  397 lines

  1. /* nm.c -- Describe symbol table of a rel file.
  2.    Copyright 1991, 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Binutils.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "bfd.h"
  21. #include "sysdep.h"
  22. #include "bucomm.h"
  23. #include "getopt.h"
  24. #include "aout/stab_gnu.h"
  25. #include "aout/ranlib.h"
  26.  
  27. static boolean
  28. display_file PARAMS ((char *filename));
  29.  
  30. static void
  31. do_one_rel_file PARAMS ((bfd* file, bfd *archive));
  32.  
  33. static unsigned int
  34. filter_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount));
  35.  
  36. static void
  37. print_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount,
  38.                bfd *archive));
  39.  
  40. static void
  41. print_symdef_entry PARAMS ((bfd * abfd));
  42.  
  43. /* Command options.  */
  44.  
  45. int external_only = 0;    /* print external symbols only */
  46. int file_on_each_line = 0; /* print file name on each line */
  47. int no_sort = 0;    /* don't sort; print syms in order found */
  48. int print_debug_syms = 0; /* print debugger-only symbols too */
  49. int print_armap = 0;    /* describe __.SYMDEF data in archive files.  */
  50. int reverse_sort = 0;    /* sort in downward(alpha or numeric) order */
  51. int sort_numerically = 0; /* sort in numeric rather than alpha order */
  52. int undefined_only = 0;    /* print undefined symbols only */
  53. int show_version = 0;    /* show the version number */
  54.  
  55. boolean print_each_filename = false; /* Ick.  Used in archives. */
  56.  
  57. /* IMPORT */
  58. extern char *program_name;
  59. extern char *program_version;
  60. extern char *target;
  61. extern int print_version;
  62.  
  63. struct option long_options[] = {
  64.     {"debug-syms",        no_argument, &print_debug_syms,  1},
  65.     {"extern-only",        no_argument, &external_only,     1},
  66.     {"no-sort",        no_argument, &no_sort,         1},
  67.     {"numeric-sort",    no_argument, &sort_numerically,  1},
  68.     {"print-armap",        no_argument, &print_armap,       1},
  69.     {"print-file-name", no_argument, &file_on_each_line, 1},
  70.     {"reverse-sort",    no_argument, &reverse_sort,      1},
  71.     {"target",         optional_argument, 0,            200},
  72.     {"undefined-only",  no_argument, &undefined_only,    1},
  73.     {"version",         no_argument, &show_version,      1},
  74.     {0, no_argument, 0, 0}
  75. };
  76.  
  77. int show_names = 0;
  78.  
  79. /* Some error-reporting functions */
  80.  
  81. void
  82. usage ()
  83. {
  84.   fprintf(stderr, "\
  85. Usage: %s [-agnoprsuV] [--debug-syms] [--extern-only] [--print-armap]\n\
  86.        [--print-file-name] [--numeric-sort] [--no-sort] [--reverse-sort]\n\
  87.        [--undefined-only] [--target=bfdname] [file...]\n", program_name);
  88.   exit(1);
  89. }
  90.  
  91. int
  92. main (argc, argv)
  93.      int argc;
  94.      char **argv;
  95. {
  96.   int c;            /* sez which option char */
  97.   int retval;
  98.   program_name = *argv;
  99.  
  100.   bfd_init();
  101.  
  102.   while ((c = getopt_long(argc, argv, "agnoprsuvABV", long_options, (int *) 0)) != EOF) {
  103.     switch (c) {
  104.     case 'a': print_debug_syms = 1; break;
  105.     case 'g': external_only = 1; break;
  106.     case 'n': sort_numerically = 1; break;
  107.     case 'o': file_on_each_line = 1; break;
  108.     case 'p': no_sort = 1; break;
  109.     case 'r': reverse_sort = 1; break;
  110.     case 's': print_armap = 1; break;
  111.     case 'u': undefined_only = 1; break;
  112.     case 'v':
  113.     case 'V': show_version = 1; break;
  114.  
  115.     /* For MIPS compatibility, -A selects System V style output, -B
  116.        selects BSD style output.  These are not implemented.  When
  117.        they are, they should be added to usage ().  */
  118.     case 'A': break;
  119.     case 'B': break;
  120.  
  121.     case 200:            /* --target */
  122.       target = optarg;
  123.       break;
  124.  
  125.     default:
  126.       usage ();
  127.     }
  128.   }
  129.  
  130.   if (show_version)
  131.     printf ("%s version %s\n", program_name, program_version);
  132.  
  133.   /* Strangely, for the shell you should return only a nonzero value
  134.      on sucess -- the inverse of the C sense. */
  135.  
  136.   /* OK, all options now parsed.  If no filename specified, do a.out. */
  137.   if (optind == argc) return !display_file ("a.out");
  138.  
  139.   retval = 0;
  140.   show_names = (argc -optind)>1;
  141.   /* We were given several filenames to do: */
  142.   while (optind < argc) {
  143.     if (!display_file (argv[optind++])) {
  144.       retval++;
  145.     }
  146.   }
  147.  
  148.   return retval;
  149. }
  150.  
  151. /* Display a file's stats */
  152.  
  153. /* goto here is marginally cleaner than the nested if syntax */
  154.  
  155. static boolean
  156. display_file (filename)
  157.      char *filename;
  158. {
  159.   boolean retval = true;
  160.   bfd *file;
  161.   bfd *arfile = NULL;
  162.  
  163.   file = bfd_openr(filename, target);
  164.   if (file == NULL) {
  165.     fprintf (stderr, "%s: ", program_name);
  166.     bfd_perror (filename);
  167.     return false;
  168.   }
  169.  
  170.   if (bfd_check_format(file, bfd_object))
  171.       {
  172.     if (show_names) {
  173.       printf ("\n%s:\n",filename);
  174.     }
  175.     do_one_rel_file (file, NULL);
  176.       }
  177.   else if (bfd_check_format (file, bfd_archive)) {
  178.     if (!bfd_check_format (file, bfd_archive)) {
  179.       fprintf (stderr, "%s: %s: unknown format\n", program_name, filename);
  180.       retval = false;
  181.       goto closer;
  182.     }
  183.  
  184.     if (!file_on_each_line)
  185.       printf("\n%s:\n", filename);
  186.     if (print_armap) print_symdef_entry (file);
  187.     for (;;) {
  188.       arfile = bfd_openr_next_archived_file (file, arfile);
  189.  
  190.       if (arfile == NULL) {
  191.     if (bfd_error != no_more_archived_files)
  192.       bfd_fatal (filename);
  193.     goto closer;
  194.       }
  195.  
  196.       if (!bfd_check_format(arfile, bfd_object))
  197.     printf("%s: not an object file\n", arfile->filename);
  198.       else {
  199.     if (!file_on_each_line)
  200.       printf ("\n%s:\n", arfile->filename);
  201.     do_one_rel_file (arfile, file) ;
  202.       }
  203.     }
  204.   }
  205.   else {
  206.     fprintf (stderr, "\n%s: %s: unknown format\n", program_name, filename);
  207.     retval = false;
  208.   }
  209.  
  210.  closer:
  211.   if (bfd_close(file) == false)
  212.     bfd_fatal (filename);
  213.  
  214.   return retval;
  215. }
  216.  
  217. /* Symbol-sorting predicates */
  218. #define valueof(x) ((x)->section->vma + (x)->value)
  219. int
  220. numeric_forward (x, y)
  221.      CONST void *x;
  222.      CONST void *y;
  223. {
  224.   return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y));
  225. }
  226.  
  227. int
  228. numeric_reverse (x, y)
  229.      CONST void *x;
  230.      CONST void *y;
  231. {
  232.   return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x));
  233. }
  234.  
  235. int
  236. non_numeric_forward (x, y)
  237.      CONST void *x;
  238.      CONST void *y;
  239. {
  240.   CONST char *xn = (*(asymbol **) x)->name;
  241.   CONST char *yn = (*(asymbol **) y)->name;
  242.  
  243.   return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
  244.       ((yn == NULL) ? 1 : strcmp (xn, yn)));
  245. }
  246.  
  247. int
  248. non_numeric_reverse (x, y)
  249.      CONST void *x;
  250.      CONST void *y;
  251. {
  252.   return -(non_numeric_forward (x, y));
  253. }
  254.  
  255. int (*(sorters[2][2])) PARAMS ((CONST void *, CONST void *)) = {
  256.     {non_numeric_forward, non_numeric_reverse},
  257.     {numeric_forward, numeric_reverse},
  258. };
  259.  
  260. static void
  261. do_one_rel_file (abfd, archive_bfd)
  262.      bfd *abfd;
  263.      bfd *archive_bfd; /* If non-NULL: archive containing abfd. */
  264. {
  265.   unsigned int storage;
  266.   asymbol **syms;
  267.   unsigned int symcount = 0;
  268.  
  269.   if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) {
  270.     (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
  271.     return;
  272.   }
  273.  
  274.   storage = get_symtab_upper_bound (abfd);
  275.   if (storage == 0) {
  276.   nosymz:
  277.     fprintf (stderr, "%s: Symflags set but there are none?\n",
  278.          bfd_get_filename (abfd));
  279.     return;
  280.   }
  281.  
  282.   syms = (asymbol **) xmalloc (storage);
  283.  
  284.   symcount = bfd_canonicalize_symtab (abfd, syms);
  285.   if (symcount == 0) goto nosymz;
  286.  
  287.   /* Discard the symbols we don't want to print.
  288.      It's OK to do this in place; we'll free the storage anyway
  289.      (after printing) */
  290.  
  291.   symcount = filter_symbols (abfd, syms, symcount);
  292.  
  293.   if (!no_sort)
  294.     qsort((char *) syms, symcount, sizeof (asymbol *),
  295.       sorters[sort_numerically][reverse_sort]);
  296.  
  297.   if (print_each_filename && !file_on_each_line)
  298.     printf("\n%s:\n", bfd_get_filename(abfd));
  299.  
  300.   print_symbols (abfd, syms, symcount, archive_bfd);
  301.   free (syms);
  302. }
  303.  
  304. /* Choose which symbol entries to print;
  305.    compact them downward to get rid of the rest.
  306.    Return the number of symbols to be printed.  */
  307. static unsigned int
  308. filter_symbols (abfd, syms, symcount)
  309.      bfd *abfd;
  310.      asymbol **syms;
  311.      unsigned long symcount;
  312. {
  313.   asymbol **from, **to;
  314.   unsigned int dst_count = 0;
  315.   asymbol *sym;
  316.  
  317.   unsigned int src_count;
  318.   for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
  319.     int keep = 0;
  320.  
  321.     flagword flags = (from[src_count])->flags;
  322.     sym = from[src_count];
  323.     if (undefined_only) {
  324.       keep = sym->section == &bfd_und_section;
  325.     } else if (external_only) {
  326.       keep = ((flags & BSF_GLOBAL)
  327.           || (sym->section == &bfd_und_section)
  328.           || (bfd_is_com_section (sym->section)));
  329.     } else {
  330.       keep = 1;
  331.     }
  332.  
  333.     if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) {
  334.       keep = 0;
  335.     }
  336.  
  337.     if (keep) {
  338.       to[dst_count++] = from[src_count];
  339.     }
  340.   }
  341.  
  342.   return dst_count;
  343. }
  344.  
  345. static void
  346. print_symbols (abfd, syms, symcount, archive_bfd)
  347.      bfd *abfd;
  348.      asymbol **syms;
  349.      unsigned long symcount;
  350.      bfd *archive_bfd;
  351. {
  352.   asymbol **sym = syms, **end = syms + symcount;
  353.  
  354.   for (; sym < end; ++sym) {
  355.     if (file_on_each_line) {
  356.       if (archive_bfd)
  357.     printf("%s:", bfd_get_filename(archive_bfd));
  358.       printf("%s:", bfd_get_filename(abfd));
  359.     }
  360.  
  361.     if (undefined_only) {
  362.       if ((*sym)->section == &bfd_und_section)
  363.     puts ((*sym)->name);
  364.     }
  365.     else {
  366.       asymbol *p = *sym;
  367.       if (p) {
  368.     bfd_print_symbol(abfd, stdout, p, bfd_print_symbol_nm);
  369.     putchar('\n');
  370.       }
  371.     }
  372.   }
  373. }
  374.  
  375. static void
  376. print_symdef_entry (abfd)
  377.      bfd * abfd;
  378. {
  379.   symindex idx = BFD_NO_MORE_SYMBOLS;
  380.   carsym *thesym;
  381.   boolean everprinted = false;
  382.  
  383.   for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
  384.        idx != BFD_NO_MORE_SYMBOLS;
  385.        idx = bfd_get_next_mapent (abfd, idx, &thesym)) {
  386.     bfd *elt;
  387.     if (!everprinted) {
  388.       printf ("\nArchive index:\n");
  389.       everprinted = true;
  390.     }
  391.     elt = bfd_get_elt_at_index (abfd, idx);
  392.     if (thesym->name != (char *)NULL) {
  393.       printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
  394.     }
  395.   }
  396. }
  397.