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