Initial revision
[deliverable/binutils-gdb.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 "getopt.h"
23 #include "aout/stab_gnu.h"
24 #include <ranlib.h>
25
26
27
28 PROTO(static boolean, display_file, (char *filename));
29 PROTO(static void, do_one_rel_file, (bfd *file));
30 PROTO(static unsigned int, filter_symbols, (bfd *file, asymbol **syms,
31 unsigned long symcount));
32
33 PROTO(static void, print_symbols, (bfd *file, asymbol **syms,
34 unsigned long symcount));
35 extern PROTO(int, (*sorters[2][2]), (char *x, char *y));
36 PROTO(static void, print_symdef_entry, (bfd * abfd));
37
38 /* Command options. */
39
40 int external_only = 0; /* print external symbols only */
41 int file_on_each_line = 0; /* print file name on each line */
42 int no_sort = 0; /* don't sort; print syms in order found */
43 int print_debug_syms = 0; /* print debugger-only symbols too */
44 int print_armap = 0; /* describe __.SYMDEF data in archive files. */
45 int reverse_sort = 0; /* sort in downward(alpha or numeric) order */
46 int sort_numerically = 0; /* sort in numeric rather than alpha order */
47 int undefined_only = 0; /* print undefined symbols only */
48
49 boolean print_each_filename = false; /* Ick. Used in archives. */
50
51 /* IMPORT */
52 extern char *program_name;
53 extern char *program_version;
54 extern char *target;
55
56 struct option long_options[] = {
57 {"debug-syms", 0, &print_debug_syms, 1},
58 {"extern-only", 0, &external_only, 1},
59 {"no-sort", 0, &no_sort, 1},
60 {"numeric-sort", 0, &sort_numerically, 1},
61 {"print-armap", 0, &print_armap, 1},
62 {"print-file-name", 0, &file_on_each_line, 1},
63 {"reverse-sort", 0, &reverse_sort, 1},
64 {"target", 2, (int *)NULL, 0},
65 {"undefined-only", 0, &undefined_only, 1},
66 {0, 0, 0, 0}
67 };
68
69 int show_names = 0;
70 \f
71 /* Some error-reporting functions */
72
73 void
74 usage ()
75 {
76 fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n",
77 program_version, program_name);
78 exit(0);
79 }
80
81 int
82 main (argc, argv)
83 int argc;
84 char **argv;
85 {
86 int c; /* sez which option char */
87 int ind = 0; /* used by getopt and ignored by us */
88 extern int optind; /* steps thru options */
89 int retval;
90 program_name = *argv;
91
92 bfd_init();
93
94 while ((c = getopt_long(argc, argv, "agnoprsu", long_options, &ind)) != 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 (optind == 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 ? (x)->section->vma + (x)->value : (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 unsigned int src_count;
307 for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
308 int keep = 0;
309 flagword flags = (from[src_count])->flags;
310
311 if (undefined_only) {
312 keep = (flags & BSF_UNDEFINED);
313 } else if (external_only) {
314 keep = ((flags & BSF_GLOBAL) || (flags & BSF_UNDEFINED) ||
315 (flags & BSF_FORT_COMM));
316 } else {
317 keep = 1;
318 }
319
320 if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) {
321 keep = 0;
322 }
323
324 if (keep) {
325 to[dst_count++] = from[src_count];
326 }
327 }
328
329 return dst_count;
330 }
331 \f
332 static void
333 print_symbols (abfd, syms, symcount)
334 bfd *abfd;
335 asymbol **syms;
336 unsigned long symcount;
337 {
338 asymbol **sym = syms, **end = syms + symcount;
339 char class;
340
341 for (; sym < end; ++sym) {
342 if (file_on_each_line) printf("%s:", bfd_get_filename(abfd));
343
344 if (undefined_only) {
345 if ((*sym)->flags & BSF_UNDEFINED)
346 puts ((*sym)->name);
347 }
348 else {
349 asymbol *p = *sym;
350 if (p) {
351 bfd_print_symbol(abfd, stdout, p, bfd_print_symbol_nm);
352 putchar('\n');
353 }
354 }
355 }
356 }
357
358 static void
359 print_symdef_entry (abfd)
360 bfd * abfd;
361 {
362 symindex idx = BFD_NO_MORE_SYMBOLS;
363 carsym *thesym;
364 boolean everprinted = false;
365
366 for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
367 idx != BFD_NO_MORE_SYMBOLS;
368 idx = bfd_get_next_mapent (abfd, idx, &thesym)) {
369 bfd *elt;
370 if (!everprinted) {
371 printf ("\nArchive index:\n");
372 everprinted = true;
373 }
374 elt = bfd_get_elt_at_index (abfd, idx);
375 if (thesym->name != (char *)NULL) {
376 printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
377 }
378 }
379 }
This page took 0.036498 seconds and 4 git commands to generate.