1*3d8817e4Smiod /* nm.c -- Describe symbol table of a rel file.
2*3d8817e4Smiod Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3*3d8817e4Smiod 2001, 2002, 2003, 2004, 2005
4*3d8817e4Smiod Free Software Foundation, Inc.
5*3d8817e4Smiod
6*3d8817e4Smiod This file is part of GNU Binutils.
7*3d8817e4Smiod
8*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod (at your option) any later version.
12*3d8817e4Smiod
13*3d8817e4Smiod This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*3d8817e4Smiod GNU General Public License for more details.
17*3d8817e4Smiod
18*3d8817e4Smiod You should have received a copy of the GNU General Public License
19*3d8817e4Smiod along with this program; if not, write to the Free Software
20*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21*3d8817e4Smiod 02110-1301, USA. */
22*3d8817e4Smiod
23*3d8817e4Smiod #include "bfd.h"
24*3d8817e4Smiod #include "progress.h"
25*3d8817e4Smiod #include "bucomm.h"
26*3d8817e4Smiod #include "budemang.h"
27*3d8817e4Smiod #include "getopt.h"
28*3d8817e4Smiod #include "aout/stab_gnu.h"
29*3d8817e4Smiod #include "aout/ranlib.h"
30*3d8817e4Smiod #include "demangle.h"
31*3d8817e4Smiod #include "libiberty.h"
32*3d8817e4Smiod #include "elf-bfd.h"
33*3d8817e4Smiod #include "elf/common.h"
34*3d8817e4Smiod
35*3d8817e4Smiod /* When sorting by size, we use this structure to hold the size and a
36*3d8817e4Smiod pointer to the minisymbol. */
37*3d8817e4Smiod
38*3d8817e4Smiod struct size_sym
39*3d8817e4Smiod {
40*3d8817e4Smiod const void *minisym;
41*3d8817e4Smiod bfd_vma size;
42*3d8817e4Smiod };
43*3d8817e4Smiod
44*3d8817e4Smiod /* When fetching relocs, we use this structure to pass information to
45*3d8817e4Smiod get_relocs. */
46*3d8817e4Smiod
47*3d8817e4Smiod struct get_relocs_info
48*3d8817e4Smiod {
49*3d8817e4Smiod asection **secs;
50*3d8817e4Smiod arelent ***relocs;
51*3d8817e4Smiod long *relcount;
52*3d8817e4Smiod asymbol **syms;
53*3d8817e4Smiod };
54*3d8817e4Smiod
55*3d8817e4Smiod struct extended_symbol_info
56*3d8817e4Smiod {
57*3d8817e4Smiod symbol_info *sinfo;
58*3d8817e4Smiod bfd_vma ssize;
59*3d8817e4Smiod elf_symbol_type *elfinfo;
60*3d8817e4Smiod /* FIXME: We should add more fields for Type, Line, Section. */
61*3d8817e4Smiod };
62*3d8817e4Smiod #define SYM_NAME(sym) (sym->sinfo->name)
63*3d8817e4Smiod #define SYM_VALUE(sym) (sym->sinfo->value)
64*3d8817e4Smiod #define SYM_TYPE(sym) (sym->sinfo->type)
65*3d8817e4Smiod #define SYM_STAB_NAME(sym) (sym->sinfo->stab_name)
66*3d8817e4Smiod #define SYM_STAB_DESC(sym) (sym->sinfo->stab_desc)
67*3d8817e4Smiod #define SYM_STAB_OTHER(sym) (sym->sinfo->stab_other)
68*3d8817e4Smiod #define SYM_SIZE(sym) \
69*3d8817e4Smiod (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
70*3d8817e4Smiod
71*3d8817e4Smiod /* The output formatting functions. */
72*3d8817e4Smiod static void print_object_filename_bsd (char *);
73*3d8817e4Smiod static void print_object_filename_sysv (char *);
74*3d8817e4Smiod static void print_object_filename_posix (char *);
75*3d8817e4Smiod static void print_archive_filename_bsd (char *);
76*3d8817e4Smiod static void print_archive_filename_sysv (char *);
77*3d8817e4Smiod static void print_archive_filename_posix (char *);
78*3d8817e4Smiod static void print_archive_member_bsd (char *, const char *);
79*3d8817e4Smiod static void print_archive_member_sysv (char *, const char *);
80*3d8817e4Smiod static void print_archive_member_posix (char *, const char *);
81*3d8817e4Smiod static void print_symbol_filename_bsd (bfd *, bfd *);
82*3d8817e4Smiod static void print_symbol_filename_sysv (bfd *, bfd *);
83*3d8817e4Smiod static void print_symbol_filename_posix (bfd *, bfd *);
84*3d8817e4Smiod static void print_value (bfd *, bfd_vma);
85*3d8817e4Smiod static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
86*3d8817e4Smiod static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
87*3d8817e4Smiod static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
88*3d8817e4Smiod
89*3d8817e4Smiod /* Support for different output formats. */
90*3d8817e4Smiod struct output_fns
91*3d8817e4Smiod {
92*3d8817e4Smiod /* Print the name of an object file given on the command line. */
93*3d8817e4Smiod void (*print_object_filename) (char *);
94*3d8817e4Smiod
95*3d8817e4Smiod /* Print the name of an archive file given on the command line. */
96*3d8817e4Smiod void (*print_archive_filename) (char *);
97*3d8817e4Smiod
98*3d8817e4Smiod /* Print the name of an archive member file. */
99*3d8817e4Smiod void (*print_archive_member) (char *, const char *);
100*3d8817e4Smiod
101*3d8817e4Smiod /* Print the name of the file (and archive, if there is one)
102*3d8817e4Smiod containing a symbol. */
103*3d8817e4Smiod void (*print_symbol_filename) (bfd *, bfd *);
104*3d8817e4Smiod
105*3d8817e4Smiod /* Print a line of information about a symbol. */
106*3d8817e4Smiod void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
107*3d8817e4Smiod };
108*3d8817e4Smiod
109*3d8817e4Smiod static struct output_fns formats[] =
110*3d8817e4Smiod {
111*3d8817e4Smiod {print_object_filename_bsd,
112*3d8817e4Smiod print_archive_filename_bsd,
113*3d8817e4Smiod print_archive_member_bsd,
114*3d8817e4Smiod print_symbol_filename_bsd,
115*3d8817e4Smiod print_symbol_info_bsd},
116*3d8817e4Smiod {print_object_filename_sysv,
117*3d8817e4Smiod print_archive_filename_sysv,
118*3d8817e4Smiod print_archive_member_sysv,
119*3d8817e4Smiod print_symbol_filename_sysv,
120*3d8817e4Smiod print_symbol_info_sysv},
121*3d8817e4Smiod {print_object_filename_posix,
122*3d8817e4Smiod print_archive_filename_posix,
123*3d8817e4Smiod print_archive_member_posix,
124*3d8817e4Smiod print_symbol_filename_posix,
125*3d8817e4Smiod print_symbol_info_posix}
126*3d8817e4Smiod };
127*3d8817e4Smiod
128*3d8817e4Smiod /* Indices in `formats'. */
129*3d8817e4Smiod #define FORMAT_BSD 0
130*3d8817e4Smiod #define FORMAT_SYSV 1
131*3d8817e4Smiod #define FORMAT_POSIX 2
132*3d8817e4Smiod #define FORMAT_DEFAULT FORMAT_BSD
133*3d8817e4Smiod
134*3d8817e4Smiod /* The output format to use. */
135*3d8817e4Smiod static struct output_fns *format = &formats[FORMAT_DEFAULT];
136*3d8817e4Smiod
137*3d8817e4Smiod /* Command options. */
138*3d8817e4Smiod
139*3d8817e4Smiod static int do_demangle = 0; /* Pretty print C++ symbol names. */
140*3d8817e4Smiod static int external_only = 0; /* Print external symbols only. */
141*3d8817e4Smiod static int defined_only = 0; /* Print defined symbols only. */
142*3d8817e4Smiod static int no_sort = 0; /* Don't sort; print syms in order found. */
143*3d8817e4Smiod static int print_debug_syms = 0;/* Print debugger-only symbols too. */
144*3d8817e4Smiod static int print_armap = 0; /* Describe __.SYMDEF data in archive files. */
145*3d8817e4Smiod static int print_size = 0; /* Print size of defined symbols. */
146*3d8817e4Smiod static int reverse_sort = 0; /* Sort in downward(alpha or numeric) order. */
147*3d8817e4Smiod static int sort_numerically = 0;/* Sort in numeric rather than alpha order. */
148*3d8817e4Smiod static int sort_by_size = 0; /* Sort by size of symbol. */
149*3d8817e4Smiod static int undefined_only = 0; /* Print undefined symbols only. */
150*3d8817e4Smiod static int dynamic = 0; /* Print dynamic symbols. */
151*3d8817e4Smiod static int show_version = 0; /* Show the version number. */
152*3d8817e4Smiod static int show_stats = 0; /* Show statistics. */
153*3d8817e4Smiod static int show_synthetic = 0; /* Display synthesized symbols too. */
154*3d8817e4Smiod static int line_numbers = 0; /* Print line numbers for symbols. */
155*3d8817e4Smiod static int allow_special_symbols = 0; /* Allow special symbols. */
156*3d8817e4Smiod
157*3d8817e4Smiod /* When to print the names of files. Not mutually exclusive in SYSV format. */
158*3d8817e4Smiod static int filename_per_file = 0; /* Once per file, on its own line. */
159*3d8817e4Smiod static int filename_per_symbol = 0; /* Once per symbol, at start of line. */
160*3d8817e4Smiod
161*3d8817e4Smiod /* Print formats for printing a symbol value. */
162*3d8817e4Smiod #ifndef BFD64
163*3d8817e4Smiod static char value_format[] = "%08lx";
164*3d8817e4Smiod #else
165*3d8817e4Smiod #if BFD_HOST_64BIT_LONG
166*3d8817e4Smiod static char value_format[] = "%016lx";
167*3d8817e4Smiod #else
168*3d8817e4Smiod /* We don't use value_format for this case. */
169*3d8817e4Smiod #endif
170*3d8817e4Smiod #endif
171*3d8817e4Smiod #ifdef BFD64
172*3d8817e4Smiod static int print_width = 16;
173*3d8817e4Smiod #else
174*3d8817e4Smiod static int print_width = 8;
175*3d8817e4Smiod #endif
176*3d8817e4Smiod static int print_radix = 16;
177*3d8817e4Smiod /* Print formats for printing stab info. */
178*3d8817e4Smiod static char other_format[] = "%02x";
179*3d8817e4Smiod static char desc_format[] = "%04x";
180*3d8817e4Smiod
181*3d8817e4Smiod static char *target = NULL;
182*3d8817e4Smiod
183*3d8817e4Smiod /* Used to cache the line numbers for a BFD. */
184*3d8817e4Smiod static bfd *lineno_cache_bfd;
185*3d8817e4Smiod static bfd *lineno_cache_rel_bfd;
186*3d8817e4Smiod
187*3d8817e4Smiod #define OPTION_TARGET 200
188*3d8817e4Smiod
189*3d8817e4Smiod static struct option long_options[] =
190*3d8817e4Smiod {
191*3d8817e4Smiod {"debug-syms", no_argument, &print_debug_syms, 1},
192*3d8817e4Smiod {"demangle", optional_argument, 0, 'C'},
193*3d8817e4Smiod {"dynamic", no_argument, &dynamic, 1},
194*3d8817e4Smiod {"extern-only", no_argument, &external_only, 1},
195*3d8817e4Smiod {"format", required_argument, 0, 'f'},
196*3d8817e4Smiod {"help", no_argument, 0, 'h'},
197*3d8817e4Smiod {"line-numbers", no_argument, 0, 'l'},
198*3d8817e4Smiod {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
199*3d8817e4Smiod {"no-demangle", no_argument, &do_demangle, 0},
200*3d8817e4Smiod {"no-sort", no_argument, &no_sort, 1},
201*3d8817e4Smiod {"numeric-sort", no_argument, &sort_numerically, 1},
202*3d8817e4Smiod {"portability", no_argument, 0, 'P'},
203*3d8817e4Smiod {"print-armap", no_argument, &print_armap, 1},
204*3d8817e4Smiod {"print-file-name", no_argument, 0, 'o'},
205*3d8817e4Smiod {"print-size", no_argument, 0, 'S'},
206*3d8817e4Smiod {"radix", required_argument, 0, 't'},
207*3d8817e4Smiod {"reverse-sort", no_argument, &reverse_sort, 1},
208*3d8817e4Smiod {"size-sort", no_argument, &sort_by_size, 1},
209*3d8817e4Smiod {"special-syms", no_argument, &allow_special_symbols, 1},
210*3d8817e4Smiod {"stats", no_argument, &show_stats, 1},
211*3d8817e4Smiod {"synthetic", no_argument, &show_synthetic, 1},
212*3d8817e4Smiod {"target", required_argument, 0, OPTION_TARGET},
213*3d8817e4Smiod {"defined-only", no_argument, &defined_only, 1},
214*3d8817e4Smiod {"undefined-only", no_argument, &undefined_only, 1},
215*3d8817e4Smiod {"version", no_argument, &show_version, 1},
216*3d8817e4Smiod {0, no_argument, 0, 0}
217*3d8817e4Smiod };
218*3d8817e4Smiod
219*3d8817e4Smiod /* Some error-reporting functions. */
220*3d8817e4Smiod
221*3d8817e4Smiod static void
usage(FILE * stream,int status)222*3d8817e4Smiod usage (FILE *stream, int status)
223*3d8817e4Smiod {
224*3d8817e4Smiod fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
225*3d8817e4Smiod fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
226*3d8817e4Smiod fprintf (stream, _(" The options are:\n\
227*3d8817e4Smiod -a, --debug-syms Display debugger-only symbols\n\
228*3d8817e4Smiod -A, --print-file-name Print name of the input file before every symbol\n\
229*3d8817e4Smiod -B Same as --format=bsd\n\
230*3d8817e4Smiod -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
231*3d8817e4Smiod The STYLE, if specified, can be `auto' (the default),\n\
232*3d8817e4Smiod `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
233*3d8817e4Smiod or `gnat'\n\
234*3d8817e4Smiod --no-demangle Do not demangle low-level symbol names\n\
235*3d8817e4Smiod -D, --dynamic Display dynamic symbols instead of normal symbols\n\
236*3d8817e4Smiod --defined-only Display only defined symbols\n\
237*3d8817e4Smiod -e (ignored)\n\
238*3d8817e4Smiod -f, --format=FORMAT Use the output format FORMAT. FORMAT can be `bsd',\n\
239*3d8817e4Smiod `sysv' or `posix'. The default is `bsd'\n\
240*3d8817e4Smiod -g, --extern-only Display only external symbols\n\
241*3d8817e4Smiod -l, --line-numbers Use debugging information to find a filename and\n\
242*3d8817e4Smiod line number for each symbol\n\
243*3d8817e4Smiod -n, --numeric-sort Sort symbols numerically by address\n\
244*3d8817e4Smiod -o Same as -A\n\
245*3d8817e4Smiod -p, --no-sort Do not sort the symbols\n\
246*3d8817e4Smiod -P, --portability Same as --format=posix\n\
247*3d8817e4Smiod -r, --reverse-sort Reverse the sense of the sort\n\
248*3d8817e4Smiod -S, --print-size Print size of defined symbols\n\
249*3d8817e4Smiod -s, --print-armap Include index for symbols from archive members\n\
250*3d8817e4Smiod --size-sort Sort symbols by size\n\
251*3d8817e4Smiod --special-syms Include special symbols in the output\n\
252*3d8817e4Smiod --synthetic Display synthetic symbols as well\n\
253*3d8817e4Smiod -t, --radix=RADIX Use RADIX for printing symbol values\n\
254*3d8817e4Smiod --target=BFDNAME Specify the target object format as BFDNAME\n\
255*3d8817e4Smiod -u, --undefined-only Display only undefined symbols\n\
256*3d8817e4Smiod -X 32_64 (ignored)\n\
257*3d8817e4Smiod @FILE Read options from FILE\n\
258*3d8817e4Smiod -h, --help Display this information\n\
259*3d8817e4Smiod -V, --version Display this program's version number\n\
260*3d8817e4Smiod \n"));
261*3d8817e4Smiod list_supported_targets (program_name, stream);
262*3d8817e4Smiod if (status == 0)
263*3d8817e4Smiod fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
264*3d8817e4Smiod exit (status);
265*3d8817e4Smiod }
266*3d8817e4Smiod
267*3d8817e4Smiod /* Set the radix for the symbol value and size according to RADIX. */
268*3d8817e4Smiod
269*3d8817e4Smiod static void
set_print_radix(char * radix)270*3d8817e4Smiod set_print_radix (char *radix)
271*3d8817e4Smiod {
272*3d8817e4Smiod switch (*radix)
273*3d8817e4Smiod {
274*3d8817e4Smiod case 'x':
275*3d8817e4Smiod break;
276*3d8817e4Smiod case 'd':
277*3d8817e4Smiod case 'o':
278*3d8817e4Smiod if (*radix == 'd')
279*3d8817e4Smiod print_radix = 10;
280*3d8817e4Smiod else
281*3d8817e4Smiod print_radix = 8;
282*3d8817e4Smiod #ifndef BFD64
283*3d8817e4Smiod value_format[4] = *radix;
284*3d8817e4Smiod #else
285*3d8817e4Smiod #if BFD_HOST_64BIT_LONG
286*3d8817e4Smiod value_format[5] = *radix;
287*3d8817e4Smiod #else
288*3d8817e4Smiod /* This case requires special handling for octal and decimal
289*3d8817e4Smiod printing. */
290*3d8817e4Smiod #endif
291*3d8817e4Smiod #endif
292*3d8817e4Smiod other_format[3] = desc_format[3] = *radix;
293*3d8817e4Smiod break;
294*3d8817e4Smiod default:
295*3d8817e4Smiod fatal (_("%s: invalid radix"), radix);
296*3d8817e4Smiod }
297*3d8817e4Smiod }
298*3d8817e4Smiod
299*3d8817e4Smiod static void
set_output_format(char * f)300*3d8817e4Smiod set_output_format (char *f)
301*3d8817e4Smiod {
302*3d8817e4Smiod int i;
303*3d8817e4Smiod
304*3d8817e4Smiod switch (*f)
305*3d8817e4Smiod {
306*3d8817e4Smiod case 'b':
307*3d8817e4Smiod case 'B':
308*3d8817e4Smiod i = FORMAT_BSD;
309*3d8817e4Smiod break;
310*3d8817e4Smiod case 'p':
311*3d8817e4Smiod case 'P':
312*3d8817e4Smiod i = FORMAT_POSIX;
313*3d8817e4Smiod break;
314*3d8817e4Smiod case 's':
315*3d8817e4Smiod case 'S':
316*3d8817e4Smiod i = FORMAT_SYSV;
317*3d8817e4Smiod break;
318*3d8817e4Smiod default:
319*3d8817e4Smiod fatal (_("%s: invalid output format"), f);
320*3d8817e4Smiod }
321*3d8817e4Smiod format = &formats[i];
322*3d8817e4Smiod }
323*3d8817e4Smiod
324*3d8817e4Smiod static const char *
get_symbol_type(unsigned int type)325*3d8817e4Smiod get_symbol_type (unsigned int type)
326*3d8817e4Smiod {
327*3d8817e4Smiod static char buff [32];
328*3d8817e4Smiod
329*3d8817e4Smiod switch (type)
330*3d8817e4Smiod {
331*3d8817e4Smiod case STT_NOTYPE: return "NOTYPE";
332*3d8817e4Smiod case STT_OBJECT: return "OBJECT";
333*3d8817e4Smiod case STT_FUNC: return "FUNC";
334*3d8817e4Smiod case STT_SECTION: return "SECTION";
335*3d8817e4Smiod case STT_FILE: return "FILE";
336*3d8817e4Smiod case STT_COMMON: return "COMMON";
337*3d8817e4Smiod case STT_TLS: return "TLS";
338*3d8817e4Smiod default:
339*3d8817e4Smiod if (type >= STT_LOPROC && type <= STT_HIPROC)
340*3d8817e4Smiod sprintf (buff, _("<processor specific>: %d"), type);
341*3d8817e4Smiod else if (type >= STT_LOOS && type <= STT_HIOS)
342*3d8817e4Smiod sprintf (buff, _("<OS specific>: %d"), type);
343*3d8817e4Smiod else
344*3d8817e4Smiod sprintf (buff, _("<unknown>: %d"), type);
345*3d8817e4Smiod return buff;
346*3d8817e4Smiod }
347*3d8817e4Smiod }
348*3d8817e4Smiod
349*3d8817e4Smiod /* Print symbol name NAME, read from ABFD, with printf format FORMAT,
350*3d8817e4Smiod demangling it if requested. */
351*3d8817e4Smiod
352*3d8817e4Smiod static void
print_symname(const char * format,const char * name,bfd * abfd)353*3d8817e4Smiod print_symname (const char *format, const char *name, bfd *abfd)
354*3d8817e4Smiod {
355*3d8817e4Smiod if (do_demangle && *name)
356*3d8817e4Smiod {
357*3d8817e4Smiod char *res = demangle (abfd, name);
358*3d8817e4Smiod
359*3d8817e4Smiod printf (format, res);
360*3d8817e4Smiod free (res);
361*3d8817e4Smiod return;
362*3d8817e4Smiod }
363*3d8817e4Smiod
364*3d8817e4Smiod printf (format, name);
365*3d8817e4Smiod }
366*3d8817e4Smiod
367*3d8817e4Smiod static void
print_symdef_entry(bfd * abfd)368*3d8817e4Smiod print_symdef_entry (bfd *abfd)
369*3d8817e4Smiod {
370*3d8817e4Smiod symindex idx = BFD_NO_MORE_SYMBOLS;
371*3d8817e4Smiod carsym *thesym;
372*3d8817e4Smiod bfd_boolean everprinted = FALSE;
373*3d8817e4Smiod
374*3d8817e4Smiod for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
375*3d8817e4Smiod idx != BFD_NO_MORE_SYMBOLS;
376*3d8817e4Smiod idx = bfd_get_next_mapent (abfd, idx, &thesym))
377*3d8817e4Smiod {
378*3d8817e4Smiod bfd *elt;
379*3d8817e4Smiod if (!everprinted)
380*3d8817e4Smiod {
381*3d8817e4Smiod printf (_("\nArchive index:\n"));
382*3d8817e4Smiod everprinted = TRUE;
383*3d8817e4Smiod }
384*3d8817e4Smiod elt = bfd_get_elt_at_index (abfd, idx);
385*3d8817e4Smiod if (elt == NULL)
386*3d8817e4Smiod bfd_fatal ("bfd_get_elt_at_index");
387*3d8817e4Smiod if (thesym->name != (char *) NULL)
388*3d8817e4Smiod {
389*3d8817e4Smiod print_symname ("%s", thesym->name, abfd);
390*3d8817e4Smiod printf (" in %s\n", bfd_get_filename (elt));
391*3d8817e4Smiod }
392*3d8817e4Smiod }
393*3d8817e4Smiod }
394*3d8817e4Smiod
395*3d8817e4Smiod /* Choose which symbol entries to print;
396*3d8817e4Smiod compact them downward to get rid of the rest.
397*3d8817e4Smiod Return the number of symbols to be printed. */
398*3d8817e4Smiod
399*3d8817e4Smiod static long
filter_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size)400*3d8817e4Smiod filter_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms,
401*3d8817e4Smiod long symcount, unsigned int size)
402*3d8817e4Smiod {
403*3d8817e4Smiod bfd_byte *from, *fromend, *to;
404*3d8817e4Smiod asymbol *store;
405*3d8817e4Smiod
406*3d8817e4Smiod store = bfd_make_empty_symbol (abfd);
407*3d8817e4Smiod if (store == NULL)
408*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
409*3d8817e4Smiod
410*3d8817e4Smiod from = (bfd_byte *) minisyms;
411*3d8817e4Smiod fromend = from + symcount * size;
412*3d8817e4Smiod to = (bfd_byte *) minisyms;
413*3d8817e4Smiod
414*3d8817e4Smiod for (; from < fromend; from += size)
415*3d8817e4Smiod {
416*3d8817e4Smiod int keep = 0;
417*3d8817e4Smiod asymbol *sym;
418*3d8817e4Smiod
419*3d8817e4Smiod PROGRESS (1);
420*3d8817e4Smiod
421*3d8817e4Smiod sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from, store);
422*3d8817e4Smiod if (sym == NULL)
423*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
424*3d8817e4Smiod
425*3d8817e4Smiod if (undefined_only)
426*3d8817e4Smiod keep = bfd_is_und_section (sym->section);
427*3d8817e4Smiod else if (external_only)
428*3d8817e4Smiod keep = ((sym->flags & BSF_GLOBAL) != 0
429*3d8817e4Smiod || (sym->flags & BSF_WEAK) != 0
430*3d8817e4Smiod || bfd_is_und_section (sym->section)
431*3d8817e4Smiod || bfd_is_com_section (sym->section));
432*3d8817e4Smiod else
433*3d8817e4Smiod keep = 1;
434*3d8817e4Smiod
435*3d8817e4Smiod if (keep
436*3d8817e4Smiod && ! print_debug_syms
437*3d8817e4Smiod && (sym->flags & BSF_DEBUGGING) != 0)
438*3d8817e4Smiod keep = 0;
439*3d8817e4Smiod
440*3d8817e4Smiod if (keep
441*3d8817e4Smiod && sort_by_size
442*3d8817e4Smiod && (bfd_is_abs_section (sym->section)
443*3d8817e4Smiod || bfd_is_und_section (sym->section)))
444*3d8817e4Smiod keep = 0;
445*3d8817e4Smiod
446*3d8817e4Smiod if (keep
447*3d8817e4Smiod && defined_only)
448*3d8817e4Smiod {
449*3d8817e4Smiod if (bfd_is_und_section (sym->section))
450*3d8817e4Smiod keep = 0;
451*3d8817e4Smiod }
452*3d8817e4Smiod
453*3d8817e4Smiod if (keep
454*3d8817e4Smiod && bfd_is_target_special_symbol (abfd, sym)
455*3d8817e4Smiod && ! allow_special_symbols)
456*3d8817e4Smiod keep = 0;
457*3d8817e4Smiod
458*3d8817e4Smiod if (keep)
459*3d8817e4Smiod {
460*3d8817e4Smiod memcpy (to, from, size);
461*3d8817e4Smiod to += size;
462*3d8817e4Smiod }
463*3d8817e4Smiod }
464*3d8817e4Smiod
465*3d8817e4Smiod return (to - (bfd_byte *) minisyms) / size;
466*3d8817e4Smiod }
467*3d8817e4Smiod
468*3d8817e4Smiod /* These globals are used to pass information into the sorting
469*3d8817e4Smiod routines. */
470*3d8817e4Smiod static bfd *sort_bfd;
471*3d8817e4Smiod static bfd_boolean sort_dynamic;
472*3d8817e4Smiod static asymbol *sort_x;
473*3d8817e4Smiod static asymbol *sort_y;
474*3d8817e4Smiod
475*3d8817e4Smiod /* Symbol-sorting predicates */
476*3d8817e4Smiod #define valueof(x) ((x)->section->vma + (x)->value)
477*3d8817e4Smiod
478*3d8817e4Smiod /* Numeric sorts. Undefined symbols are always considered "less than"
479*3d8817e4Smiod defined symbols with zero values. Common symbols are not treated
480*3d8817e4Smiod specially -- i.e., their sizes are used as their "values". */
481*3d8817e4Smiod
482*3d8817e4Smiod static int
non_numeric_forward(const void * P_x,const void * P_y)483*3d8817e4Smiod non_numeric_forward (const void *P_x, const void *P_y)
484*3d8817e4Smiod {
485*3d8817e4Smiod asymbol *x, *y;
486*3d8817e4Smiod const char *xn, *yn;
487*3d8817e4Smiod
488*3d8817e4Smiod x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
489*3d8817e4Smiod y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
490*3d8817e4Smiod if (x == NULL || y == NULL)
491*3d8817e4Smiod bfd_fatal (bfd_get_filename (sort_bfd));
492*3d8817e4Smiod
493*3d8817e4Smiod xn = bfd_asymbol_name (x);
494*3d8817e4Smiod yn = bfd_asymbol_name (y);
495*3d8817e4Smiod
496*3d8817e4Smiod if (yn == NULL)
497*3d8817e4Smiod return xn != NULL;
498*3d8817e4Smiod if (xn == NULL)
499*3d8817e4Smiod return -1;
500*3d8817e4Smiod
501*3d8817e4Smiod #ifdef HAVE_STRCOLL
502*3d8817e4Smiod /* Solaris 2.5 has a bug in strcoll.
503*3d8817e4Smiod strcoll returns invalid values when confronted with empty strings. */
504*3d8817e4Smiod if (*yn == '\0')
505*3d8817e4Smiod return *xn != '\0';
506*3d8817e4Smiod if (*xn == '\0')
507*3d8817e4Smiod return -1;
508*3d8817e4Smiod
509*3d8817e4Smiod return strcoll (xn, yn);
510*3d8817e4Smiod #else
511*3d8817e4Smiod return strcmp (xn, yn);
512*3d8817e4Smiod #endif
513*3d8817e4Smiod }
514*3d8817e4Smiod
515*3d8817e4Smiod static int
non_numeric_reverse(const void * x,const void * y)516*3d8817e4Smiod non_numeric_reverse (const void *x, const void *y)
517*3d8817e4Smiod {
518*3d8817e4Smiod return - non_numeric_forward (x, y);
519*3d8817e4Smiod }
520*3d8817e4Smiod
521*3d8817e4Smiod static int
numeric_forward(const void * P_x,const void * P_y)522*3d8817e4Smiod numeric_forward (const void *P_x, const void *P_y)
523*3d8817e4Smiod {
524*3d8817e4Smiod asymbol *x, *y;
525*3d8817e4Smiod asection *xs, *ys;
526*3d8817e4Smiod
527*3d8817e4Smiod x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
528*3d8817e4Smiod y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
529*3d8817e4Smiod if (x == NULL || y == NULL)
530*3d8817e4Smiod bfd_fatal (bfd_get_filename (sort_bfd));
531*3d8817e4Smiod
532*3d8817e4Smiod xs = bfd_get_section (x);
533*3d8817e4Smiod ys = bfd_get_section (y);
534*3d8817e4Smiod
535*3d8817e4Smiod if (bfd_is_und_section (xs))
536*3d8817e4Smiod {
537*3d8817e4Smiod if (! bfd_is_und_section (ys))
538*3d8817e4Smiod return -1;
539*3d8817e4Smiod }
540*3d8817e4Smiod else if (bfd_is_und_section (ys))
541*3d8817e4Smiod return 1;
542*3d8817e4Smiod else if (valueof (x) != valueof (y))
543*3d8817e4Smiod return valueof (x) < valueof (y) ? -1 : 1;
544*3d8817e4Smiod
545*3d8817e4Smiod return non_numeric_forward (P_x, P_y);
546*3d8817e4Smiod }
547*3d8817e4Smiod
548*3d8817e4Smiod static int
numeric_reverse(const void * x,const void * y)549*3d8817e4Smiod numeric_reverse (const void *x, const void *y)
550*3d8817e4Smiod {
551*3d8817e4Smiod return - numeric_forward (x, y);
552*3d8817e4Smiod }
553*3d8817e4Smiod
554*3d8817e4Smiod static int (*(sorters[2][2])) (const void *, const void *) =
555*3d8817e4Smiod {
556*3d8817e4Smiod { non_numeric_forward, non_numeric_reverse },
557*3d8817e4Smiod { numeric_forward, numeric_reverse }
558*3d8817e4Smiod };
559*3d8817e4Smiod
560*3d8817e4Smiod /* This sort routine is used by sort_symbols_by_size. It is similar
561*3d8817e4Smiod to numeric_forward, but when symbols have the same value it sorts
562*3d8817e4Smiod by section VMA. This simplifies the sort_symbols_by_size code
563*3d8817e4Smiod which handles symbols at the end of sections. Also, this routine
564*3d8817e4Smiod tries to sort file names before other symbols with the same value.
565*3d8817e4Smiod That will make the file name have a zero size, which will make
566*3d8817e4Smiod sort_symbols_by_size choose the non file name symbol, leading to
567*3d8817e4Smiod more meaningful output. For similar reasons, this code sorts
568*3d8817e4Smiod gnu_compiled_* and gcc2_compiled before other symbols with the same
569*3d8817e4Smiod value. */
570*3d8817e4Smiod
571*3d8817e4Smiod static int
size_forward1(const void * P_x,const void * P_y)572*3d8817e4Smiod size_forward1 (const void *P_x, const void *P_y)
573*3d8817e4Smiod {
574*3d8817e4Smiod asymbol *x, *y;
575*3d8817e4Smiod asection *xs, *ys;
576*3d8817e4Smiod const char *xn, *yn;
577*3d8817e4Smiod size_t xnl, ynl;
578*3d8817e4Smiod int xf, yf;
579*3d8817e4Smiod
580*3d8817e4Smiod x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
581*3d8817e4Smiod y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
582*3d8817e4Smiod if (x == NULL || y == NULL)
583*3d8817e4Smiod bfd_fatal (bfd_get_filename (sort_bfd));
584*3d8817e4Smiod
585*3d8817e4Smiod xs = bfd_get_section (x);
586*3d8817e4Smiod ys = bfd_get_section (y);
587*3d8817e4Smiod
588*3d8817e4Smiod if (bfd_is_und_section (xs))
589*3d8817e4Smiod abort ();
590*3d8817e4Smiod if (bfd_is_und_section (ys))
591*3d8817e4Smiod abort ();
592*3d8817e4Smiod
593*3d8817e4Smiod if (valueof (x) != valueof (y))
594*3d8817e4Smiod return valueof (x) < valueof (y) ? -1 : 1;
595*3d8817e4Smiod
596*3d8817e4Smiod if (xs->vma != ys->vma)
597*3d8817e4Smiod return xs->vma < ys->vma ? -1 : 1;
598*3d8817e4Smiod
599*3d8817e4Smiod xn = bfd_asymbol_name (x);
600*3d8817e4Smiod yn = bfd_asymbol_name (y);
601*3d8817e4Smiod xnl = strlen (xn);
602*3d8817e4Smiod ynl = strlen (yn);
603*3d8817e4Smiod
604*3d8817e4Smiod /* The symbols gnu_compiled and gcc2_compiled convey even less
605*3d8817e4Smiod information than the file name, so sort them out first. */
606*3d8817e4Smiod
607*3d8817e4Smiod xf = (strstr (xn, "gnu_compiled") != NULL
608*3d8817e4Smiod || strstr (xn, "gcc2_compiled") != NULL);
609*3d8817e4Smiod yf = (strstr (yn, "gnu_compiled") != NULL
610*3d8817e4Smiod || strstr (yn, "gcc2_compiled") != NULL);
611*3d8817e4Smiod
612*3d8817e4Smiod if (xf && ! yf)
613*3d8817e4Smiod return -1;
614*3d8817e4Smiod if (! xf && yf)
615*3d8817e4Smiod return 1;
616*3d8817e4Smiod
617*3d8817e4Smiod /* We use a heuristic for the file name. It may not work on non
618*3d8817e4Smiod Unix systems, but it doesn't really matter; the only difference
619*3d8817e4Smiod is precisely which symbol names get printed. */
620*3d8817e4Smiod
621*3d8817e4Smiod #define file_symbol(s, sn, snl) \
622*3d8817e4Smiod (((s)->flags & BSF_FILE) != 0 \
623*3d8817e4Smiod || ((sn)[(snl) - 2] == '.' \
624*3d8817e4Smiod && ((sn)[(snl) - 1] == 'o' \
625*3d8817e4Smiod || (sn)[(snl) - 1] == 'a')))
626*3d8817e4Smiod
627*3d8817e4Smiod xf = file_symbol (x, xn, xnl);
628*3d8817e4Smiod yf = file_symbol (y, yn, ynl);
629*3d8817e4Smiod
630*3d8817e4Smiod if (xf && ! yf)
631*3d8817e4Smiod return -1;
632*3d8817e4Smiod if (! xf && yf)
633*3d8817e4Smiod return 1;
634*3d8817e4Smiod
635*3d8817e4Smiod return non_numeric_forward (P_x, P_y);
636*3d8817e4Smiod }
637*3d8817e4Smiod
638*3d8817e4Smiod /* This sort routine is used by sort_symbols_by_size. It is sorting
639*3d8817e4Smiod an array of size_sym structures into size order. */
640*3d8817e4Smiod
641*3d8817e4Smiod static int
size_forward2(const void * P_x,const void * P_y)642*3d8817e4Smiod size_forward2 (const void *P_x, const void *P_y)
643*3d8817e4Smiod {
644*3d8817e4Smiod const struct size_sym *x = (const struct size_sym *) P_x;
645*3d8817e4Smiod const struct size_sym *y = (const struct size_sym *) P_y;
646*3d8817e4Smiod
647*3d8817e4Smiod if (x->size < y->size)
648*3d8817e4Smiod return reverse_sort ? 1 : -1;
649*3d8817e4Smiod else if (x->size > y->size)
650*3d8817e4Smiod return reverse_sort ? -1 : 1;
651*3d8817e4Smiod else
652*3d8817e4Smiod return sorters[0][reverse_sort] (x->minisym, y->minisym);
653*3d8817e4Smiod }
654*3d8817e4Smiod
655*3d8817e4Smiod /* Sort the symbols by size. ELF provides a size but for other formats
656*3d8817e4Smiod we have to make a guess by assuming that the difference between the
657*3d8817e4Smiod address of a symbol and the address of the next higher symbol is the
658*3d8817e4Smiod size. */
659*3d8817e4Smiod
660*3d8817e4Smiod static long
sort_symbols_by_size(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,struct size_sym ** symsizesp)661*3d8817e4Smiod sort_symbols_by_size (bfd *abfd, bfd_boolean dynamic, void *minisyms,
662*3d8817e4Smiod long symcount, unsigned int size,
663*3d8817e4Smiod struct size_sym **symsizesp)
664*3d8817e4Smiod {
665*3d8817e4Smiod struct size_sym *symsizes;
666*3d8817e4Smiod bfd_byte *from, *fromend;
667*3d8817e4Smiod asymbol *sym = NULL;
668*3d8817e4Smiod asymbol *store_sym, *store_next;
669*3d8817e4Smiod
670*3d8817e4Smiod qsort (minisyms, symcount, size, size_forward1);
671*3d8817e4Smiod
672*3d8817e4Smiod /* We are going to return a special set of symbols and sizes to
673*3d8817e4Smiod print. */
674*3d8817e4Smiod symsizes = xmalloc (symcount * sizeof (struct size_sym));
675*3d8817e4Smiod *symsizesp = symsizes;
676*3d8817e4Smiod
677*3d8817e4Smiod /* Note that filter_symbols has already removed all absolute and
678*3d8817e4Smiod undefined symbols. Here we remove all symbols whose size winds
679*3d8817e4Smiod up as zero. */
680*3d8817e4Smiod from = (bfd_byte *) minisyms;
681*3d8817e4Smiod fromend = from + symcount * size;
682*3d8817e4Smiod
683*3d8817e4Smiod store_sym = sort_x;
684*3d8817e4Smiod store_next = sort_y;
685*3d8817e4Smiod
686*3d8817e4Smiod if (from < fromend)
687*3d8817e4Smiod {
688*3d8817e4Smiod sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from,
689*3d8817e4Smiod store_sym);
690*3d8817e4Smiod if (sym == NULL)
691*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
692*3d8817e4Smiod }
693*3d8817e4Smiod
694*3d8817e4Smiod for (; from < fromend; from += size)
695*3d8817e4Smiod {
696*3d8817e4Smiod asymbol *next;
697*3d8817e4Smiod asection *sec;
698*3d8817e4Smiod bfd_vma sz;
699*3d8817e4Smiod asymbol *temp;
700*3d8817e4Smiod
701*3d8817e4Smiod if (from + size < fromend)
702*3d8817e4Smiod {
703*3d8817e4Smiod next = bfd_minisymbol_to_symbol (abfd,
704*3d8817e4Smiod dynamic,
705*3d8817e4Smiod (const void *) (from + size),
706*3d8817e4Smiod store_next);
707*3d8817e4Smiod if (next == NULL)
708*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
709*3d8817e4Smiod }
710*3d8817e4Smiod else
711*3d8817e4Smiod next = NULL;
712*3d8817e4Smiod
713*3d8817e4Smiod sec = bfd_get_section (sym);
714*3d8817e4Smiod
715*3d8817e4Smiod if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
716*3d8817e4Smiod sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
717*3d8817e4Smiod else if (bfd_is_com_section (sec))
718*3d8817e4Smiod sz = sym->value;
719*3d8817e4Smiod else
720*3d8817e4Smiod {
721*3d8817e4Smiod if (from + size < fromend
722*3d8817e4Smiod && sec == bfd_get_section (next))
723*3d8817e4Smiod sz = valueof (next) - valueof (sym);
724*3d8817e4Smiod else
725*3d8817e4Smiod sz = (bfd_get_section_vma (abfd, sec)
726*3d8817e4Smiod + bfd_section_size (abfd, sec)
727*3d8817e4Smiod - valueof (sym));
728*3d8817e4Smiod }
729*3d8817e4Smiod
730*3d8817e4Smiod if (sz != 0)
731*3d8817e4Smiod {
732*3d8817e4Smiod symsizes->minisym = (const void *) from;
733*3d8817e4Smiod symsizes->size = sz;
734*3d8817e4Smiod ++symsizes;
735*3d8817e4Smiod }
736*3d8817e4Smiod
737*3d8817e4Smiod sym = next;
738*3d8817e4Smiod
739*3d8817e4Smiod temp = store_sym;
740*3d8817e4Smiod store_sym = store_next;
741*3d8817e4Smiod store_next = temp;
742*3d8817e4Smiod }
743*3d8817e4Smiod
744*3d8817e4Smiod symcount = symsizes - *symsizesp;
745*3d8817e4Smiod
746*3d8817e4Smiod /* We must now sort again by size. */
747*3d8817e4Smiod qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
748*3d8817e4Smiod
749*3d8817e4Smiod return symcount;
750*3d8817e4Smiod }
751*3d8817e4Smiod
752*3d8817e4Smiod /* This function is used to get the relocs for a particular section.
753*3d8817e4Smiod It is called via bfd_map_over_sections. */
754*3d8817e4Smiod
755*3d8817e4Smiod static void
get_relocs(bfd * abfd,asection * sec,void * dataarg)756*3d8817e4Smiod get_relocs (bfd *abfd, asection *sec, void *dataarg)
757*3d8817e4Smiod {
758*3d8817e4Smiod struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
759*3d8817e4Smiod
760*3d8817e4Smiod *data->secs = sec;
761*3d8817e4Smiod
762*3d8817e4Smiod if ((sec->flags & SEC_RELOC) == 0)
763*3d8817e4Smiod {
764*3d8817e4Smiod *data->relocs = NULL;
765*3d8817e4Smiod *data->relcount = 0;
766*3d8817e4Smiod }
767*3d8817e4Smiod else
768*3d8817e4Smiod {
769*3d8817e4Smiod long relsize;
770*3d8817e4Smiod
771*3d8817e4Smiod relsize = bfd_get_reloc_upper_bound (abfd, sec);
772*3d8817e4Smiod if (relsize < 0)
773*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
774*3d8817e4Smiod
775*3d8817e4Smiod *data->relocs = xmalloc (relsize);
776*3d8817e4Smiod *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
777*3d8817e4Smiod data->syms);
778*3d8817e4Smiod if (*data->relcount < 0)
779*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
780*3d8817e4Smiod }
781*3d8817e4Smiod
782*3d8817e4Smiod ++data->secs;
783*3d8817e4Smiod ++data->relocs;
784*3d8817e4Smiod ++data->relcount;
785*3d8817e4Smiod }
786*3d8817e4Smiod
787*3d8817e4Smiod /* Print a single symbol. */
788*3d8817e4Smiod
789*3d8817e4Smiod static void
print_symbol(bfd * abfd,asymbol * sym,bfd_vma ssize,bfd * archive_bfd)790*3d8817e4Smiod print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
791*3d8817e4Smiod {
792*3d8817e4Smiod symbol_info syminfo;
793*3d8817e4Smiod struct extended_symbol_info info;
794*3d8817e4Smiod
795*3d8817e4Smiod PROGRESS (1);
796*3d8817e4Smiod
797*3d8817e4Smiod format->print_symbol_filename (archive_bfd, abfd);
798*3d8817e4Smiod
799*3d8817e4Smiod bfd_get_symbol_info (abfd, sym, &syminfo);
800*3d8817e4Smiod info.sinfo = &syminfo;
801*3d8817e4Smiod info.ssize = ssize;
802*3d8817e4Smiod if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
803*3d8817e4Smiod info.elfinfo = (elf_symbol_type *) sym;
804*3d8817e4Smiod else
805*3d8817e4Smiod info.elfinfo = NULL;
806*3d8817e4Smiod format->print_symbol_info (&info, abfd);
807*3d8817e4Smiod
808*3d8817e4Smiod if (line_numbers)
809*3d8817e4Smiod {
810*3d8817e4Smiod static asymbol **syms;
811*3d8817e4Smiod static long symcount;
812*3d8817e4Smiod const char *filename, *functionname;
813*3d8817e4Smiod unsigned int lineno;
814*3d8817e4Smiod
815*3d8817e4Smiod /* We need to get the canonical symbols in order to call
816*3d8817e4Smiod bfd_find_nearest_line. This is inefficient, but, then, you
817*3d8817e4Smiod don't have to use --line-numbers. */
818*3d8817e4Smiod if (abfd != lineno_cache_bfd && syms != NULL)
819*3d8817e4Smiod {
820*3d8817e4Smiod free (syms);
821*3d8817e4Smiod syms = NULL;
822*3d8817e4Smiod }
823*3d8817e4Smiod if (syms == NULL)
824*3d8817e4Smiod {
825*3d8817e4Smiod long symsize;
826*3d8817e4Smiod
827*3d8817e4Smiod symsize = bfd_get_symtab_upper_bound (abfd);
828*3d8817e4Smiod if (symsize < 0)
829*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
830*3d8817e4Smiod syms = xmalloc (symsize);
831*3d8817e4Smiod symcount = bfd_canonicalize_symtab (abfd, syms);
832*3d8817e4Smiod if (symcount < 0)
833*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
834*3d8817e4Smiod lineno_cache_bfd = abfd;
835*3d8817e4Smiod }
836*3d8817e4Smiod
837*3d8817e4Smiod if (bfd_is_und_section (bfd_get_section (sym)))
838*3d8817e4Smiod {
839*3d8817e4Smiod static asection **secs;
840*3d8817e4Smiod static arelent ***relocs;
841*3d8817e4Smiod static long *relcount;
842*3d8817e4Smiod static unsigned int seccount;
843*3d8817e4Smiod unsigned int i;
844*3d8817e4Smiod const char *symname;
845*3d8817e4Smiod
846*3d8817e4Smiod /* For an undefined symbol, we try to find a reloc for the
847*3d8817e4Smiod symbol, and print the line number of the reloc. */
848*3d8817e4Smiod if (abfd != lineno_cache_rel_bfd && relocs != NULL)
849*3d8817e4Smiod {
850*3d8817e4Smiod for (i = 0; i < seccount; i++)
851*3d8817e4Smiod if (relocs[i] != NULL)
852*3d8817e4Smiod free (relocs[i]);
853*3d8817e4Smiod free (secs);
854*3d8817e4Smiod free (relocs);
855*3d8817e4Smiod free (relcount);
856*3d8817e4Smiod secs = NULL;
857*3d8817e4Smiod relocs = NULL;
858*3d8817e4Smiod relcount = NULL;
859*3d8817e4Smiod }
860*3d8817e4Smiod
861*3d8817e4Smiod if (relocs == NULL)
862*3d8817e4Smiod {
863*3d8817e4Smiod struct get_relocs_info info;
864*3d8817e4Smiod
865*3d8817e4Smiod seccount = bfd_count_sections (abfd);
866*3d8817e4Smiod
867*3d8817e4Smiod secs = xmalloc (seccount * sizeof *secs);
868*3d8817e4Smiod relocs = xmalloc (seccount * sizeof *relocs);
869*3d8817e4Smiod relcount = xmalloc (seccount * sizeof *relcount);
870*3d8817e4Smiod
871*3d8817e4Smiod info.secs = secs;
872*3d8817e4Smiod info.relocs = relocs;
873*3d8817e4Smiod info.relcount = relcount;
874*3d8817e4Smiod info.syms = syms;
875*3d8817e4Smiod bfd_map_over_sections (abfd, get_relocs, (void *) &info);
876*3d8817e4Smiod lineno_cache_rel_bfd = abfd;
877*3d8817e4Smiod }
878*3d8817e4Smiod
879*3d8817e4Smiod symname = bfd_asymbol_name (sym);
880*3d8817e4Smiod for (i = 0; i < seccount; i++)
881*3d8817e4Smiod {
882*3d8817e4Smiod long j;
883*3d8817e4Smiod
884*3d8817e4Smiod for (j = 0; j < relcount[i]; j++)
885*3d8817e4Smiod {
886*3d8817e4Smiod arelent *r;
887*3d8817e4Smiod
888*3d8817e4Smiod r = relocs[i][j];
889*3d8817e4Smiod if (r->sym_ptr_ptr != NULL
890*3d8817e4Smiod && (*r->sym_ptr_ptr)->section == sym->section
891*3d8817e4Smiod && (*r->sym_ptr_ptr)->value == sym->value
892*3d8817e4Smiod && strcmp (symname,
893*3d8817e4Smiod bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
894*3d8817e4Smiod && bfd_find_nearest_line (abfd, secs[i], syms,
895*3d8817e4Smiod r->address, &filename,
896*3d8817e4Smiod &functionname, &lineno)
897*3d8817e4Smiod && filename != NULL)
898*3d8817e4Smiod {
899*3d8817e4Smiod /* We only print the first one we find. */
900*3d8817e4Smiod printf ("\t%s:%u", filename, lineno);
901*3d8817e4Smiod i = seccount;
902*3d8817e4Smiod break;
903*3d8817e4Smiod }
904*3d8817e4Smiod }
905*3d8817e4Smiod }
906*3d8817e4Smiod }
907*3d8817e4Smiod else if (bfd_get_section (sym)->owner == abfd)
908*3d8817e4Smiod {
909*3d8817e4Smiod if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
910*3d8817e4Smiod || bfd_find_nearest_line (abfd, bfd_get_section (sym),
911*3d8817e4Smiod syms, sym->value, &filename,
912*3d8817e4Smiod &functionname, &lineno))
913*3d8817e4Smiod && filename != NULL
914*3d8817e4Smiod && lineno != 0)
915*3d8817e4Smiod printf ("\t%s:%u", filename, lineno);
916*3d8817e4Smiod }
917*3d8817e4Smiod }
918*3d8817e4Smiod
919*3d8817e4Smiod putchar ('\n');
920*3d8817e4Smiod }
921*3d8817e4Smiod
922*3d8817e4Smiod /* Print the symbols when sorting by size. */
923*3d8817e4Smiod
924*3d8817e4Smiod static void
print_size_symbols(bfd * abfd,bfd_boolean dynamic,struct size_sym * symsizes,long symcount,bfd * archive_bfd)925*3d8817e4Smiod print_size_symbols (bfd *abfd, bfd_boolean dynamic,
926*3d8817e4Smiod struct size_sym *symsizes, long symcount,
927*3d8817e4Smiod bfd *archive_bfd)
928*3d8817e4Smiod {
929*3d8817e4Smiod asymbol *store;
930*3d8817e4Smiod struct size_sym *from, *fromend;
931*3d8817e4Smiod
932*3d8817e4Smiod store = bfd_make_empty_symbol (abfd);
933*3d8817e4Smiod if (store == NULL)
934*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
935*3d8817e4Smiod
936*3d8817e4Smiod from = symsizes;
937*3d8817e4Smiod fromend = from + symcount;
938*3d8817e4Smiod for (; from < fromend; from++)
939*3d8817e4Smiod {
940*3d8817e4Smiod asymbol *sym;
941*3d8817e4Smiod bfd_vma ssize;
942*3d8817e4Smiod
943*3d8817e4Smiod sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
944*3d8817e4Smiod if (sym == NULL)
945*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
946*3d8817e4Smiod
947*3d8817e4Smiod /* For elf we have already computed the correct symbol size. */
948*3d8817e4Smiod if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
949*3d8817e4Smiod ssize = from->size;
950*3d8817e4Smiod else
951*3d8817e4Smiod ssize = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
952*3d8817e4Smiod
953*3d8817e4Smiod print_symbol (abfd, sym, ssize, archive_bfd);
954*3d8817e4Smiod }
955*3d8817e4Smiod }
956*3d8817e4Smiod
957*3d8817e4Smiod
958*3d8817e4Smiod /* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive
959*3d8817e4Smiod containing ABFD. */
960*3d8817e4Smiod
961*3d8817e4Smiod static void
print_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,bfd * archive_bfd)962*3d8817e4Smiod print_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms, long symcount,
963*3d8817e4Smiod unsigned int size, bfd *archive_bfd)
964*3d8817e4Smiod {
965*3d8817e4Smiod asymbol *store;
966*3d8817e4Smiod bfd_byte *from, *fromend;
967*3d8817e4Smiod
968*3d8817e4Smiod store = bfd_make_empty_symbol (abfd);
969*3d8817e4Smiod if (store == NULL)
970*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
971*3d8817e4Smiod
972*3d8817e4Smiod from = (bfd_byte *) minisyms;
973*3d8817e4Smiod fromend = from + symcount * size;
974*3d8817e4Smiod for (; from < fromend; from += size)
975*3d8817e4Smiod {
976*3d8817e4Smiod asymbol *sym;
977*3d8817e4Smiod
978*3d8817e4Smiod sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
979*3d8817e4Smiod if (sym == NULL)
980*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
981*3d8817e4Smiod
982*3d8817e4Smiod print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
983*3d8817e4Smiod }
984*3d8817e4Smiod }
985*3d8817e4Smiod
986*3d8817e4Smiod /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */
987*3d8817e4Smiod
988*3d8817e4Smiod static void
display_rel_file(bfd * abfd,bfd * archive_bfd)989*3d8817e4Smiod display_rel_file (bfd *abfd, bfd *archive_bfd)
990*3d8817e4Smiod {
991*3d8817e4Smiod long symcount;
992*3d8817e4Smiod void *minisyms;
993*3d8817e4Smiod unsigned int size;
994*3d8817e4Smiod struct size_sym *symsizes;
995*3d8817e4Smiod
996*3d8817e4Smiod if (! dynamic)
997*3d8817e4Smiod {
998*3d8817e4Smiod if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
999*3d8817e4Smiod {
1000*3d8817e4Smiod non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
1001*3d8817e4Smiod return;
1002*3d8817e4Smiod }
1003*3d8817e4Smiod }
1004*3d8817e4Smiod
1005*3d8817e4Smiod symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
1006*3d8817e4Smiod if (symcount < 0)
1007*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
1008*3d8817e4Smiod
1009*3d8817e4Smiod if (symcount == 0)
1010*3d8817e4Smiod {
1011*3d8817e4Smiod non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
1012*3d8817e4Smiod return;
1013*3d8817e4Smiod }
1014*3d8817e4Smiod
1015*3d8817e4Smiod if (show_synthetic && size == sizeof (asymbol *))
1016*3d8817e4Smiod {
1017*3d8817e4Smiod asymbol *synthsyms;
1018*3d8817e4Smiod long synth_count;
1019*3d8817e4Smiod asymbol **static_syms = NULL;
1020*3d8817e4Smiod asymbol **dyn_syms = NULL;
1021*3d8817e4Smiod long static_count = 0;
1022*3d8817e4Smiod long dyn_count = 0;
1023*3d8817e4Smiod
1024*3d8817e4Smiod if (dynamic)
1025*3d8817e4Smiod {
1026*3d8817e4Smiod dyn_count = symcount;
1027*3d8817e4Smiod dyn_syms = minisyms;
1028*3d8817e4Smiod }
1029*3d8817e4Smiod else
1030*3d8817e4Smiod {
1031*3d8817e4Smiod long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
1032*3d8817e4Smiod
1033*3d8817e4Smiod static_count = symcount;
1034*3d8817e4Smiod static_syms = minisyms;
1035*3d8817e4Smiod
1036*3d8817e4Smiod if (storage > 0)
1037*3d8817e4Smiod {
1038*3d8817e4Smiod dyn_syms = xmalloc (storage);
1039*3d8817e4Smiod dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms);
1040*3d8817e4Smiod if (dyn_count < 0)
1041*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
1042*3d8817e4Smiod }
1043*3d8817e4Smiod }
1044*3d8817e4Smiod synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
1045*3d8817e4Smiod dyn_count, dyn_syms, &synthsyms);
1046*3d8817e4Smiod if (synth_count > 0)
1047*3d8817e4Smiod {
1048*3d8817e4Smiod asymbol **symp;
1049*3d8817e4Smiod void *new_mini;
1050*3d8817e4Smiod long i;
1051*3d8817e4Smiod
1052*3d8817e4Smiod new_mini = xmalloc ((symcount + synth_count + 1) * sizeof (*symp));
1053*3d8817e4Smiod symp = new_mini;
1054*3d8817e4Smiod memcpy (symp, minisyms, symcount * sizeof (*symp));
1055*3d8817e4Smiod symp += symcount;
1056*3d8817e4Smiod for (i = 0; i < synth_count; i++)
1057*3d8817e4Smiod *symp++ = synthsyms + i;
1058*3d8817e4Smiod *symp = 0;
1059*3d8817e4Smiod minisyms = new_mini;
1060*3d8817e4Smiod symcount += synth_count;
1061*3d8817e4Smiod }
1062*3d8817e4Smiod }
1063*3d8817e4Smiod
1064*3d8817e4Smiod /* Discard the symbols we don't want to print.
1065*3d8817e4Smiod It's OK to do this in place; we'll free the storage anyway
1066*3d8817e4Smiod (after printing). */
1067*3d8817e4Smiod
1068*3d8817e4Smiod symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
1069*3d8817e4Smiod
1070*3d8817e4Smiod symsizes = NULL;
1071*3d8817e4Smiod if (! no_sort)
1072*3d8817e4Smiod {
1073*3d8817e4Smiod sort_bfd = abfd;
1074*3d8817e4Smiod sort_dynamic = dynamic;
1075*3d8817e4Smiod sort_x = bfd_make_empty_symbol (abfd);
1076*3d8817e4Smiod sort_y = bfd_make_empty_symbol (abfd);
1077*3d8817e4Smiod if (sort_x == NULL || sort_y == NULL)
1078*3d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
1079*3d8817e4Smiod
1080*3d8817e4Smiod if (! sort_by_size)
1081*3d8817e4Smiod qsort (minisyms, symcount, size,
1082*3d8817e4Smiod sorters[sort_numerically][reverse_sort]);
1083*3d8817e4Smiod else
1084*3d8817e4Smiod symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
1085*3d8817e4Smiod size, &symsizes);
1086*3d8817e4Smiod }
1087*3d8817e4Smiod
1088*3d8817e4Smiod if (! sort_by_size)
1089*3d8817e4Smiod print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
1090*3d8817e4Smiod else
1091*3d8817e4Smiod print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
1092*3d8817e4Smiod
1093*3d8817e4Smiod free (minisyms);
1094*3d8817e4Smiod }
1095*3d8817e4Smiod
1096*3d8817e4Smiod static void
display_archive(bfd * file)1097*3d8817e4Smiod display_archive (bfd *file)
1098*3d8817e4Smiod {
1099*3d8817e4Smiod bfd *arfile = NULL;
1100*3d8817e4Smiod bfd *last_arfile = NULL;
1101*3d8817e4Smiod char **matching;
1102*3d8817e4Smiod
1103*3d8817e4Smiod format->print_archive_filename (bfd_get_filename (file));
1104*3d8817e4Smiod
1105*3d8817e4Smiod if (print_armap)
1106*3d8817e4Smiod print_symdef_entry (file);
1107*3d8817e4Smiod
1108*3d8817e4Smiod for (;;)
1109*3d8817e4Smiod {
1110*3d8817e4Smiod PROGRESS (1);
1111*3d8817e4Smiod
1112*3d8817e4Smiod arfile = bfd_openr_next_archived_file (file, arfile);
1113*3d8817e4Smiod
1114*3d8817e4Smiod if (arfile == NULL)
1115*3d8817e4Smiod {
1116*3d8817e4Smiod if (bfd_get_error () != bfd_error_no_more_archived_files)
1117*3d8817e4Smiod bfd_fatal (bfd_get_filename (file));
1118*3d8817e4Smiod break;
1119*3d8817e4Smiod }
1120*3d8817e4Smiod
1121*3d8817e4Smiod if (bfd_check_format_matches (arfile, bfd_object, &matching))
1122*3d8817e4Smiod {
1123*3d8817e4Smiod char buf[30];
1124*3d8817e4Smiod
1125*3d8817e4Smiod bfd_sprintf_vma (arfile, buf, (bfd_vma) -1);
1126*3d8817e4Smiod print_width = strlen (buf);
1127*3d8817e4Smiod format->print_archive_member (bfd_get_filename (file),
1128*3d8817e4Smiod bfd_get_filename (arfile));
1129*3d8817e4Smiod display_rel_file (arfile, file);
1130*3d8817e4Smiod }
1131*3d8817e4Smiod else
1132*3d8817e4Smiod {
1133*3d8817e4Smiod bfd_nonfatal (bfd_get_filename (arfile));
1134*3d8817e4Smiod if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1135*3d8817e4Smiod {
1136*3d8817e4Smiod list_matching_formats (matching);
1137*3d8817e4Smiod free (matching);
1138*3d8817e4Smiod }
1139*3d8817e4Smiod }
1140*3d8817e4Smiod
1141*3d8817e4Smiod if (last_arfile != NULL)
1142*3d8817e4Smiod {
1143*3d8817e4Smiod bfd_close (last_arfile);
1144*3d8817e4Smiod lineno_cache_bfd = NULL;
1145*3d8817e4Smiod lineno_cache_rel_bfd = NULL;
1146*3d8817e4Smiod }
1147*3d8817e4Smiod last_arfile = arfile;
1148*3d8817e4Smiod }
1149*3d8817e4Smiod
1150*3d8817e4Smiod if (last_arfile != NULL)
1151*3d8817e4Smiod {
1152*3d8817e4Smiod bfd_close (last_arfile);
1153*3d8817e4Smiod lineno_cache_bfd = NULL;
1154*3d8817e4Smiod lineno_cache_rel_bfd = NULL;
1155*3d8817e4Smiod }
1156*3d8817e4Smiod }
1157*3d8817e4Smiod
1158*3d8817e4Smiod static bfd_boolean
display_file(char * filename)1159*3d8817e4Smiod display_file (char *filename)
1160*3d8817e4Smiod {
1161*3d8817e4Smiod bfd_boolean retval = TRUE;
1162*3d8817e4Smiod bfd *file;
1163*3d8817e4Smiod char **matching;
1164*3d8817e4Smiod
1165*3d8817e4Smiod if (get_file_size (filename) < 1)
1166*3d8817e4Smiod return FALSE;
1167*3d8817e4Smiod
1168*3d8817e4Smiod file = bfd_openr (filename, target);
1169*3d8817e4Smiod if (file == NULL)
1170*3d8817e4Smiod {
1171*3d8817e4Smiod bfd_nonfatal (filename);
1172*3d8817e4Smiod return FALSE;
1173*3d8817e4Smiod }
1174*3d8817e4Smiod
1175*3d8817e4Smiod if (bfd_check_format (file, bfd_archive))
1176*3d8817e4Smiod {
1177*3d8817e4Smiod display_archive (file);
1178*3d8817e4Smiod }
1179*3d8817e4Smiod else if (bfd_check_format_matches (file, bfd_object, &matching))
1180*3d8817e4Smiod {
1181*3d8817e4Smiod char buf[30];
1182*3d8817e4Smiod
1183*3d8817e4Smiod bfd_sprintf_vma (file, buf, (bfd_vma) -1);
1184*3d8817e4Smiod print_width = strlen (buf);
1185*3d8817e4Smiod format->print_object_filename (filename);
1186*3d8817e4Smiod display_rel_file (file, NULL);
1187*3d8817e4Smiod }
1188*3d8817e4Smiod else
1189*3d8817e4Smiod {
1190*3d8817e4Smiod bfd_nonfatal (filename);
1191*3d8817e4Smiod if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1192*3d8817e4Smiod {
1193*3d8817e4Smiod list_matching_formats (matching);
1194*3d8817e4Smiod free (matching);
1195*3d8817e4Smiod }
1196*3d8817e4Smiod retval = FALSE;
1197*3d8817e4Smiod }
1198*3d8817e4Smiod
1199*3d8817e4Smiod if (!bfd_close (file))
1200*3d8817e4Smiod bfd_fatal (filename);
1201*3d8817e4Smiod
1202*3d8817e4Smiod lineno_cache_bfd = NULL;
1203*3d8817e4Smiod lineno_cache_rel_bfd = NULL;
1204*3d8817e4Smiod
1205*3d8817e4Smiod return retval;
1206*3d8817e4Smiod }
1207*3d8817e4Smiod
1208*3d8817e4Smiod /* The following 3 groups of functions are called unconditionally,
1209*3d8817e4Smiod once at the start of processing each file of the appropriate type.
1210*3d8817e4Smiod They should check `filename_per_file' and `filename_per_symbol',
1211*3d8817e4Smiod as appropriate for their output format, to determine whether to
1212*3d8817e4Smiod print anything. */
1213*3d8817e4Smiod
1214*3d8817e4Smiod /* Print the name of an object file given on the command line. */
1215*3d8817e4Smiod
1216*3d8817e4Smiod static void
print_object_filename_bsd(char * filename)1217*3d8817e4Smiod print_object_filename_bsd (char *filename)
1218*3d8817e4Smiod {
1219*3d8817e4Smiod if (filename_per_file && !filename_per_symbol)
1220*3d8817e4Smiod printf ("\n%s:\n", filename);
1221*3d8817e4Smiod }
1222*3d8817e4Smiod
1223*3d8817e4Smiod static void
print_object_filename_sysv(char * filename)1224*3d8817e4Smiod print_object_filename_sysv (char *filename)
1225*3d8817e4Smiod {
1226*3d8817e4Smiod if (undefined_only)
1227*3d8817e4Smiod printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
1228*3d8817e4Smiod else
1229*3d8817e4Smiod printf (_("\n\nSymbols from %s:\n\n"), filename);
1230*3d8817e4Smiod if (print_width == 8)
1231*3d8817e4Smiod printf (_("\
1232*3d8817e4Smiod Name Value Class Type Size Line Section\n\n"));
1233*3d8817e4Smiod else
1234*3d8817e4Smiod printf (_("\
1235*3d8817e4Smiod Name Value Class Type Size Line Section\n\n"));
1236*3d8817e4Smiod }
1237*3d8817e4Smiod
1238*3d8817e4Smiod static void
print_object_filename_posix(char * filename)1239*3d8817e4Smiod print_object_filename_posix (char *filename)
1240*3d8817e4Smiod {
1241*3d8817e4Smiod if (filename_per_file && !filename_per_symbol)
1242*3d8817e4Smiod printf ("%s:\n", filename);
1243*3d8817e4Smiod }
1244*3d8817e4Smiod
1245*3d8817e4Smiod /* Print the name of an archive file given on the command line. */
1246*3d8817e4Smiod
1247*3d8817e4Smiod static void
print_archive_filename_bsd(char * filename)1248*3d8817e4Smiod print_archive_filename_bsd (char *filename)
1249*3d8817e4Smiod {
1250*3d8817e4Smiod if (filename_per_file)
1251*3d8817e4Smiod printf ("\n%s:\n", filename);
1252*3d8817e4Smiod }
1253*3d8817e4Smiod
1254*3d8817e4Smiod static void
print_archive_filename_sysv(char * filename ATTRIBUTE_UNUSED)1255*3d8817e4Smiod print_archive_filename_sysv (char *filename ATTRIBUTE_UNUSED)
1256*3d8817e4Smiod {
1257*3d8817e4Smiod }
1258*3d8817e4Smiod
1259*3d8817e4Smiod static void
print_archive_filename_posix(char * filename ATTRIBUTE_UNUSED)1260*3d8817e4Smiod print_archive_filename_posix (char *filename ATTRIBUTE_UNUSED)
1261*3d8817e4Smiod {
1262*3d8817e4Smiod }
1263*3d8817e4Smiod
1264*3d8817e4Smiod /* Print the name of an archive member file. */
1265*3d8817e4Smiod
1266*3d8817e4Smiod static void
print_archive_member_bsd(char * archive ATTRIBUTE_UNUSED,const char * filename)1267*3d8817e4Smiod print_archive_member_bsd (char *archive ATTRIBUTE_UNUSED,
1268*3d8817e4Smiod const char *filename)
1269*3d8817e4Smiod {
1270*3d8817e4Smiod if (!filename_per_symbol)
1271*3d8817e4Smiod printf ("\n%s:\n", filename);
1272*3d8817e4Smiod }
1273*3d8817e4Smiod
1274*3d8817e4Smiod static void
print_archive_member_sysv(char * archive,const char * filename)1275*3d8817e4Smiod print_archive_member_sysv (char *archive, const char *filename)
1276*3d8817e4Smiod {
1277*3d8817e4Smiod if (undefined_only)
1278*3d8817e4Smiod printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
1279*3d8817e4Smiod else
1280*3d8817e4Smiod printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
1281*3d8817e4Smiod if (print_width == 8)
1282*3d8817e4Smiod printf (_("\
1283*3d8817e4Smiod Name Value Class Type Size Line Section\n\n"));
1284*3d8817e4Smiod else
1285*3d8817e4Smiod printf (_("\
1286*3d8817e4Smiod Name Value Class Type Size Line Section\n\n"));
1287*3d8817e4Smiod }
1288*3d8817e4Smiod
1289*3d8817e4Smiod static void
print_archive_member_posix(char * archive,const char * filename)1290*3d8817e4Smiod print_archive_member_posix (char *archive, const char *filename)
1291*3d8817e4Smiod {
1292*3d8817e4Smiod if (!filename_per_symbol)
1293*3d8817e4Smiod printf ("%s[%s]:\n", archive, filename);
1294*3d8817e4Smiod }
1295*3d8817e4Smiod
1296*3d8817e4Smiod /* Print the name of the file (and archive, if there is one)
1297*3d8817e4Smiod containing a symbol. */
1298*3d8817e4Smiod
1299*3d8817e4Smiod static void
print_symbol_filename_bsd(bfd * archive_bfd,bfd * abfd)1300*3d8817e4Smiod print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
1301*3d8817e4Smiod {
1302*3d8817e4Smiod if (filename_per_symbol)
1303*3d8817e4Smiod {
1304*3d8817e4Smiod if (archive_bfd)
1305*3d8817e4Smiod printf ("%s:", bfd_get_filename (archive_bfd));
1306*3d8817e4Smiod printf ("%s:", bfd_get_filename (abfd));
1307*3d8817e4Smiod }
1308*3d8817e4Smiod }
1309*3d8817e4Smiod
1310*3d8817e4Smiod static void
print_symbol_filename_sysv(bfd * archive_bfd,bfd * abfd)1311*3d8817e4Smiod print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
1312*3d8817e4Smiod {
1313*3d8817e4Smiod if (filename_per_symbol)
1314*3d8817e4Smiod {
1315*3d8817e4Smiod if (archive_bfd)
1316*3d8817e4Smiod printf ("%s:", bfd_get_filename (archive_bfd));
1317*3d8817e4Smiod printf ("%s:", bfd_get_filename (abfd));
1318*3d8817e4Smiod }
1319*3d8817e4Smiod }
1320*3d8817e4Smiod
1321*3d8817e4Smiod static void
print_symbol_filename_posix(bfd * archive_bfd,bfd * abfd)1322*3d8817e4Smiod print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
1323*3d8817e4Smiod {
1324*3d8817e4Smiod if (filename_per_symbol)
1325*3d8817e4Smiod {
1326*3d8817e4Smiod if (archive_bfd)
1327*3d8817e4Smiod printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
1328*3d8817e4Smiod bfd_get_filename (abfd));
1329*3d8817e4Smiod else
1330*3d8817e4Smiod printf ("%s: ", bfd_get_filename (abfd));
1331*3d8817e4Smiod }
1332*3d8817e4Smiod }
1333*3d8817e4Smiod
1334*3d8817e4Smiod /* Print a symbol value. */
1335*3d8817e4Smiod
1336*3d8817e4Smiod static void
print_value(bfd * abfd ATTRIBUTE_UNUSED,bfd_vma val)1337*3d8817e4Smiod print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
1338*3d8817e4Smiod {
1339*3d8817e4Smiod #if ! defined (BFD64) || BFD_HOST_64BIT_LONG
1340*3d8817e4Smiod printf (value_format, val);
1341*3d8817e4Smiod #else
1342*3d8817e4Smiod /* We have a 64 bit value to print, but the host is only 32 bit. */
1343*3d8817e4Smiod if (print_radix == 16)
1344*3d8817e4Smiod bfd_fprintf_vma (abfd, stdout, val);
1345*3d8817e4Smiod else
1346*3d8817e4Smiod {
1347*3d8817e4Smiod char buf[30];
1348*3d8817e4Smiod char *s;
1349*3d8817e4Smiod
1350*3d8817e4Smiod s = buf + sizeof buf;
1351*3d8817e4Smiod *--s = '\0';
1352*3d8817e4Smiod while (val > 0)
1353*3d8817e4Smiod {
1354*3d8817e4Smiod *--s = (val % print_radix) + '0';
1355*3d8817e4Smiod val /= print_radix;
1356*3d8817e4Smiod }
1357*3d8817e4Smiod while ((buf + sizeof buf - 1) - s < 16)
1358*3d8817e4Smiod *--s = '0';
1359*3d8817e4Smiod printf ("%s", s);
1360*3d8817e4Smiod }
1361*3d8817e4Smiod #endif
1362*3d8817e4Smiod }
1363*3d8817e4Smiod
1364*3d8817e4Smiod /* Print a line of information about a symbol. */
1365*3d8817e4Smiod
1366*3d8817e4Smiod static void
print_symbol_info_bsd(struct extended_symbol_info * info,bfd * abfd)1367*3d8817e4Smiod print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
1368*3d8817e4Smiod {
1369*3d8817e4Smiod if (bfd_is_undefined_symclass (SYM_TYPE (info)))
1370*3d8817e4Smiod {
1371*3d8817e4Smiod if (print_width == 16)
1372*3d8817e4Smiod printf (" ");
1373*3d8817e4Smiod printf (" ");
1374*3d8817e4Smiod }
1375*3d8817e4Smiod else
1376*3d8817e4Smiod {
1377*3d8817e4Smiod /* Normally we print the value of the symbol. If we are printing the
1378*3d8817e4Smiod size or sorting by size then we print its size, except for the
1379*3d8817e4Smiod (weird) special case where both flags are defined, in which case we
1380*3d8817e4Smiod print both values. This conforms to documented behaviour. */
1381*3d8817e4Smiod if (sort_by_size && !print_size)
1382*3d8817e4Smiod print_value (abfd, SYM_SIZE (info));
1383*3d8817e4Smiod else
1384*3d8817e4Smiod print_value (abfd, SYM_VALUE (info));
1385*3d8817e4Smiod
1386*3d8817e4Smiod if (print_size && SYM_SIZE (info))
1387*3d8817e4Smiod {
1388*3d8817e4Smiod printf (" ");
1389*3d8817e4Smiod print_value (abfd, SYM_SIZE (info));
1390*3d8817e4Smiod }
1391*3d8817e4Smiod }
1392*3d8817e4Smiod
1393*3d8817e4Smiod printf (" %c", SYM_TYPE (info));
1394*3d8817e4Smiod
1395*3d8817e4Smiod if (SYM_TYPE (info) == '-')
1396*3d8817e4Smiod {
1397*3d8817e4Smiod /* A stab. */
1398*3d8817e4Smiod printf (" ");
1399*3d8817e4Smiod printf (other_format, SYM_STAB_OTHER (info));
1400*3d8817e4Smiod printf (" ");
1401*3d8817e4Smiod printf (desc_format, SYM_STAB_DESC (info));
1402*3d8817e4Smiod printf (" %5s", SYM_STAB_NAME (info));
1403*3d8817e4Smiod }
1404*3d8817e4Smiod print_symname (" %s", SYM_NAME (info), abfd);
1405*3d8817e4Smiod }
1406*3d8817e4Smiod
1407*3d8817e4Smiod static void
print_symbol_info_sysv(struct extended_symbol_info * info,bfd * abfd)1408*3d8817e4Smiod print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
1409*3d8817e4Smiod {
1410*3d8817e4Smiod print_symname ("%-20s|", SYM_NAME (info), abfd);
1411*3d8817e4Smiod
1412*3d8817e4Smiod if (bfd_is_undefined_symclass (SYM_TYPE (info)))
1413*3d8817e4Smiod {
1414*3d8817e4Smiod if (print_width == 8)
1415*3d8817e4Smiod printf (" ");
1416*3d8817e4Smiod else
1417*3d8817e4Smiod printf (" ");
1418*3d8817e4Smiod }
1419*3d8817e4Smiod else
1420*3d8817e4Smiod print_value (abfd, SYM_VALUE (info));
1421*3d8817e4Smiod
1422*3d8817e4Smiod printf ("| %c |", SYM_TYPE (info));
1423*3d8817e4Smiod
1424*3d8817e4Smiod if (SYM_TYPE (info) == '-')
1425*3d8817e4Smiod {
1426*3d8817e4Smiod /* A stab. */
1427*3d8817e4Smiod printf ("%18s| ", SYM_STAB_NAME (info)); /* (C) Type. */
1428*3d8817e4Smiod printf (desc_format, SYM_STAB_DESC (info)); /* Size. */
1429*3d8817e4Smiod printf ("| |"); /* Line, Section. */
1430*3d8817e4Smiod }
1431*3d8817e4Smiod else
1432*3d8817e4Smiod {
1433*3d8817e4Smiod /* Type, Size, Line, Section */
1434*3d8817e4Smiod if (info->elfinfo)
1435*3d8817e4Smiod printf ("%18s|",
1436*3d8817e4Smiod get_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
1437*3d8817e4Smiod else
1438*3d8817e4Smiod printf (" |");
1439*3d8817e4Smiod
1440*3d8817e4Smiod if (SYM_SIZE (info))
1441*3d8817e4Smiod print_value (abfd, SYM_SIZE (info));
1442*3d8817e4Smiod else
1443*3d8817e4Smiod {
1444*3d8817e4Smiod if (print_width == 8)
1445*3d8817e4Smiod printf (" ");
1446*3d8817e4Smiod else
1447*3d8817e4Smiod printf (" ");
1448*3d8817e4Smiod }
1449*3d8817e4Smiod
1450*3d8817e4Smiod if (info->elfinfo)
1451*3d8817e4Smiod printf("| |%s", info->elfinfo->symbol.section->name);
1452*3d8817e4Smiod else
1453*3d8817e4Smiod printf("| |");
1454*3d8817e4Smiod }
1455*3d8817e4Smiod }
1456*3d8817e4Smiod
1457*3d8817e4Smiod static void
print_symbol_info_posix(struct extended_symbol_info * info,bfd * abfd)1458*3d8817e4Smiod print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
1459*3d8817e4Smiod {
1460*3d8817e4Smiod print_symname ("%s ", SYM_NAME (info), abfd);
1461*3d8817e4Smiod printf ("%c ", SYM_TYPE (info));
1462*3d8817e4Smiod
1463*3d8817e4Smiod if (bfd_is_undefined_symclass (SYM_TYPE (info)))
1464*3d8817e4Smiod printf (" ");
1465*3d8817e4Smiod else
1466*3d8817e4Smiod {
1467*3d8817e4Smiod print_value (abfd, SYM_VALUE (info));
1468*3d8817e4Smiod printf (" ");
1469*3d8817e4Smiod if (SYM_SIZE (info))
1470*3d8817e4Smiod print_value (abfd, SYM_SIZE (info));
1471*3d8817e4Smiod }
1472*3d8817e4Smiod }
1473*3d8817e4Smiod
1474*3d8817e4Smiod int
main(int argc,char ** argv)1475*3d8817e4Smiod main (int argc, char **argv)
1476*3d8817e4Smiod {
1477*3d8817e4Smiod int c;
1478*3d8817e4Smiod int retval;
1479*3d8817e4Smiod
1480*3d8817e4Smiod #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1481*3d8817e4Smiod setlocale (LC_MESSAGES, "");
1482*3d8817e4Smiod #endif
1483*3d8817e4Smiod #if defined (HAVE_SETLOCALE)
1484*3d8817e4Smiod setlocale (LC_CTYPE, "");
1485*3d8817e4Smiod setlocale (LC_COLLATE, "");
1486*3d8817e4Smiod #endif
1487*3d8817e4Smiod bindtextdomain (PACKAGE, LOCALEDIR);
1488*3d8817e4Smiod textdomain (PACKAGE);
1489*3d8817e4Smiod
1490*3d8817e4Smiod program_name = *argv;
1491*3d8817e4Smiod xmalloc_set_program_name (program_name);
1492*3d8817e4Smiod
1493*3d8817e4Smiod START_PROGRESS (program_name, 0);
1494*3d8817e4Smiod
1495*3d8817e4Smiod expandargv (&argc, &argv);
1496*3d8817e4Smiod
1497*3d8817e4Smiod bfd_init ();
1498*3d8817e4Smiod set_default_bfd_target ();
1499*3d8817e4Smiod
1500*3d8817e4Smiod while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
1501*3d8817e4Smiod long_options, (int *) 0)) != EOF)
1502*3d8817e4Smiod {
1503*3d8817e4Smiod switch (c)
1504*3d8817e4Smiod {
1505*3d8817e4Smiod case 'a':
1506*3d8817e4Smiod print_debug_syms = 1;
1507*3d8817e4Smiod break;
1508*3d8817e4Smiod case 'A':
1509*3d8817e4Smiod case 'o':
1510*3d8817e4Smiod filename_per_symbol = 1;
1511*3d8817e4Smiod break;
1512*3d8817e4Smiod case 'B': /* For MIPS compatibility. */
1513*3d8817e4Smiod set_output_format ("bsd");
1514*3d8817e4Smiod break;
1515*3d8817e4Smiod case 'C':
1516*3d8817e4Smiod do_demangle = 1;
1517*3d8817e4Smiod if (optarg != NULL)
1518*3d8817e4Smiod {
1519*3d8817e4Smiod enum demangling_styles style;
1520*3d8817e4Smiod
1521*3d8817e4Smiod style = cplus_demangle_name_to_style (optarg);
1522*3d8817e4Smiod if (style == unknown_demangling)
1523*3d8817e4Smiod fatal (_("unknown demangling style `%s'"),
1524*3d8817e4Smiod optarg);
1525*3d8817e4Smiod
1526*3d8817e4Smiod cplus_demangle_set_style (style);
1527*3d8817e4Smiod }
1528*3d8817e4Smiod break;
1529*3d8817e4Smiod case 'D':
1530*3d8817e4Smiod dynamic = 1;
1531*3d8817e4Smiod break;
1532*3d8817e4Smiod case 'e':
1533*3d8817e4Smiod /* Ignored for HP/UX compatibility. */
1534*3d8817e4Smiod break;
1535*3d8817e4Smiod case 'f':
1536*3d8817e4Smiod set_output_format (optarg);
1537*3d8817e4Smiod break;
1538*3d8817e4Smiod case 'g':
1539*3d8817e4Smiod external_only = 1;
1540*3d8817e4Smiod break;
1541*3d8817e4Smiod case 'H':
1542*3d8817e4Smiod case 'h':
1543*3d8817e4Smiod usage (stdout, 0);
1544*3d8817e4Smiod case 'l':
1545*3d8817e4Smiod line_numbers = 1;
1546*3d8817e4Smiod break;
1547*3d8817e4Smiod case 'n':
1548*3d8817e4Smiod case 'v':
1549*3d8817e4Smiod sort_numerically = 1;
1550*3d8817e4Smiod break;
1551*3d8817e4Smiod case 'p':
1552*3d8817e4Smiod no_sort = 1;
1553*3d8817e4Smiod break;
1554*3d8817e4Smiod case 'P':
1555*3d8817e4Smiod set_output_format ("posix");
1556*3d8817e4Smiod break;
1557*3d8817e4Smiod case 'r':
1558*3d8817e4Smiod reverse_sort = 1;
1559*3d8817e4Smiod break;
1560*3d8817e4Smiod case 's':
1561*3d8817e4Smiod print_armap = 1;
1562*3d8817e4Smiod break;
1563*3d8817e4Smiod case 'S':
1564*3d8817e4Smiod print_size = 1;
1565*3d8817e4Smiod break;
1566*3d8817e4Smiod case 't':
1567*3d8817e4Smiod set_print_radix (optarg);
1568*3d8817e4Smiod break;
1569*3d8817e4Smiod case 'u':
1570*3d8817e4Smiod undefined_only = 1;
1571*3d8817e4Smiod break;
1572*3d8817e4Smiod case 'V':
1573*3d8817e4Smiod show_version = 1;
1574*3d8817e4Smiod break;
1575*3d8817e4Smiod case 'X':
1576*3d8817e4Smiod /* Ignored for (partial) AIX compatibility. On AIX, the
1577*3d8817e4Smiod argument has values 32, 64, or 32_64, and specifies that
1578*3d8817e4Smiod only 32-bit, only 64-bit, or both kinds of objects should
1579*3d8817e4Smiod be examined. The default is 32. So plain AIX nm on a
1580*3d8817e4Smiod library archive with both kinds of objects will ignore
1581*3d8817e4Smiod the 64-bit ones. For GNU nm, the default is and always
1582*3d8817e4Smiod has been -X 32_64, and other options are not supported. */
1583*3d8817e4Smiod if (strcmp (optarg, "32_64") != 0)
1584*3d8817e4Smiod fatal (_("Only -X 32_64 is supported"));
1585*3d8817e4Smiod break;
1586*3d8817e4Smiod
1587*3d8817e4Smiod case OPTION_TARGET: /* --target */
1588*3d8817e4Smiod target = optarg;
1589*3d8817e4Smiod break;
1590*3d8817e4Smiod
1591*3d8817e4Smiod case 0: /* A long option that just sets a flag. */
1592*3d8817e4Smiod break;
1593*3d8817e4Smiod
1594*3d8817e4Smiod default:
1595*3d8817e4Smiod usage (stderr, 1);
1596*3d8817e4Smiod }
1597*3d8817e4Smiod }
1598*3d8817e4Smiod
1599*3d8817e4Smiod if (show_version)
1600*3d8817e4Smiod print_version ("nm");
1601*3d8817e4Smiod
1602*3d8817e4Smiod if (sort_by_size && undefined_only)
1603*3d8817e4Smiod {
1604*3d8817e4Smiod non_fatal (_("Using the --size-sort and --undefined-only options together"));
1605*3d8817e4Smiod non_fatal (_("will produce no output, since undefined symbols have no size."));
1606*3d8817e4Smiod return 0;
1607*3d8817e4Smiod }
1608*3d8817e4Smiod
1609*3d8817e4Smiod /* OK, all options now parsed. If no filename specified, do a.out. */
1610*3d8817e4Smiod if (optind == argc)
1611*3d8817e4Smiod return !display_file ("a.out");
1612*3d8817e4Smiod
1613*3d8817e4Smiod retval = 0;
1614*3d8817e4Smiod
1615*3d8817e4Smiod if (argc - optind > 1)
1616*3d8817e4Smiod filename_per_file = 1;
1617*3d8817e4Smiod
1618*3d8817e4Smiod /* We were given several filenames to do. */
1619*3d8817e4Smiod while (optind < argc)
1620*3d8817e4Smiod {
1621*3d8817e4Smiod PROGRESS (1);
1622*3d8817e4Smiod if (!display_file (argv[optind++]))
1623*3d8817e4Smiod retval++;
1624*3d8817e4Smiod }
1625*3d8817e4Smiod
1626*3d8817e4Smiod END_PROGRESS (program_name);
1627*3d8817e4Smiod
1628*3d8817e4Smiod #ifdef HAVE_SBRK
1629*3d8817e4Smiod if (show_stats)
1630*3d8817e4Smiod {
1631*3d8817e4Smiod char *lim = (char *) sbrk (0);
1632*3d8817e4Smiod
1633*3d8817e4Smiod non_fatal (_("data size %ld"), (long) (lim - (char *) &environ));
1634*3d8817e4Smiod }
1635*3d8817e4Smiod #endif
1636*3d8817e4Smiod
1637*3d8817e4Smiod exit (retval);
1638*3d8817e4Smiod return retval;
1639*3d8817e4Smiod }
1640