1 /*** nm.c -- Describe symbol table of a rel file. */
10 PROTO(static boolean
, display_file
, (char *filename
));
11 PROTO(static boolean
, do_one_rel_file
, (bfd
*file
));
12 PROTO(static unsigned int, filter_symbols
, (bfd
*file
, asymbol
**syms
,
13 unsigned long symcount
));
15 PROTO(static void, print_symbols
, (bfd
*file
, asymbol
**syms
,
16 unsigned long symcount
));
17 extern PROTO(int, (*sorters
[2][2]), (char *x
, char *y
));
18 PROTO(static void, print_symdef_entry
, (bfd
* abfd
));
20 /* Command options. */
22 int external_only
= 0; /* print external symbols only */
23 int file_on_each_line
= 0; /* print file name on each line */
24 int no_sort
= 0; /* don't sort; print syms in order found */
25 int print_debug_syms
= 0; /* print debugger-only symbols too */
26 int print_armap
= 0; /* describe __.SYMDEF data in archive files. */
27 int reverse_sort
= 0; /* sort in downward(alpha or numeric) order */
28 int sort_numerically
= 0; /* sort in numeric rather than alpha order */
29 int undefined_only
= 0; /* print undefined symbols only */
31 boolean print_each_filename
= false; /* Ick. Used in archives. */
34 extern char *program_name
;
35 extern char *program_version
;
38 struct option long_options
[] = {
39 {"debug-syms", 0, &print_debug_syms
, 1},
40 {"extern-only", 0, &external_only
, 1},
41 {"no-sort", 0, &no_sort
, 1},
42 {"numeric-sort", 0, &sort_numerically
, 1},
43 {"print-armap", 0, &print_armap
, 1},
44 {"print-file-name", 0, &file_on_each_line
, 1},
45 {"reverse-sort", 0, &reverse_sort
, 1},
46 {"target", 2, (int *)NULL
, 0},
47 {"undefined-only", 0, &undefined_only
, 1},
51 /* Some error-reporting functions */
56 fprintf(stderr
, "nm %s\nUsage: %s [-agnoprsu] filename...\n",
57 program_version
, program_name
);
66 int c
; /* sez which option char */
67 int ind
= 0; /* used by getopt and ignored by us */
68 extern int optind
; /* steps thru options */
72 while ((c
= getopt_long(argc
, argv
, "agnoprsu", long_options
, &ind
)) != EOF
) {
74 case 'a': print_debug_syms
= 1; break;
75 case 'g': external_only
= 1; break;
76 case 'n': sort_numerically
= 1; break;
77 case 'o': file_on_each_line
= 1; break;
78 case 'p': no_sort
= 1; break;
79 case 'r': reverse_sort
= 1; break;
80 case 's': print_armap
= 1; break;
81 case 'u': undefined_only
= 1; break;
84 if (!strcmp("target",(long_options
[option_index
]).name
)) {
88 break; /* we've been given a long option */
95 /* Strangely, for the shell you should return only a nonzero value
96 on sucess -- the inverse of the C sense. */
98 /* OK, all options now parsed. If no filename specified, do a.out. */
99 if (optind
== argc
) return !display_file ("a.out");
101 /* We were given several filenames to do: */
102 while (optind
< argc
)
103 if (!display_file (argv
[optind
++])) return 1;
108 /** Display a file's stats */
110 /* goto here is marginally cleaner than the nested if syntax */
113 display_file (filename
)
116 boolean retval
= false;
120 file
= bfd_openr(filename
, target
);
122 bfd_fatal (filename
);
125 if (bfd_check_format(file
, bfd_object
)) {
126 retval
= do_one_rel_file (file
);
130 if (!bfd_check_format (file
, bfd_archive
)) {
131 fprintf (stderr
, "%s: %s: unknown format.\n", program_name
, filename
);
136 printf("In archive %s:\n", filename
);
137 if (print_armap
) print_symdef_entry (file
);
139 arfile
= bfd_openr_next_archived_file (file
, arfile
);
141 if (arfile
== NULL
) {
142 if (bfd_error
!= no_more_archived_files
)
143 bfd_fatal (filename
);
147 if (!bfd_check_format(arfile
, bfd_object
))
148 printf("%s: not an object file\n", arfile
->filename
);
150 printf ("\n%s:\n", arfile
->filename
);
151 if (!do_one_rel_file (arfile
)) return false;
156 if (bfd_close(file
) == false)
157 bfd_fatal (filename
);
164 do_one_rel_file (abfd
)
167 unsigned int storage
;
169 unsigned int symcount
= 0;
171 if (!(bfd_get_file_flags (abfd
) & HAS_SYMS
)) {
172 (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd
));
177 storage
= get_symtab_upper_bound (abfd
);
180 fprintf (stderr
, "%s: Symflags set but there are none?\n",
181 bfd_get_filename (abfd
));
185 syms
= (asymbol
**) xmalloc (storage
);
187 symcount
= bfd_canonicalize_symtab (abfd
, syms
);
188 if (symcount
== 0) goto nosymz
;
190 /* Discard the symbols we don't want to print.
191 It's OK to do this in place; we'll free the storage anyway
194 symcount
= filter_symbols (abfd
, syms
, symcount
);
197 qsort((char *) syms
, symcount
, sizeof (asymbol
*),
198 sorters
[sort_numerically
][reverse_sort
]);
200 if (print_each_filename
&& !file_on_each_line
)
201 printf("\n%s:\n", bfd_get_filename(abfd
));
203 print_symbols (abfd
, syms
, symcount
);
208 /* Symbol-sorting predicates */
209 #define valueof(x) ((x)->section ? (x)->section->vma + (x)->value : (x)->value)
211 numeric_forward (x
, y
)
216 return (valueof(*(asymbol
**)x
) - valueof(*(asymbol
**) y
));;
220 numeric_reverse (x
, y
)
224 return (valueof(*(asymbol
**)y
) - valueof(*(asymbol
**) x
));
229 non_numeric_forward (x
, y
)
233 CONST
char *xn
= (*(asymbol
**) x
)->name
;
234 CONST
char *yn
= (*(asymbol
**) y
)->name
;
236 return ((xn
== NULL
) ? ((yn
== NULL
) ? 0 : -1) :
237 ((yn
== NULL
) ? 1 : strcmp (xn
, yn
)));
241 non_numeric_reverse (x
, y
)
245 return -(non_numeric_forward (x
, y
));
248 int (*sorters
[2][2])() = {
249 {non_numeric_forward
, non_numeric_reverse
},
250 {numeric_forward
, numeric_reverse
},
254 /* Choose which symbol entries to print;
255 compact them downward to get rid of the rest.
256 Return the number of symbols to be printed. */
258 filter_symbols (abfd
, syms
, symcount
)
261 unsigned long symcount
;
263 asymbol
**from
, **to
;
264 unsigned int dst_count
= 0;
265 unsigned int src_count
;
266 for (from
= to
= syms
, src_count
= 0; src_count
<symcount
; src_count
++) {
268 flagword flags
= (from
[src_count
])->flags
;
270 if (undefined_only
) {
271 keep
= (flags
& BSF_UNDEFINED
);
272 } else if (external_only
) {
273 keep
= ((flags
& BSF_GLOBAL
) || (flags
& BSF_UNDEFINED
) ||
274 (flags
& BSF_FORT_COMM
));
279 if (!print_debug_syms
&& ((flags
& BSF_DEBUGGING
) != 0)) {
284 to
[dst_count
++] = from
[src_count
];
292 /* Return a lower-case character corresponding to the symbol class of sym */
294 decode_symclass (sym
)
297 flagword flags
= sym
->flags
;
299 if ((sym
->value
== 0) && (sym
->section
!= NULL
))
300 /* Huh? All section names don't begin with "." */
301 return (sym
->section
->name
)[1];
303 if (flags
& BSF_FORT_COMM
) return 'C';
304 if (flags
& BSF_UNDEFINED
) return 'U';
305 if (flags
& BSF_ABSOLUTE
) return 'a';
308 if ( (flags
& BSF_GLOBAL
) || (flags
& BSF_LOCAL
) ){
309 if ( !strcmp(sym
->section
->name
, ".text") ){
311 } else if ( !strcmp(sym
->section
->name
, ".data") ){
313 } else if ( !strcmp(sym
->section
->name
, ".bss") ){
320 /* We don't have to handle these cases just yet, but we will soon:
333 print_symbols (abfd
, syms
, symcount
)
336 unsigned long symcount
;
338 asymbol
**sym
= syms
, **end
= syms
+ symcount
;
341 for (; sym
< end
; ++sym
) {
342 if (file_on_each_line
) printf("%s:", bfd_get_filename(abfd
));
344 if (undefined_only
) {
345 if ((*sym
)->flags
& BSF_UNDEFINED
)
351 class = decode_symclass (p
);
353 if (p
->flags
& BSF_GLOBAL
)
354 class = toupper (class);
356 if (p
->value
|| ((p
->flags
& BSF_UNDEFINED
) != BSF_UNDEFINED
))
357 printf_vma( (p
->section
? p
->value
+ p
->section
->vma
: p
->value
));
358 else fputs (" ", stdout
);
360 printf (" %c %s\n", class, p
->name
);
367 print_symdef_entry (abfd
)
370 symindex idx
= BFD_NO_MORE_SYMBOLS
;
372 boolean everprinted
= false;
374 for (idx
= bfd_get_next_mapent (abfd
, idx
, &thesym
);
375 idx
!= BFD_NO_MORE_SYMBOLS
;
376 idx
= bfd_get_next_mapent (abfd
, idx
, &thesym
)) {
379 printf ("\nArchive index:\n");
382 elt
= bfd_get_elt_at_index (abfd
, idx
);
383 if (thesym
->name
!= (char *)NULL
) {
384 printf ("%s in %s\n", thesym
->name
, bfd_get_filename (elt
));