175fd0b74Schristos /* nm.c -- Describe symbol table of a rel file.
2*e992f068Schristos Copyright (C) 1991-2022 Free Software Foundation, Inc.
375fd0b74Schristos
475fd0b74Schristos This file is part of GNU Binutils.
575fd0b74Schristos
675fd0b74Schristos This program is free software; you can redistribute it and/or modify
775fd0b74Schristos it under the terms of the GNU General Public License as published by
875fd0b74Schristos the Free Software Foundation; either version 3 of the License, or
975fd0b74Schristos (at your option) any later version.
1075fd0b74Schristos
1175fd0b74Schristos This program is distributed in the hope that it will be useful,
1275fd0b74Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1375fd0b74Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1475fd0b74Schristos GNU General Public License for more details.
1575fd0b74Schristos
1675fd0b74Schristos You should have received a copy of the GNU General Public License
1775fd0b74Schristos along with this program; if not, write to the Free Software
1875fd0b74Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
1975fd0b74Schristos 02110-1301, USA. */
2075fd0b74Schristos
2175fd0b74Schristos #include "sysdep.h"
2275fd0b74Schristos #include "bfd.h"
2375fd0b74Schristos #include "progress.h"
2475fd0b74Schristos #include "getopt.h"
2575fd0b74Schristos #include "aout/stab_gnu.h"
2675fd0b74Schristos #include "aout/ranlib.h"
2775fd0b74Schristos #include "demangle.h"
2875fd0b74Schristos #include "libiberty.h"
2975fd0b74Schristos #include "elf-bfd.h"
3075fd0b74Schristos #include "elf/common.h"
3175fd0b74Schristos #define DO_NOT_DEFINE_AOUTHDR
3275fd0b74Schristos #define DO_NOT_DEFINE_FILHDR
3375fd0b74Schristos #define DO_NOT_DEFINE_LINENO
3475fd0b74Schristos #define DO_NOT_DEFINE_SCNHDR
3575fd0b74Schristos #include "coff/external.h"
3675fd0b74Schristos #include "coff/internal.h"
3775fd0b74Schristos #include "libcoff.h"
3875fd0b74Schristos #include "bucomm.h"
39*e992f068Schristos #include "demanguse.h"
40ede78133Schristos #include "plugin-api.h"
4175fd0b74Schristos #include "plugin.h"
42*e992f068Schristos #include "safe-ctype.h"
43*e992f068Schristos
44*e992f068Schristos #ifndef streq
45*e992f068Schristos #define streq(a,b) (strcmp ((a),(b)) == 0)
46*e992f068Schristos #endif
4775fd0b74Schristos
4875fd0b74Schristos /* When sorting by size, we use this structure to hold the size and a
4975fd0b74Schristos pointer to the minisymbol. */
5075fd0b74Schristos
5175fd0b74Schristos struct size_sym
5275fd0b74Schristos {
5375fd0b74Schristos const void *minisym;
5475fd0b74Schristos bfd_vma size;
5575fd0b74Schristos };
5675fd0b74Schristos
5775fd0b74Schristos /* When fetching relocs, we use this structure to pass information to
5875fd0b74Schristos get_relocs. */
5975fd0b74Schristos
6075fd0b74Schristos struct get_relocs_info
6175fd0b74Schristos {
6275fd0b74Schristos asection **secs;
6375fd0b74Schristos arelent ***relocs;
6475fd0b74Schristos long *relcount;
6575fd0b74Schristos asymbol **syms;
6675fd0b74Schristos };
6775fd0b74Schristos
6875fd0b74Schristos struct extended_symbol_info
6975fd0b74Schristos {
7075fd0b74Schristos symbol_info *sinfo;
7175fd0b74Schristos bfd_vma ssize;
7275fd0b74Schristos elf_symbol_type *elfinfo;
7375fd0b74Schristos coff_symbol_type *coffinfo;
7475fd0b74Schristos /* FIXME: We should add more fields for Type, Line, Section. */
7575fd0b74Schristos };
7675fd0b74Schristos #define SYM_VALUE(sym) (sym->sinfo->value)
7775fd0b74Schristos #define SYM_TYPE(sym) (sym->sinfo->type)
7875fd0b74Schristos #define SYM_STAB_NAME(sym) (sym->sinfo->stab_name)
7975fd0b74Schristos #define SYM_STAB_DESC(sym) (sym->sinfo->stab_desc)
8075fd0b74Schristos #define SYM_STAB_OTHER(sym) (sym->sinfo->stab_other)
8175fd0b74Schristos #define SYM_SIZE(sym) \
8275fd0b74Schristos (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
8375fd0b74Schristos
8475fd0b74Schristos /* The output formatting functions. */
85012573ebSchristos static void print_object_filename_bsd (const char *);
86012573ebSchristos static void print_object_filename_sysv (const char *);
87012573ebSchristos static void print_object_filename_posix (const char *);
88*e992f068Schristos static void do_not_print_object_filename (const char *);
89*e992f068Schristos
90012573ebSchristos static void print_archive_filename_bsd (const char *);
91012573ebSchristos static void print_archive_filename_sysv (const char *);
92012573ebSchristos static void print_archive_filename_posix (const char *);
93*e992f068Schristos static void do_not_print_archive_filename (const char *);
94*e992f068Schristos
95012573ebSchristos static void print_archive_member_bsd (const char *, const char *);
96012573ebSchristos static void print_archive_member_sysv (const char *, const char *);
97012573ebSchristos static void print_archive_member_posix (const char *, const char *);
98*e992f068Schristos static void do_not_print_archive_member (const char *, const char *);
99*e992f068Schristos
10075fd0b74Schristos static void print_symbol_filename_bsd (bfd *, bfd *);
10175fd0b74Schristos static void print_symbol_filename_sysv (bfd *, bfd *);
10275fd0b74Schristos static void print_symbol_filename_posix (bfd *, bfd *);
103*e992f068Schristos static void do_not_print_symbol_filename (bfd *, bfd *);
104*e992f068Schristos
10575fd0b74Schristos static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
10675fd0b74Schristos static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
10775fd0b74Schristos static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
108*e992f068Schristos static void just_print_symbol_name (struct extended_symbol_info *, bfd *);
109*e992f068Schristos
110*e992f068Schristos static void print_value (bfd *, bfd_vma);
11175fd0b74Schristos
11275fd0b74Schristos /* Support for different output formats. */
11375fd0b74Schristos struct output_fns
11475fd0b74Schristos {
11575fd0b74Schristos /* Print the name of an object file given on the command line. */
116012573ebSchristos void (*print_object_filename) (const char *);
11775fd0b74Schristos
11875fd0b74Schristos /* Print the name of an archive file given on the command line. */
119012573ebSchristos void (*print_archive_filename) (const char *);
12075fd0b74Schristos
12175fd0b74Schristos /* Print the name of an archive member file. */
122012573ebSchristos void (*print_archive_member) (const char *, const char *);
12375fd0b74Schristos
12475fd0b74Schristos /* Print the name of the file (and archive, if there is one)
12575fd0b74Schristos containing a symbol. */
12675fd0b74Schristos void (*print_symbol_filename) (bfd *, bfd *);
12775fd0b74Schristos
12875fd0b74Schristos /* Print a line of information about a symbol. */
12975fd0b74Schristos void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
13075fd0b74Schristos };
13175fd0b74Schristos
132*e992f068Schristos /* Indices in `formats'. */
133*e992f068Schristos enum formats
134*e992f068Schristos {
135*e992f068Schristos FORMAT_BSD = 0,
136*e992f068Schristos FORMAT_SYSV,
137*e992f068Schristos FORMAT_POSIX,
138*e992f068Schristos FORMAT_JUST_SYMBOLS,
139*e992f068Schristos FORMAT_MAX
140*e992f068Schristos };
141*e992f068Schristos
142*e992f068Schristos #define FORMAT_DEFAULT FORMAT_BSD
143*e992f068Schristos
144*e992f068Schristos static struct output_fns formats[FORMAT_MAX] =
14575fd0b74Schristos {
14675fd0b74Schristos {print_object_filename_bsd,
14775fd0b74Schristos print_archive_filename_bsd,
14875fd0b74Schristos print_archive_member_bsd,
14975fd0b74Schristos print_symbol_filename_bsd,
15075fd0b74Schristos print_symbol_info_bsd},
15175fd0b74Schristos {print_object_filename_sysv,
15275fd0b74Schristos print_archive_filename_sysv,
15375fd0b74Schristos print_archive_member_sysv,
15475fd0b74Schristos print_symbol_filename_sysv,
15575fd0b74Schristos print_symbol_info_sysv},
15675fd0b74Schristos {print_object_filename_posix,
15775fd0b74Schristos print_archive_filename_posix,
15875fd0b74Schristos print_archive_member_posix,
15975fd0b74Schristos print_symbol_filename_posix,
160*e992f068Schristos print_symbol_info_posix},
161*e992f068Schristos {do_not_print_object_filename,
162*e992f068Schristos do_not_print_archive_filename,
163*e992f068Schristos do_not_print_archive_member,
164*e992f068Schristos do_not_print_symbol_filename,
165*e992f068Schristos just_print_symbol_name}
16675fd0b74Schristos };
16775fd0b74Schristos
16875fd0b74Schristos
16975fd0b74Schristos /* The output format to use. */
17075fd0b74Schristos static struct output_fns *format = &formats[FORMAT_DEFAULT];
171012573ebSchristos static unsigned int print_format = FORMAT_DEFAULT;
172012573ebSchristos static const char *print_format_string = NULL;
17375fd0b74Schristos
17475fd0b74Schristos /* Command options. */
17575fd0b74Schristos
17675fd0b74Schristos static int do_demangle = 0; /* Pretty print C++ symbol names. */
17775fd0b74Schristos static int external_only = 0; /* Print external symbols only. */
17875fd0b74Schristos static int defined_only = 0; /* Print defined symbols only. */
179*e992f068Schristos static int non_weak = 0; /* Ignore weak symbols. */
18075fd0b74Schristos static int no_sort = 0; /* Don't sort; print syms in order found. */
18175fd0b74Schristos static int print_debug_syms = 0;/* Print debugger-only symbols too. */
18275fd0b74Schristos static int print_armap = 0; /* Describe __.SYMDEF data in archive files. */
18375fd0b74Schristos static int print_size = 0; /* Print size of defined symbols. */
18475fd0b74Schristos static int reverse_sort = 0; /* Sort in downward(alpha or numeric) order. */
18575fd0b74Schristos static int sort_numerically = 0;/* Sort in numeric rather than alpha order. */
18675fd0b74Schristos static int sort_by_size = 0; /* Sort by size of symbol. */
18775fd0b74Schristos static int undefined_only = 0; /* Print undefined symbols only. */
18875fd0b74Schristos static int dynamic = 0; /* Print dynamic symbols. */
18975fd0b74Schristos static int show_version = 0; /* Show the version number. */
19075fd0b74Schristos static int show_synthetic = 0; /* Display synthesized symbols too. */
19175fd0b74Schristos static int line_numbers = 0; /* Print line numbers for symbols. */
19275fd0b74Schristos static int allow_special_symbols = 0; /* Allow special symbols. */
193*e992f068Schristos static int with_symbol_versions = -1; /* Output symbol version information. */
194*e992f068Schristos static int quiet = 0; /* Suppress "no symbols" diagnostic. */
195*e992f068Schristos
196*e992f068Schristos /* The characters to use for global and local ifunc symbols. */
197*e992f068Schristos #if DEFAULT_F_FOR_IFUNC_SYMBOLS
198*e992f068Schristos static const char * ifunc_type_chars = "Ff";
199*e992f068Schristos #else
200*e992f068Schristos static const char * ifunc_type_chars = NULL;
201*e992f068Schristos #endif
20275fd0b74Schristos
203012573ebSchristos static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
204012573ebSchristos
20575fd0b74Schristos /* When to print the names of files. Not mutually exclusive in SYSV format. */
20675fd0b74Schristos static int filename_per_file = 0; /* Once per file, on its own line. */
20775fd0b74Schristos static int filename_per_symbol = 0; /* Once per symbol, at start of line. */
20875fd0b74Schristos
20975fd0b74Schristos static int print_width = 0;
21075fd0b74Schristos static int print_radix = 16;
21175fd0b74Schristos /* Print formats for printing stab info. */
21275fd0b74Schristos static char other_format[] = "%02x";
21375fd0b74Schristos static char desc_format[] = "%04x";
21475fd0b74Schristos
21575fd0b74Schristos static char *target = NULL;
21675fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
21775fd0b74Schristos static const char *plugin_target = "plugin";
21875fd0b74Schristos #else
21975fd0b74Schristos static const char *plugin_target = NULL;
22075fd0b74Schristos #endif
22175fd0b74Schristos
22275fd0b74Schristos /* Used to cache the line numbers for a BFD. */
22375fd0b74Schristos static bfd *lineno_cache_bfd;
22475fd0b74Schristos static bfd *lineno_cache_rel_bfd;
22575fd0b74Schristos
226*e992f068Schristos typedef enum unicode_display_type
227*e992f068Schristos {
228*e992f068Schristos unicode_default = 0,
229*e992f068Schristos unicode_locale,
230*e992f068Schristos unicode_escape,
231*e992f068Schristos unicode_hex,
232*e992f068Schristos unicode_highlight,
233*e992f068Schristos unicode_invalid
234*e992f068Schristos } unicode_display_type;
235*e992f068Schristos
236*e992f068Schristos static unicode_display_type unicode_display = unicode_default;
237*e992f068Schristos
238012573ebSchristos enum long_option_values
239012573ebSchristos {
240012573ebSchristos OPTION_TARGET = 200,
241012573ebSchristos OPTION_PLUGIN,
242012573ebSchristos OPTION_SIZE_SORT,
243012573ebSchristos OPTION_RECURSE_LIMIT,
244*e992f068Schristos OPTION_NO_RECURSE_LIMIT,
245*e992f068Schristos OPTION_IFUNC_CHARS,
246*e992f068Schristos OPTION_UNICODE,
247*e992f068Schristos OPTION_QUIET
248012573ebSchristos };
24975fd0b74Schristos
25075fd0b74Schristos static struct option long_options[] =
25175fd0b74Schristos {
25275fd0b74Schristos {"debug-syms", no_argument, &print_debug_syms, 1},
25375fd0b74Schristos {"demangle", optional_argument, 0, 'C'},
25475fd0b74Schristos {"dynamic", no_argument, &dynamic, 1},
25575fd0b74Schristos {"extern-only", no_argument, &external_only, 1},
25675fd0b74Schristos {"format", required_argument, 0, 'f'},
25775fd0b74Schristos {"help", no_argument, 0, 'h'},
258*e992f068Schristos {"ifunc-chars", required_argument, 0, OPTION_IFUNC_CHARS},
259*e992f068Schristos {"just-symbols", no_argument, 0, 'j'},
26075fd0b74Schristos {"line-numbers", no_argument, 0, 'l'},
26175fd0b74Schristos {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
26275fd0b74Schristos {"no-demangle", no_argument, &do_demangle, 0},
263012573ebSchristos {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
264012573ebSchristos {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
26575fd0b74Schristos {"no-sort", no_argument, 0, 'p'},
26675fd0b74Schristos {"numeric-sort", no_argument, 0, 'n'},
26775fd0b74Schristos {"plugin", required_argument, 0, OPTION_PLUGIN},
26875fd0b74Schristos {"portability", no_argument, 0, 'P'},
26975fd0b74Schristos {"print-armap", no_argument, &print_armap, 1},
27075fd0b74Schristos {"print-file-name", no_argument, 0, 'o'},
27175fd0b74Schristos {"print-size", no_argument, 0, 'S'},
272*e992f068Schristos {"quiet", no_argument, 0, OPTION_QUIET},
27375fd0b74Schristos {"radix", required_argument, 0, 't'},
274012573ebSchristos {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
275012573ebSchristos {"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
27675fd0b74Schristos {"reverse-sort", no_argument, &reverse_sort, 1},
27775fd0b74Schristos {"size-sort", no_argument, 0, OPTION_SIZE_SORT},
27875fd0b74Schristos {"special-syms", no_argument, &allow_special_symbols, 1},
27975fd0b74Schristos {"synthetic", no_argument, &show_synthetic, 1},
28075fd0b74Schristos {"target", required_argument, 0, OPTION_TARGET},
281*e992f068Schristos {"defined-only", no_argument, 0, 'U'},
282*e992f068Schristos {"undefined-only", no_argument, 0, 'u'},
283*e992f068Schristos {"unicode", required_argument, NULL, OPTION_UNICODE},
28475fd0b74Schristos {"version", no_argument, &show_version, 1},
285*e992f068Schristos {"no-weak", no_argument, 0, 'W'},
286ede78133Schristos {"with-symbol-versions", no_argument, &with_symbol_versions, 1},
287*e992f068Schristos {"without-symbol-versions", no_argument, &with_symbol_versions, 0},
28875fd0b74Schristos {0, no_argument, 0, 0}
28975fd0b74Schristos };
29075fd0b74Schristos
29175fd0b74Schristos /* Some error-reporting functions. */
29275fd0b74Schristos
293ede78133Schristos ATTRIBUTE_NORETURN static void
usage(FILE * stream,int status)29475fd0b74Schristos usage (FILE *stream, int status)
29575fd0b74Schristos {
29675fd0b74Schristos fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
29775fd0b74Schristos fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
298*e992f068Schristos fprintf (stream, _(" The options are:\n"));
299*e992f068Schristos fprintf (stream, _("\
300*e992f068Schristos -a, --debug-syms Display debugger-only symbols\n"));
301*e992f068Schristos fprintf (stream, _("\
302*e992f068Schristos -A, --print-file-name Print name of the input file before every symbol\n"));
303*e992f068Schristos fprintf (stream, _("\
304*e992f068Schristos -B Same as --format=bsd\n"));
305*e992f068Schristos fprintf (stream, _("\
306*e992f068Schristos -C, --demangle[=STYLE] Decode mangled/processed symbol names\n"));
307*e992f068Schristos display_demangler_styles (stream, _("\
308*e992f068Schristos STYLE can be "));
309*e992f068Schristos fprintf (stream, _("\
310*e992f068Schristos --no-demangle Do not demangle low-level symbol names\n"));
311*e992f068Schristos fprintf (stream, _("\
312*e992f068Schristos --recurse-limit Enable a demangling recursion limit. (default)\n"));
313*e992f068Schristos fprintf (stream, _("\
314*e992f068Schristos --no-recurse-limit Disable a demangling recursion limit.\n"));
315*e992f068Schristos fprintf (stream, _("\
316*e992f068Schristos -D, --dynamic Display dynamic symbols instead of normal symbols\n"));
317*e992f068Schristos fprintf (stream, _("\
318*e992f068Schristos -e (ignored)\n"));
319*e992f068Schristos fprintf (stream, _("\
32075fd0b74Schristos -f, --format=FORMAT Use the output format FORMAT. FORMAT can be `bsd',\n\
321*e992f068Schristos `sysv', `posix' or 'just-symbols'.\n\
322*e992f068Schristos The default is `bsd'\n"));
323*e992f068Schristos fprintf (stream, _("\
324*e992f068Schristos -g, --extern-only Display only external symbols\n"));
325*e992f068Schristos fprintf (stream, _("\
326*e992f068Schristos --ifunc-chars=CHARS Characters to use when displaying ifunc symbols\n"));
327*e992f068Schristos fprintf (stream, _("\
328*e992f068Schristos -j, --just-symbols Same as --format=just-symbols\n"));
329*e992f068Schristos fprintf (stream, _("\
33075fd0b74Schristos -l, --line-numbers Use debugging information to find a filename and\n\
331*e992f068Schristos line number for each symbol\n"));
332*e992f068Schristos fprintf (stream, _("\
333*e992f068Schristos -n, --numeric-sort Sort symbols numerically by address\n"));
334*e992f068Schristos fprintf (stream, _("\
335*e992f068Schristos -o Same as -A\n"));
336*e992f068Schristos fprintf (stream, _("\
337*e992f068Schristos -p, --no-sort Do not sort the symbols\n"));
338*e992f068Schristos fprintf (stream, _("\
339*e992f068Schristos -P, --portability Same as --format=posix\n"));
340*e992f068Schristos fprintf (stream, _("\
34175fd0b74Schristos -r, --reverse-sort Reverse the sense of the sort\n"));
34275fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
34375fd0b74Schristos fprintf (stream, _("\
34475fd0b74Schristos --plugin NAME Load the specified plugin\n"));
34575fd0b74Schristos #endif
34675fd0b74Schristos fprintf (stream, _("\
347*e992f068Schristos -S, --print-size Print size of defined symbols\n"));
348*e992f068Schristos fprintf (stream, _("\
349*e992f068Schristos -s, --print-armap Include index for symbols from archive members\n"));
350*e992f068Schristos fprintf (stream, _("\
351*e992f068Schristos --quiet Suppress \"no symbols\" diagnostic\n"));
352*e992f068Schristos fprintf (stream, _("\
353*e992f068Schristos --size-sort Sort symbols by size\n"));
354*e992f068Schristos fprintf (stream, _("\
355*e992f068Schristos --special-syms Include special symbols in the output\n"));
356*e992f068Schristos fprintf (stream, _("\
357*e992f068Schristos --synthetic Display synthetic symbols as well\n"));
358*e992f068Schristos fprintf (stream, _("\
359*e992f068Schristos -t, --radix=RADIX Use RADIX for printing symbol values\n"));
360*e992f068Schristos fprintf (stream, _("\
361*e992f068Schristos --target=BFDNAME Specify the target object format as BFDNAME\n"));
362*e992f068Schristos fprintf (stream, _("\
363*e992f068Schristos -u, --undefined-only Display only undefined symbols\n"));
364*e992f068Schristos fprintf (stream, _("\
365*e992f068Schristos -U, --defined-only Display only defined symbols\n"));
366*e992f068Schristos fprintf (stream, _("\
367*e992f068Schristos --unicode={default|show|invalid|hex|escape|highlight}\n\
368*e992f068Schristos Specify how to treat UTF-8 encoded unicode characters\n"));
369*e992f068Schristos fprintf (stream, _("\
370*e992f068Schristos -W, --no-weak Ignore weak symbols\n"));
371*e992f068Schristos fprintf (stream, _("\
372*e992f068Schristos --with-symbol-versions Display version strings after symbol names\n"));
373*e992f068Schristos fprintf (stream, _("\
374*e992f068Schristos -X 32_64 (ignored)\n"));
375*e992f068Schristos fprintf (stream, _("\
376*e992f068Schristos @FILE Read options from FILE\n"));
377*e992f068Schristos fprintf (stream, _("\
378*e992f068Schristos -h, --help Display this information\n"));
379*e992f068Schristos fprintf (stream, _("\
380*e992f068Schristos -V, --version Display this program's version number\n"));
381*e992f068Schristos
38275fd0b74Schristos list_supported_targets (program_name, stream);
38375fd0b74Schristos if (REPORT_BUGS_TO[0] && status == 0)
38475fd0b74Schristos fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
38575fd0b74Schristos exit (status);
38675fd0b74Schristos }
38775fd0b74Schristos
38875fd0b74Schristos /* Set the radix for the symbol value and size according to RADIX. */
38975fd0b74Schristos
39075fd0b74Schristos static void
set_print_radix(char * radix)39175fd0b74Schristos set_print_radix (char *radix)
39275fd0b74Schristos {
39375fd0b74Schristos switch (*radix)
39475fd0b74Schristos {
395012573ebSchristos case 'x': print_radix = 16; break;
396012573ebSchristos case 'd': print_radix = 10; break;
397012573ebSchristos case 'o': print_radix = 8; break;
398012573ebSchristos
39975fd0b74Schristos default:
40075fd0b74Schristos fatal (_("%s: invalid radix"), radix);
40175fd0b74Schristos }
402012573ebSchristos
403012573ebSchristos other_format[3] = desc_format[3] = *radix;
40475fd0b74Schristos }
40575fd0b74Schristos
40675fd0b74Schristos static void
set_output_format(char * f)40775fd0b74Schristos set_output_format (char *f)
40875fd0b74Schristos {
40975fd0b74Schristos int i;
41075fd0b74Schristos
41175fd0b74Schristos switch (*f)
41275fd0b74Schristos {
41375fd0b74Schristos case 'b':
41475fd0b74Schristos case 'B':
41575fd0b74Schristos i = FORMAT_BSD;
41675fd0b74Schristos break;
41775fd0b74Schristos case 'p':
41875fd0b74Schristos case 'P':
41975fd0b74Schristos i = FORMAT_POSIX;
42075fd0b74Schristos break;
42175fd0b74Schristos case 's':
42275fd0b74Schristos case 'S':
42375fd0b74Schristos i = FORMAT_SYSV;
42475fd0b74Schristos break;
425*e992f068Schristos case 'j':
426*e992f068Schristos case 'J':
427*e992f068Schristos i = FORMAT_JUST_SYMBOLS;
428*e992f068Schristos break;
42975fd0b74Schristos default:
43075fd0b74Schristos fatal (_("%s: invalid output format"), f);
43175fd0b74Schristos }
43275fd0b74Schristos format = &formats[i];
433012573ebSchristos print_format = i;
43475fd0b74Schristos }
43575fd0b74Schristos
43675fd0b74Schristos static const char *
get_elf_symbol_type(unsigned int type)43775fd0b74Schristos get_elf_symbol_type (unsigned int type)
43875fd0b74Schristos {
439ede78133Schristos static char *bufp;
440ede78133Schristos int n;
44175fd0b74Schristos
44275fd0b74Schristos switch (type)
44375fd0b74Schristos {
44475fd0b74Schristos case STT_NOTYPE: return "NOTYPE";
44575fd0b74Schristos case STT_OBJECT: return "OBJECT";
44675fd0b74Schristos case STT_FUNC: return "FUNC";
44775fd0b74Schristos case STT_SECTION: return "SECTION";
44875fd0b74Schristos case STT_FILE: return "FILE";
44975fd0b74Schristos case STT_COMMON: return "COMMON";
45075fd0b74Schristos case STT_TLS: return "TLS";
45175fd0b74Schristos }
452ede78133Schristos
453ede78133Schristos free (bufp);
454ede78133Schristos if (type >= STT_LOPROC && type <= STT_HIPROC)
455ede78133Schristos n = asprintf (&bufp, _("<processor specific>: %d"), type);
456ede78133Schristos else if (type >= STT_LOOS && type <= STT_HIOS)
457ede78133Schristos n = asprintf (&bufp, _("<OS specific>: %d"), type);
458ede78133Schristos else
459ede78133Schristos n = asprintf (&bufp, _("<unknown>: %d"), type);
460ede78133Schristos if (n < 0)
461ede78133Schristos fatal ("%s", xstrerror (errno));
462ede78133Schristos return bufp;
46375fd0b74Schristos }
46475fd0b74Schristos
46575fd0b74Schristos static const char *
get_coff_symbol_type(const struct internal_syment * sym)46675fd0b74Schristos get_coff_symbol_type (const struct internal_syment *sym)
46775fd0b74Schristos {
468ede78133Schristos static char *bufp;
469ede78133Schristos int n;
47075fd0b74Schristos
47175fd0b74Schristos switch (sym->n_sclass)
47275fd0b74Schristos {
47375fd0b74Schristos case C_BLOCK: return "Block";
47475fd0b74Schristos case C_FILE: return "File";
47575fd0b74Schristos case C_LINE: return "Line";
47675fd0b74Schristos }
47775fd0b74Schristos
47875fd0b74Schristos if (!sym->n_type)
47975fd0b74Schristos return "None";
48075fd0b74Schristos
48175fd0b74Schristos switch (DTYPE(sym->n_type))
48275fd0b74Schristos {
48375fd0b74Schristos case DT_FCN: return "Function";
48475fd0b74Schristos case DT_PTR: return "Pointer";
48575fd0b74Schristos case DT_ARY: return "Array";
48675fd0b74Schristos }
48775fd0b74Schristos
488ede78133Schristos free (bufp);
489ede78133Schristos n = asprintf (&bufp, _("<unknown>: %d/%d"), sym->n_sclass, sym->n_type);
490ede78133Schristos if (n < 0)
491ede78133Schristos fatal ("%s", xstrerror (errno));
492ede78133Schristos return bufp;
49375fd0b74Schristos }
49475fd0b74Schristos
495*e992f068Schristos /* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
496*e992f068Schristos The conversion format is controlled by the unicode_display variable.
497*e992f068Schristos Returns the number of characters added to OUT.
498*e992f068Schristos Returns the number of bytes consumed from IN in CONSUMED.
499*e992f068Schristos Always consumes at least one byte and displays at least one character. */
500*e992f068Schristos
501*e992f068Schristos static unsigned int
display_utf8(const unsigned char * in,char * out,unsigned int * consumed)502*e992f068Schristos display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
503*e992f068Schristos {
504*e992f068Schristos char * orig_out = out;
505*e992f068Schristos unsigned int nchars = 0;
506*e992f068Schristos unsigned int j;
507*e992f068Schristos
508*e992f068Schristos if (unicode_display == unicode_default)
509*e992f068Schristos goto invalid;
510*e992f068Schristos
511*e992f068Schristos if (in[0] < 0xc0)
512*e992f068Schristos goto invalid;
513*e992f068Schristos
514*e992f068Schristos if ((in[1] & 0xc0) != 0x80)
515*e992f068Schristos goto invalid;
516*e992f068Schristos
517*e992f068Schristos if ((in[0] & 0x20) == 0)
518*e992f068Schristos {
519*e992f068Schristos nchars = 2;
520*e992f068Schristos goto valid;
521*e992f068Schristos }
522*e992f068Schristos
523*e992f068Schristos if ((in[2] & 0xc0) != 0x80)
524*e992f068Schristos goto invalid;
525*e992f068Schristos
526*e992f068Schristos if ((in[0] & 0x10) == 0)
527*e992f068Schristos {
528*e992f068Schristos nchars = 3;
529*e992f068Schristos goto valid;
530*e992f068Schristos }
531*e992f068Schristos
532*e992f068Schristos if ((in[3] & 0xc0) != 0x80)
533*e992f068Schristos goto invalid;
534*e992f068Schristos
535*e992f068Schristos nchars = 4;
536*e992f068Schristos
537*e992f068Schristos valid:
538*e992f068Schristos switch (unicode_display)
539*e992f068Schristos {
540*e992f068Schristos case unicode_locale:
541*e992f068Schristos /* Copy the bytes into the output buffer as is. */
542*e992f068Schristos memcpy (out, in, nchars);
543*e992f068Schristos out += nchars;
544*e992f068Schristos break;
545*e992f068Schristos
546*e992f068Schristos case unicode_invalid:
547*e992f068Schristos case unicode_hex:
548*e992f068Schristos out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
549*e992f068Schristos out += sprintf (out, "0x");
550*e992f068Schristos for (j = 0; j < nchars; j++)
551*e992f068Schristos out += sprintf (out, "%02x", in [j]);
552*e992f068Schristos out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
553*e992f068Schristos break;
554*e992f068Schristos
555*e992f068Schristos case unicode_highlight:
556*e992f068Schristos if (isatty (1))
557*e992f068Schristos out += sprintf (out, "\x1B[31;47m"); /* Red. */
558*e992f068Schristos /* Fall through. */
559*e992f068Schristos case unicode_escape:
560*e992f068Schristos switch (nchars)
561*e992f068Schristos {
562*e992f068Schristos case 2:
563*e992f068Schristos out += sprintf (out, "\\u%02x%02x",
564*e992f068Schristos ((in[0] & 0x1c) >> 2),
565*e992f068Schristos ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
566*e992f068Schristos break;
567*e992f068Schristos
568*e992f068Schristos case 3:
569*e992f068Schristos out += sprintf (out, "\\u%02x%02x",
570*e992f068Schristos ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
571*e992f068Schristos ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
572*e992f068Schristos break;
573*e992f068Schristos
574*e992f068Schristos case 4:
575*e992f068Schristos out += sprintf (out, "\\u%02x%02x%02x",
576*e992f068Schristos ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
577*e992f068Schristos ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
578*e992f068Schristos ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
579*e992f068Schristos break;
580*e992f068Schristos default:
581*e992f068Schristos /* URG. */
582*e992f068Schristos break;
583*e992f068Schristos }
584*e992f068Schristos
585*e992f068Schristos if (unicode_display == unicode_highlight && isatty (1))
586*e992f068Schristos out += sprintf (out, "\033[0m"); /* Default colour. */
587*e992f068Schristos break;
588*e992f068Schristos
589*e992f068Schristos default:
590*e992f068Schristos /* URG */
591*e992f068Schristos break;
592*e992f068Schristos }
593*e992f068Schristos
594*e992f068Schristos * consumed = nchars;
595*e992f068Schristos return out - orig_out;
596*e992f068Schristos
597*e992f068Schristos invalid:
598*e992f068Schristos /* Not a valid UTF-8 sequence. */
599*e992f068Schristos *out = *in;
600*e992f068Schristos * consumed = 1;
601*e992f068Schristos return 1;
602*e992f068Schristos }
603*e992f068Schristos
604*e992f068Schristos /* Convert any UTF-8 encoded characters in NAME into the form specified by
605*e992f068Schristos unicode_display. Also converts control characters. Returns a static
606*e992f068Schristos buffer if conversion was necessary.
607*e992f068Schristos Code stolen from objdump.c:sanitize_string(). */
608*e992f068Schristos
609*e992f068Schristos static const char *
convert_utf8(const char * in)610*e992f068Schristos convert_utf8 (const char * in)
611*e992f068Schristos {
612*e992f068Schristos static char * buffer = NULL;
613*e992f068Schristos static size_t buffer_len = 0;
614*e992f068Schristos const char * original = in;
615*e992f068Schristos char * out;
616*e992f068Schristos
617*e992f068Schristos /* Paranoia. */
618*e992f068Schristos if (in == NULL)
619*e992f068Schristos return "";
620*e992f068Schristos
621*e992f068Schristos /* See if any conversion is necessary.
622*e992f068Schristos In the majority of cases it will not be needed. */
623*e992f068Schristos do
624*e992f068Schristos {
625*e992f068Schristos unsigned char c = *in++;
626*e992f068Schristos
627*e992f068Schristos if (c == 0)
628*e992f068Schristos return original;
629*e992f068Schristos
630*e992f068Schristos if (ISCNTRL (c))
631*e992f068Schristos break;
632*e992f068Schristos
633*e992f068Schristos if (unicode_display != unicode_default && c >= 0xc0)
634*e992f068Schristos break;
635*e992f068Schristos }
636*e992f068Schristos while (1);
637*e992f068Schristos
638*e992f068Schristos /* Copy the input, translating as needed. */
639*e992f068Schristos in = original;
640*e992f068Schristos if (buffer_len < (strlen (in) * 9))
641*e992f068Schristos {
642*e992f068Schristos free ((void *) buffer);
643*e992f068Schristos buffer_len = strlen (in) * 9;
644*e992f068Schristos buffer = xmalloc (buffer_len + 1);
645*e992f068Schristos }
646*e992f068Schristos
647*e992f068Schristos out = buffer;
648*e992f068Schristos do
649*e992f068Schristos {
650*e992f068Schristos unsigned char c = *in++;
651*e992f068Schristos
652*e992f068Schristos if (c == 0)
653*e992f068Schristos break;
654*e992f068Schristos
655*e992f068Schristos if (ISCNTRL (c))
656*e992f068Schristos {
657*e992f068Schristos *out++ = '^';
658*e992f068Schristos *out++ = c + 0x40;
659*e992f068Schristos }
660*e992f068Schristos else if (unicode_display != unicode_default && c >= 0xc0)
661*e992f068Schristos {
662*e992f068Schristos unsigned int num_consumed;
663*e992f068Schristos
664*e992f068Schristos out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
665*e992f068Schristos in += num_consumed - 1;
666*e992f068Schristos }
667*e992f068Schristos else
668*e992f068Schristos *out++ = c;
669*e992f068Schristos }
670*e992f068Schristos while (1);
671*e992f068Schristos
672*e992f068Schristos *out = 0;
673*e992f068Schristos return buffer;
674*e992f068Schristos }
675*e992f068Schristos
67675fd0b74Schristos /* Print symbol name NAME, read from ABFD, with printf format FORM,
67775fd0b74Schristos demangling it if requested. */
67875fd0b74Schristos
67975fd0b74Schristos static void
print_symname(const char * form,struct extended_symbol_info * info,const char * name,bfd * abfd)680*e992f068Schristos print_symname (const char *form, struct extended_symbol_info *info,
681*e992f068Schristos const char *name, bfd *abfd)
68275fd0b74Schristos {
683*e992f068Schristos char *alloc = NULL;
684*e992f068Schristos char *atver = NULL;
685*e992f068Schristos
686*e992f068Schristos if (name == NULL)
687*e992f068Schristos name = info->sinfo->name;
688*e992f068Schristos
689*e992f068Schristos if (!with_symbol_versions
690*e992f068Schristos && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
691*e992f068Schristos {
692*e992f068Schristos atver = strchr (name, '@');
693*e992f068Schristos if (atver)
694*e992f068Schristos *atver = 0;
695*e992f068Schristos }
696*e992f068Schristos
69775fd0b74Schristos if (do_demangle && *name)
69875fd0b74Schristos {
699*e992f068Schristos alloc = bfd_demangle (abfd, name, demangle_flags);
700*e992f068Schristos if (alloc != NULL)
701*e992f068Schristos name = alloc;
702*e992f068Schristos }
70375fd0b74Schristos
704*e992f068Schristos if (unicode_display != unicode_default)
70575fd0b74Schristos {
706*e992f068Schristos name = convert_utf8 (name);
70775fd0b74Schristos }
70875fd0b74Schristos
709*e992f068Schristos if (info != NULL && info->elfinfo && with_symbol_versions)
710*e992f068Schristos {
711*e992f068Schristos const char *version_string;
712*e992f068Schristos bool hidden;
713*e992f068Schristos
714*e992f068Schristos version_string
715*e992f068Schristos = bfd_get_symbol_version_string (abfd, &info->elfinfo->symbol,
716*e992f068Schristos false, &hidden);
717*e992f068Schristos if (version_string && version_string[0])
718*e992f068Schristos {
719*e992f068Schristos const char *at = "@@";
720*e992f068Schristos if (hidden || bfd_is_und_section (info->elfinfo->symbol.section))
721*e992f068Schristos at = "@";
722*e992f068Schristos alloc = reconcat (alloc, name, at, version_string, NULL);
723*e992f068Schristos if (alloc != NULL)
724*e992f068Schristos name = alloc;
725*e992f068Schristos }
726*e992f068Schristos }
72775fd0b74Schristos printf (form, name);
728*e992f068Schristos if (atver)
729*e992f068Schristos *atver = '@';
730*e992f068Schristos free (alloc);
73175fd0b74Schristos }
73275fd0b74Schristos
73375fd0b74Schristos static void
print_symdef_entry(bfd * abfd)73475fd0b74Schristos print_symdef_entry (bfd *abfd)
73575fd0b74Schristos {
73675fd0b74Schristos symindex idx = BFD_NO_MORE_SYMBOLS;
73775fd0b74Schristos carsym *thesym;
738*e992f068Schristos bool everprinted = false;
73975fd0b74Schristos
74075fd0b74Schristos for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
74175fd0b74Schristos idx != BFD_NO_MORE_SYMBOLS;
74275fd0b74Schristos idx = bfd_get_next_mapent (abfd, idx, &thesym))
74375fd0b74Schristos {
74475fd0b74Schristos bfd *elt;
74575fd0b74Schristos if (!everprinted)
74675fd0b74Schristos {
74775fd0b74Schristos printf (_("\nArchive index:\n"));
748*e992f068Schristos everprinted = true;
74975fd0b74Schristos }
75075fd0b74Schristos elt = bfd_get_elt_at_index (abfd, idx);
75175fd0b74Schristos if (elt == NULL)
75275fd0b74Schristos bfd_fatal ("bfd_get_elt_at_index");
75375fd0b74Schristos if (thesym->name != (char *) NULL)
75475fd0b74Schristos {
755*e992f068Schristos print_symname ("%s", NULL, thesym->name, abfd);
75675fd0b74Schristos printf (" in %s\n", bfd_get_filename (elt));
75775fd0b74Schristos }
75875fd0b74Schristos }
75975fd0b74Schristos }
76075fd0b74Schristos
761012573ebSchristos
762012573ebSchristos /* True when we can report missing plugin error. */
763*e992f068Schristos bool report_plugin_err = true;
764012573ebSchristos
76575fd0b74Schristos /* Choose which symbol entries to print;
76675fd0b74Schristos compact them downward to get rid of the rest.
76775fd0b74Schristos Return the number of symbols to be printed. */
76875fd0b74Schristos
76975fd0b74Schristos static long
filter_symbols(bfd * abfd,bool is_dynamic,void * minisyms,long symcount,unsigned int size)770*e992f068Schristos filter_symbols (bfd *abfd, bool is_dynamic, void *minisyms,
77175fd0b74Schristos long symcount, unsigned int size)
77275fd0b74Schristos {
77375fd0b74Schristos bfd_byte *from, *fromend, *to;
77475fd0b74Schristos asymbol *store;
77575fd0b74Schristos
77675fd0b74Schristos store = bfd_make_empty_symbol (abfd);
77775fd0b74Schristos if (store == NULL)
77875fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
77975fd0b74Schristos
78075fd0b74Schristos from = (bfd_byte *) minisyms;
78175fd0b74Schristos fromend = from + symcount * size;
78275fd0b74Schristos to = (bfd_byte *) minisyms;
78375fd0b74Schristos
78475fd0b74Schristos for (; from < fromend; from += size)
78575fd0b74Schristos {
78675fd0b74Schristos int keep = 0;
78775fd0b74Schristos asymbol *sym;
78875fd0b74Schristos
78975fd0b74Schristos PROGRESS (1);
79075fd0b74Schristos
79175fd0b74Schristos sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, (const void *) from, store);
79275fd0b74Schristos if (sym == NULL)
79375fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
79475fd0b74Schristos
795*e992f068Schristos if (sym->name != NULL
796*e992f068Schristos && sym->name[0] == '_'
797ede78133Schristos && sym->name[1] == '_'
798012573ebSchristos && strcmp (sym->name + (sym->name[2] == '_'), "__gnu_lto_slim") == 0
799012573ebSchristos && report_plugin_err)
800012573ebSchristos {
801*e992f068Schristos report_plugin_err = false;
80275fd0b74Schristos non_fatal (_("%s: plugin needed to handle lto object"),
80375fd0b74Schristos bfd_get_filename (abfd));
804012573ebSchristos }
80575fd0b74Schristos
80675fd0b74Schristos if (undefined_only)
80775fd0b74Schristos keep = bfd_is_und_section (sym->section);
80875fd0b74Schristos else if (external_only)
80975fd0b74Schristos /* PR binutls/12753: Unique symbols are global too. */
81075fd0b74Schristos keep = ((sym->flags & (BSF_GLOBAL
81175fd0b74Schristos | BSF_WEAK
81275fd0b74Schristos | BSF_GNU_UNIQUE)) != 0
81375fd0b74Schristos || bfd_is_und_section (sym->section)
81475fd0b74Schristos || bfd_is_com_section (sym->section));
815*e992f068Schristos else if (non_weak)
816*e992f068Schristos keep = ((sym->flags & BSF_WEAK) == 0);
81775fd0b74Schristos else
81875fd0b74Schristos keep = 1;
81975fd0b74Schristos
82075fd0b74Schristos if (keep
82175fd0b74Schristos && ! print_debug_syms
82275fd0b74Schristos && (sym->flags & BSF_DEBUGGING) != 0)
82375fd0b74Schristos keep = 0;
82475fd0b74Schristos
82575fd0b74Schristos if (keep
82675fd0b74Schristos && sort_by_size
82775fd0b74Schristos && (bfd_is_abs_section (sym->section)
82875fd0b74Schristos || bfd_is_und_section (sym->section)))
82975fd0b74Schristos keep = 0;
83075fd0b74Schristos
83175fd0b74Schristos if (keep
83275fd0b74Schristos && defined_only)
83375fd0b74Schristos {
83475fd0b74Schristos if (bfd_is_und_section (sym->section))
83575fd0b74Schristos keep = 0;
83675fd0b74Schristos }
83775fd0b74Schristos
83875fd0b74Schristos if (keep
83975fd0b74Schristos && bfd_is_target_special_symbol (abfd, sym)
84075fd0b74Schristos && ! allow_special_symbols)
84175fd0b74Schristos keep = 0;
84275fd0b74Schristos
84375fd0b74Schristos if (keep)
84475fd0b74Schristos {
84575fd0b74Schristos if (to != from)
84675fd0b74Schristos memcpy (to, from, size);
84775fd0b74Schristos to += size;
84875fd0b74Schristos }
84975fd0b74Schristos }
85075fd0b74Schristos
85175fd0b74Schristos return (to - (bfd_byte *) minisyms) / size;
85275fd0b74Schristos }
85375fd0b74Schristos
85475fd0b74Schristos /* These globals are used to pass information into the sorting
85575fd0b74Schristos routines. */
85675fd0b74Schristos static bfd *sort_bfd;
857*e992f068Schristos static bool sort_dynamic;
85875fd0b74Schristos static asymbol *sort_x;
85975fd0b74Schristos static asymbol *sort_y;
86075fd0b74Schristos
86175fd0b74Schristos /* Symbol-sorting predicates */
86275fd0b74Schristos #define valueof(x) ((x)->section->vma + (x)->value)
86375fd0b74Schristos
86475fd0b74Schristos /* Numeric sorts. Undefined symbols are always considered "less than"
86575fd0b74Schristos defined symbols with zero values. Common symbols are not treated
86675fd0b74Schristos specially -- i.e., their sizes are used as their "values". */
86775fd0b74Schristos
86875fd0b74Schristos static int
non_numeric_forward(const void * P_x,const void * P_y)86975fd0b74Schristos non_numeric_forward (const void *P_x, const void *P_y)
87075fd0b74Schristos {
87175fd0b74Schristos asymbol *x, *y;
87275fd0b74Schristos const char *xn, *yn;
87375fd0b74Schristos
87475fd0b74Schristos x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
87575fd0b74Schristos y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
87675fd0b74Schristos if (x == NULL || y == NULL)
87775fd0b74Schristos bfd_fatal (bfd_get_filename (sort_bfd));
87875fd0b74Schristos
87975fd0b74Schristos xn = bfd_asymbol_name (x);
88075fd0b74Schristos yn = bfd_asymbol_name (y);
88175fd0b74Schristos
88275fd0b74Schristos if (yn == NULL)
88375fd0b74Schristos return xn != NULL;
88475fd0b74Schristos if (xn == NULL)
88575fd0b74Schristos return -1;
88675fd0b74Schristos
88775fd0b74Schristos /* Solaris 2.5 has a bug in strcoll.
88875fd0b74Schristos strcoll returns invalid values when confronted with empty strings. */
88975fd0b74Schristos if (*yn == '\0')
89075fd0b74Schristos return *xn != '\0';
89175fd0b74Schristos if (*xn == '\0')
89275fd0b74Schristos return -1;
89375fd0b74Schristos
89475fd0b74Schristos return strcoll (xn, yn);
89575fd0b74Schristos }
89675fd0b74Schristos
89775fd0b74Schristos static int
non_numeric_reverse(const void * x,const void * y)89875fd0b74Schristos non_numeric_reverse (const void *x, const void *y)
89975fd0b74Schristos {
90075fd0b74Schristos return - non_numeric_forward (x, y);
90175fd0b74Schristos }
90275fd0b74Schristos
90375fd0b74Schristos static int
numeric_forward(const void * P_x,const void * P_y)90475fd0b74Schristos numeric_forward (const void *P_x, const void *P_y)
90575fd0b74Schristos {
90675fd0b74Schristos asymbol *x, *y;
90775fd0b74Schristos asection *xs, *ys;
90875fd0b74Schristos
90975fd0b74Schristos x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
91075fd0b74Schristos y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
91175fd0b74Schristos if (x == NULL || y == NULL)
91275fd0b74Schristos bfd_fatal (bfd_get_filename (sort_bfd));
91375fd0b74Schristos
914012573ebSchristos xs = bfd_asymbol_section (x);
915012573ebSchristos ys = bfd_asymbol_section (y);
91675fd0b74Schristos
91775fd0b74Schristos if (bfd_is_und_section (xs))
91875fd0b74Schristos {
91975fd0b74Schristos if (! bfd_is_und_section (ys))
92075fd0b74Schristos return -1;
92175fd0b74Schristos }
92275fd0b74Schristos else if (bfd_is_und_section (ys))
92375fd0b74Schristos return 1;
92475fd0b74Schristos else if (valueof (x) != valueof (y))
92575fd0b74Schristos return valueof (x) < valueof (y) ? -1 : 1;
92675fd0b74Schristos
92775fd0b74Schristos return non_numeric_forward (P_x, P_y);
92875fd0b74Schristos }
92975fd0b74Schristos
93075fd0b74Schristos static int
numeric_reverse(const void * x,const void * y)93175fd0b74Schristos numeric_reverse (const void *x, const void *y)
93275fd0b74Schristos {
93375fd0b74Schristos return - numeric_forward (x, y);
93475fd0b74Schristos }
93575fd0b74Schristos
93675fd0b74Schristos static int (*(sorters[2][2])) (const void *, const void *) =
93775fd0b74Schristos {
93875fd0b74Schristos { non_numeric_forward, non_numeric_reverse },
93975fd0b74Schristos { numeric_forward, numeric_reverse }
94075fd0b74Schristos };
94175fd0b74Schristos
94275fd0b74Schristos /* This sort routine is used by sort_symbols_by_size. It is similar
94375fd0b74Schristos to numeric_forward, but when symbols have the same value it sorts
94475fd0b74Schristos by section VMA. This simplifies the sort_symbols_by_size code
94575fd0b74Schristos which handles symbols at the end of sections. Also, this routine
94675fd0b74Schristos tries to sort file names before other symbols with the same value.
94775fd0b74Schristos That will make the file name have a zero size, which will make
94875fd0b74Schristos sort_symbols_by_size choose the non file name symbol, leading to
94975fd0b74Schristos more meaningful output. For similar reasons, this code sorts
95075fd0b74Schristos gnu_compiled_* and gcc2_compiled before other symbols with the same
95175fd0b74Schristos value. */
95275fd0b74Schristos
95375fd0b74Schristos static int
size_forward1(const void * P_x,const void * P_y)95475fd0b74Schristos size_forward1 (const void *P_x, const void *P_y)
95575fd0b74Schristos {
95675fd0b74Schristos asymbol *x, *y;
95775fd0b74Schristos asection *xs, *ys;
95875fd0b74Schristos const char *xn, *yn;
95975fd0b74Schristos size_t xnl, ynl;
96075fd0b74Schristos int xf, yf;
96175fd0b74Schristos
96275fd0b74Schristos x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
96375fd0b74Schristos y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
96475fd0b74Schristos if (x == NULL || y == NULL)
96575fd0b74Schristos bfd_fatal (bfd_get_filename (sort_bfd));
96675fd0b74Schristos
967012573ebSchristos xs = bfd_asymbol_section (x);
968012573ebSchristos ys = bfd_asymbol_section (y);
96975fd0b74Schristos
97075fd0b74Schristos if (bfd_is_und_section (xs))
97175fd0b74Schristos abort ();
97275fd0b74Schristos if (bfd_is_und_section (ys))
97375fd0b74Schristos abort ();
97475fd0b74Schristos
97575fd0b74Schristos if (valueof (x) != valueof (y))
97675fd0b74Schristos return valueof (x) < valueof (y) ? -1 : 1;
97775fd0b74Schristos
97875fd0b74Schristos if (xs->vma != ys->vma)
97975fd0b74Schristos return xs->vma < ys->vma ? -1 : 1;
98075fd0b74Schristos
98175fd0b74Schristos xn = bfd_asymbol_name (x);
98275fd0b74Schristos yn = bfd_asymbol_name (y);
98375fd0b74Schristos xnl = strlen (xn);
98475fd0b74Schristos ynl = strlen (yn);
98575fd0b74Schristos
98675fd0b74Schristos /* The symbols gnu_compiled and gcc2_compiled convey even less
98775fd0b74Schristos information than the file name, so sort them out first. */
98875fd0b74Schristos
98975fd0b74Schristos xf = (strstr (xn, "gnu_compiled") != NULL
99075fd0b74Schristos || strstr (xn, "gcc2_compiled") != NULL);
99175fd0b74Schristos yf = (strstr (yn, "gnu_compiled") != NULL
99275fd0b74Schristos || strstr (yn, "gcc2_compiled") != NULL);
99375fd0b74Schristos
99475fd0b74Schristos if (xf && ! yf)
99575fd0b74Schristos return -1;
99675fd0b74Schristos if (! xf && yf)
99775fd0b74Schristos return 1;
99875fd0b74Schristos
99975fd0b74Schristos /* We use a heuristic for the file name. It may not work on non
100075fd0b74Schristos Unix systems, but it doesn't really matter; the only difference
100175fd0b74Schristos is precisely which symbol names get printed. */
100275fd0b74Schristos
100375fd0b74Schristos #define file_symbol(s, sn, snl) \
100475fd0b74Schristos (((s)->flags & BSF_FILE) != 0 \
1005ede78133Schristos || ((snl) > 2 \
1006ede78133Schristos && (sn)[(snl) - 2] == '.' \
100775fd0b74Schristos && ((sn)[(snl) - 1] == 'o' \
100875fd0b74Schristos || (sn)[(snl) - 1] == 'a')))
100975fd0b74Schristos
101075fd0b74Schristos xf = file_symbol (x, xn, xnl);
101175fd0b74Schristos yf = file_symbol (y, yn, ynl);
101275fd0b74Schristos
101375fd0b74Schristos if (xf && ! yf)
101475fd0b74Schristos return -1;
101575fd0b74Schristos if (! xf && yf)
101675fd0b74Schristos return 1;
101775fd0b74Schristos
101875fd0b74Schristos return non_numeric_forward (P_x, P_y);
101975fd0b74Schristos }
102075fd0b74Schristos
102175fd0b74Schristos /* This sort routine is used by sort_symbols_by_size. It is sorting
102275fd0b74Schristos an array of size_sym structures into size order. */
102375fd0b74Schristos
102475fd0b74Schristos static int
size_forward2(const void * P_x,const void * P_y)102575fd0b74Schristos size_forward2 (const void *P_x, const void *P_y)
102675fd0b74Schristos {
102775fd0b74Schristos const struct size_sym *x = (const struct size_sym *) P_x;
102875fd0b74Schristos const struct size_sym *y = (const struct size_sym *) P_y;
102975fd0b74Schristos
103075fd0b74Schristos if (x->size < y->size)
103175fd0b74Schristos return reverse_sort ? 1 : -1;
103275fd0b74Schristos else if (x->size > y->size)
103375fd0b74Schristos return reverse_sort ? -1 : 1;
103475fd0b74Schristos else
103575fd0b74Schristos return sorters[0][reverse_sort] (x->minisym, y->minisym);
103675fd0b74Schristos }
103775fd0b74Schristos
103875fd0b74Schristos /* Sort the symbols by size. ELF provides a size but for other formats
103975fd0b74Schristos we have to make a guess by assuming that the difference between the
104075fd0b74Schristos address of a symbol and the address of the next higher symbol is the
104175fd0b74Schristos size. */
104275fd0b74Schristos
104375fd0b74Schristos static long
sort_symbols_by_size(bfd * abfd,bool is_dynamic,void * minisyms,long symcount,unsigned int size,struct size_sym ** symsizesp)1044*e992f068Schristos sort_symbols_by_size (bfd *abfd, bool is_dynamic, void *minisyms,
104575fd0b74Schristos long symcount, unsigned int size,
104675fd0b74Schristos struct size_sym **symsizesp)
104775fd0b74Schristos {
104875fd0b74Schristos struct size_sym *symsizes;
104975fd0b74Schristos bfd_byte *from, *fromend;
105075fd0b74Schristos asymbol *sym = NULL;
105175fd0b74Schristos asymbol *store_sym, *store_next;
105275fd0b74Schristos
105375fd0b74Schristos qsort (minisyms, symcount, size, size_forward1);
105475fd0b74Schristos
105575fd0b74Schristos /* We are going to return a special set of symbols and sizes to
105675fd0b74Schristos print. */
105775fd0b74Schristos symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym));
105875fd0b74Schristos *symsizesp = symsizes;
105975fd0b74Schristos
106075fd0b74Schristos /* Note that filter_symbols has already removed all absolute and
106175fd0b74Schristos undefined symbols. Here we remove all symbols whose size winds
106275fd0b74Schristos up as zero. */
106375fd0b74Schristos from = (bfd_byte *) minisyms;
106475fd0b74Schristos fromend = from + symcount * size;
106575fd0b74Schristos
106675fd0b74Schristos store_sym = sort_x;
106775fd0b74Schristos store_next = sort_y;
106875fd0b74Schristos
106975fd0b74Schristos if (from < fromend)
107075fd0b74Schristos {
107175fd0b74Schristos sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, (const void *) from,
107275fd0b74Schristos store_sym);
107375fd0b74Schristos if (sym == NULL)
107475fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
107575fd0b74Schristos }
107675fd0b74Schristos
107775fd0b74Schristos for (; from < fromend; from += size)
107875fd0b74Schristos {
107975fd0b74Schristos asymbol *next;
108075fd0b74Schristos asection *sec;
108175fd0b74Schristos bfd_vma sz;
108275fd0b74Schristos asymbol *temp;
108375fd0b74Schristos
108475fd0b74Schristos if (from + size < fromend)
108575fd0b74Schristos {
108675fd0b74Schristos next = bfd_minisymbol_to_symbol (abfd,
108775fd0b74Schristos is_dynamic,
108875fd0b74Schristos (const void *) (from + size),
108975fd0b74Schristos store_next);
109075fd0b74Schristos if (next == NULL)
109175fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
109275fd0b74Schristos }
109375fd0b74Schristos else
109475fd0b74Schristos next = NULL;
109575fd0b74Schristos
1096012573ebSchristos sec = bfd_asymbol_section (sym);
109775fd0b74Schristos
1098ede78133Schristos /* Synthetic symbols don't have a full type set of data available, thus
1099ede78133Schristos we can't rely on that information for the symbol size. Ditto for
1100ede78133Schristos bfd/section.c:global_syms like *ABS*. */
1101ede78133Schristos if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0
1102ede78133Schristos && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
110375fd0b74Schristos sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
1104ede78133Schristos else if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0
1105ede78133Schristos && bfd_is_com_section (sec))
110675fd0b74Schristos sz = sym->value;
110775fd0b74Schristos else
110875fd0b74Schristos {
110975fd0b74Schristos if (from + size < fromend
1110012573ebSchristos && sec == bfd_asymbol_section (next))
111175fd0b74Schristos sz = valueof (next) - valueof (sym);
111275fd0b74Schristos else
1113012573ebSchristos sz = (bfd_section_vma (sec)
1114012573ebSchristos + bfd_section_size (sec)
111575fd0b74Schristos - valueof (sym));
111675fd0b74Schristos }
111775fd0b74Schristos
111875fd0b74Schristos if (sz != 0)
111975fd0b74Schristos {
112075fd0b74Schristos symsizes->minisym = (const void *) from;
112175fd0b74Schristos symsizes->size = sz;
112275fd0b74Schristos ++symsizes;
112375fd0b74Schristos }
112475fd0b74Schristos
112575fd0b74Schristos sym = next;
112675fd0b74Schristos
112775fd0b74Schristos temp = store_sym;
112875fd0b74Schristos store_sym = store_next;
112975fd0b74Schristos store_next = temp;
113075fd0b74Schristos }
113175fd0b74Schristos
113275fd0b74Schristos symcount = symsizes - *symsizesp;
113375fd0b74Schristos
113475fd0b74Schristos /* We must now sort again by size. */
113575fd0b74Schristos qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
113675fd0b74Schristos
113775fd0b74Schristos return symcount;
113875fd0b74Schristos }
113975fd0b74Schristos
114075fd0b74Schristos /* This function is used to get the relocs for a particular section.
114175fd0b74Schristos It is called via bfd_map_over_sections. */
114275fd0b74Schristos
114375fd0b74Schristos static void
get_relocs(bfd * abfd,asection * sec,void * dataarg)114475fd0b74Schristos get_relocs (bfd *abfd, asection *sec, void *dataarg)
114575fd0b74Schristos {
114675fd0b74Schristos struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
114775fd0b74Schristos
114875fd0b74Schristos *data->secs = sec;
114975fd0b74Schristos
115075fd0b74Schristos if ((sec->flags & SEC_RELOC) == 0)
115175fd0b74Schristos {
115275fd0b74Schristos *data->relocs = NULL;
115375fd0b74Schristos *data->relcount = 0;
115475fd0b74Schristos }
115575fd0b74Schristos else
115675fd0b74Schristos {
115775fd0b74Schristos long relsize;
115875fd0b74Schristos
115975fd0b74Schristos relsize = bfd_get_reloc_upper_bound (abfd, sec);
116075fd0b74Schristos if (relsize < 0)
116175fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
116275fd0b74Schristos
116375fd0b74Schristos *data->relocs = (arelent **) xmalloc (relsize);
116475fd0b74Schristos *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
116575fd0b74Schristos data->syms);
116675fd0b74Schristos if (*data->relcount < 0)
116775fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
116875fd0b74Schristos }
116975fd0b74Schristos
117075fd0b74Schristos ++data->secs;
117175fd0b74Schristos ++data->relocs;
117275fd0b74Schristos ++data->relcount;
117375fd0b74Schristos }
117475fd0b74Schristos
117575fd0b74Schristos /* Print a single symbol. */
117675fd0b74Schristos
117775fd0b74Schristos static void
print_symbol(bfd * abfd,asymbol * sym,bfd_vma ssize,bfd * archive_bfd)117875fd0b74Schristos print_symbol (bfd * abfd,
117975fd0b74Schristos asymbol * sym,
118075fd0b74Schristos bfd_vma ssize,
1181ede78133Schristos bfd * archive_bfd)
118275fd0b74Schristos {
118375fd0b74Schristos symbol_info syminfo;
118475fd0b74Schristos struct extended_symbol_info info;
118575fd0b74Schristos
118675fd0b74Schristos PROGRESS (1);
118775fd0b74Schristos
118875fd0b74Schristos format->print_symbol_filename (archive_bfd, abfd);
118975fd0b74Schristos
119075fd0b74Schristos bfd_get_symbol_info (abfd, sym, &syminfo);
119175fd0b74Schristos
1192*e992f068Schristos /* PR 22967 - Distinguish between local and global ifunc symbols. */
1193*e992f068Schristos if (syminfo.type == 'i'
1194*e992f068Schristos && sym->flags & BSF_GNU_INDIRECT_FUNCTION)
1195*e992f068Schristos {
1196*e992f068Schristos if (ifunc_type_chars == NULL || ifunc_type_chars[0] == 0)
1197*e992f068Schristos ; /* Change nothing. */
1198*e992f068Schristos else if (sym->flags & BSF_GLOBAL)
1199*e992f068Schristos syminfo.type = ifunc_type_chars[0];
1200*e992f068Schristos else if (ifunc_type_chars[1] != 0)
1201*e992f068Schristos syminfo.type = ifunc_type_chars[1];
1202*e992f068Schristos }
1203*e992f068Schristos
120475fd0b74Schristos info.sinfo = &syminfo;
120575fd0b74Schristos info.ssize = ssize;
1206ede78133Schristos /* Synthetic symbols do not have a full symbol type set of data available.
1207ede78133Schristos Nor do bfd/section.c:global_syms like *ABS*. */
1208ede78133Schristos if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) != 0)
120975fd0b74Schristos {
121075fd0b74Schristos info.elfinfo = NULL;
121175fd0b74Schristos info.coffinfo = NULL;
121275fd0b74Schristos }
121375fd0b74Schristos else
121475fd0b74Schristos {
1215*e992f068Schristos info.elfinfo = elf_symbol_from (sym);
121675fd0b74Schristos info.coffinfo = coff_symbol_from (sym);
121775fd0b74Schristos }
121875fd0b74Schristos
121975fd0b74Schristos format->print_symbol_info (&info, abfd);
122075fd0b74Schristos
122175fd0b74Schristos if (line_numbers)
122275fd0b74Schristos {
122375fd0b74Schristos static asymbol **syms;
122475fd0b74Schristos static long symcount;
122575fd0b74Schristos const char *filename, *functionname;
122675fd0b74Schristos unsigned int lineno;
122775fd0b74Schristos
122875fd0b74Schristos /* We need to get the canonical symbols in order to call
122975fd0b74Schristos bfd_find_nearest_line. This is inefficient, but, then, you
123075fd0b74Schristos don't have to use --line-numbers. */
123175fd0b74Schristos if (abfd != lineno_cache_bfd && syms != NULL)
123275fd0b74Schristos {
123375fd0b74Schristos free (syms);
123475fd0b74Schristos syms = NULL;
123575fd0b74Schristos }
123675fd0b74Schristos if (syms == NULL)
123775fd0b74Schristos {
123875fd0b74Schristos long symsize;
123975fd0b74Schristos
124075fd0b74Schristos symsize = bfd_get_symtab_upper_bound (abfd);
124175fd0b74Schristos if (symsize < 0)
124275fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
124375fd0b74Schristos syms = (asymbol **) xmalloc (symsize);
124475fd0b74Schristos symcount = bfd_canonicalize_symtab (abfd, syms);
124575fd0b74Schristos if (symcount < 0)
124675fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
124775fd0b74Schristos lineno_cache_bfd = abfd;
124875fd0b74Schristos }
124975fd0b74Schristos
1250012573ebSchristos if (bfd_is_und_section (bfd_asymbol_section (sym)))
125175fd0b74Schristos {
125275fd0b74Schristos static asection **secs;
125375fd0b74Schristos static arelent ***relocs;
125475fd0b74Schristos static long *relcount;
125575fd0b74Schristos static unsigned int seccount;
125675fd0b74Schristos unsigned int i;
125775fd0b74Schristos const char *symname;
125875fd0b74Schristos
125975fd0b74Schristos /* For an undefined symbol, we try to find a reloc for the
126075fd0b74Schristos symbol, and print the line number of the reloc. */
126175fd0b74Schristos if (abfd != lineno_cache_rel_bfd && relocs != NULL)
126275fd0b74Schristos {
126375fd0b74Schristos for (i = 0; i < seccount; i++)
126475fd0b74Schristos if (relocs[i] != NULL)
126575fd0b74Schristos free (relocs[i]);
126675fd0b74Schristos free (secs);
126775fd0b74Schristos free (relocs);
126875fd0b74Schristos free (relcount);
126975fd0b74Schristos secs = NULL;
127075fd0b74Schristos relocs = NULL;
127175fd0b74Schristos relcount = NULL;
127275fd0b74Schristos }
127375fd0b74Schristos
127475fd0b74Schristos if (relocs == NULL)
127575fd0b74Schristos {
127675fd0b74Schristos struct get_relocs_info rinfo;
127775fd0b74Schristos
127875fd0b74Schristos seccount = bfd_count_sections (abfd);
127975fd0b74Schristos
128075fd0b74Schristos secs = (asection **) xmalloc (seccount * sizeof *secs);
128175fd0b74Schristos relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
128275fd0b74Schristos relcount = (long *) xmalloc (seccount * sizeof *relcount);
128375fd0b74Schristos
128475fd0b74Schristos rinfo.secs = secs;
128575fd0b74Schristos rinfo.relocs = relocs;
128675fd0b74Schristos rinfo.relcount = relcount;
128775fd0b74Schristos rinfo.syms = syms;
128875fd0b74Schristos bfd_map_over_sections (abfd, get_relocs, (void *) &rinfo);
128975fd0b74Schristos lineno_cache_rel_bfd = abfd;
129075fd0b74Schristos }
129175fd0b74Schristos
129275fd0b74Schristos symname = bfd_asymbol_name (sym);
129375fd0b74Schristos for (i = 0; i < seccount; i++)
129475fd0b74Schristos {
129575fd0b74Schristos long j;
129675fd0b74Schristos
129775fd0b74Schristos for (j = 0; j < relcount[i]; j++)
129875fd0b74Schristos {
129975fd0b74Schristos arelent *r;
130075fd0b74Schristos
130175fd0b74Schristos r = relocs[i][j];
130275fd0b74Schristos if (r->sym_ptr_ptr != NULL
130375fd0b74Schristos && (*r->sym_ptr_ptr)->section == sym->section
130475fd0b74Schristos && (*r->sym_ptr_ptr)->value == sym->value
130575fd0b74Schristos && strcmp (symname,
130675fd0b74Schristos bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
130775fd0b74Schristos && bfd_find_nearest_line (abfd, secs[i], syms,
130875fd0b74Schristos r->address, &filename,
130975fd0b74Schristos &functionname, &lineno)
131075fd0b74Schristos && filename != NULL)
131175fd0b74Schristos {
131275fd0b74Schristos /* We only print the first one we find. */
131375fd0b74Schristos printf ("\t%s:%u", filename, lineno);
131475fd0b74Schristos i = seccount;
131575fd0b74Schristos break;
131675fd0b74Schristos }
131775fd0b74Schristos }
131875fd0b74Schristos }
131975fd0b74Schristos }
1320012573ebSchristos else if (bfd_asymbol_section (sym)->owner == abfd)
132175fd0b74Schristos {
132275fd0b74Schristos if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
1323012573ebSchristos || bfd_find_nearest_line (abfd, bfd_asymbol_section (sym),
132475fd0b74Schristos syms, sym->value, &filename,
132575fd0b74Schristos &functionname, &lineno))
132675fd0b74Schristos && filename != NULL
132775fd0b74Schristos && lineno != 0)
132875fd0b74Schristos printf ("\t%s:%u", filename, lineno);
132975fd0b74Schristos }
133075fd0b74Schristos }
133175fd0b74Schristos
133275fd0b74Schristos putchar ('\n');
133375fd0b74Schristos }
133475fd0b74Schristos
133575fd0b74Schristos /* Print the symbols when sorting by size. */
133675fd0b74Schristos
133775fd0b74Schristos static void
print_size_symbols(bfd * abfd,bool is_dynamic,struct size_sym * symsizes,long symcount,bfd * archive_bfd)133875fd0b74Schristos print_size_symbols (bfd *abfd,
1339*e992f068Schristos bool is_dynamic,
134075fd0b74Schristos struct size_sym *symsizes,
134175fd0b74Schristos long symcount,
134275fd0b74Schristos bfd *archive_bfd)
134375fd0b74Schristos {
134475fd0b74Schristos asymbol *store;
134575fd0b74Schristos struct size_sym *from;
134675fd0b74Schristos struct size_sym *fromend;
134775fd0b74Schristos
134875fd0b74Schristos store = bfd_make_empty_symbol (abfd);
134975fd0b74Schristos if (store == NULL)
135075fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
135175fd0b74Schristos
135275fd0b74Schristos from = symsizes;
135375fd0b74Schristos fromend = from + symcount;
135475fd0b74Schristos
135575fd0b74Schristos for (; from < fromend; from++)
135675fd0b74Schristos {
135775fd0b74Schristos asymbol *sym;
135875fd0b74Schristos
135975fd0b74Schristos sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, from->minisym, store);
136075fd0b74Schristos if (sym == NULL)
136175fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
136275fd0b74Schristos
1363ede78133Schristos print_symbol (abfd, sym, from->size, archive_bfd);
136475fd0b74Schristos }
136575fd0b74Schristos }
136675fd0b74Schristos
136775fd0b74Schristos
136875fd0b74Schristos /* Print the symbols of ABFD that are held in MINISYMS.
136975fd0b74Schristos
137075fd0b74Schristos If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.
137175fd0b74Schristos
1372ede78133Schristos SYMCOUNT is the number of symbols in MINISYMS.
137375fd0b74Schristos
137475fd0b74Schristos SIZE is the size of a symbol in MINISYMS. */
137575fd0b74Schristos
137675fd0b74Schristos static void
print_symbols(bfd * abfd,bool is_dynamic,void * minisyms,long symcount,unsigned int size,bfd * archive_bfd)137775fd0b74Schristos print_symbols (bfd *abfd,
1378*e992f068Schristos bool is_dynamic,
137975fd0b74Schristos void *minisyms,
138075fd0b74Schristos long symcount,
138175fd0b74Schristos unsigned int size,
138275fd0b74Schristos bfd *archive_bfd)
138375fd0b74Schristos {
138475fd0b74Schristos asymbol *store;
138575fd0b74Schristos bfd_byte *from;
138675fd0b74Schristos bfd_byte *fromend;
138775fd0b74Schristos
138875fd0b74Schristos store = bfd_make_empty_symbol (abfd);
138975fd0b74Schristos if (store == NULL)
139075fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
139175fd0b74Schristos
139275fd0b74Schristos from = (bfd_byte *) minisyms;
139375fd0b74Schristos fromend = from + symcount * size;
139475fd0b74Schristos
139575fd0b74Schristos for (; from < fromend; from += size)
139675fd0b74Schristos {
139775fd0b74Schristos asymbol *sym;
139875fd0b74Schristos
139975fd0b74Schristos sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, from, store);
140075fd0b74Schristos if (sym == NULL)
140175fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
140275fd0b74Schristos
1403ede78133Schristos print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
140475fd0b74Schristos }
140575fd0b74Schristos }
140675fd0b74Schristos
140775fd0b74Schristos /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */
140875fd0b74Schristos
140975fd0b74Schristos static void
display_rel_file(bfd * abfd,bfd * archive_bfd)141075fd0b74Schristos display_rel_file (bfd *abfd, bfd *archive_bfd)
141175fd0b74Schristos {
141275fd0b74Schristos long symcount;
141375fd0b74Schristos void *minisyms;
141475fd0b74Schristos unsigned int size;
141575fd0b74Schristos struct size_sym *symsizes;
1416ede78133Schristos asymbol *synthsyms = NULL;
141775fd0b74Schristos
141875fd0b74Schristos if (! dynamic)
141975fd0b74Schristos {
142075fd0b74Schristos if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
142175fd0b74Schristos {
1422*e992f068Schristos if (!quiet)
142375fd0b74Schristos non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
142475fd0b74Schristos return;
142575fd0b74Schristos }
142675fd0b74Schristos }
142775fd0b74Schristos
142875fd0b74Schristos symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
142975fd0b74Schristos if (symcount < 0)
143075fd0b74Schristos {
143175fd0b74Schristos if (dynamic && bfd_get_error () == bfd_error_no_symbols)
143275fd0b74Schristos {
1433*e992f068Schristos if (!quiet)
143475fd0b74Schristos non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
143575fd0b74Schristos return;
143675fd0b74Schristos }
143775fd0b74Schristos
143875fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
143975fd0b74Schristos }
144075fd0b74Schristos
144175fd0b74Schristos if (symcount == 0)
144275fd0b74Schristos {
1443*e992f068Schristos if (!quiet)
144475fd0b74Schristos non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
144575fd0b74Schristos return;
144675fd0b74Schristos }
144775fd0b74Schristos
144875fd0b74Schristos if (show_synthetic && size == sizeof (asymbol *))
144975fd0b74Schristos {
145075fd0b74Schristos asymbol **static_syms = NULL;
145175fd0b74Schristos asymbol **dyn_syms = NULL;
145275fd0b74Schristos long static_count = 0;
145375fd0b74Schristos long dyn_count = 0;
1454ede78133Schristos long synth_count;
145575fd0b74Schristos
145675fd0b74Schristos if (dynamic)
145775fd0b74Schristos {
145875fd0b74Schristos dyn_count = symcount;
145975fd0b74Schristos dyn_syms = (asymbol **) minisyms;
146075fd0b74Schristos }
146175fd0b74Schristos else
146275fd0b74Schristos {
146375fd0b74Schristos long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
146475fd0b74Schristos
146575fd0b74Schristos static_count = symcount;
146675fd0b74Schristos static_syms = (asymbol **) minisyms;
146775fd0b74Schristos
146875fd0b74Schristos if (storage > 0)
146975fd0b74Schristos {
147075fd0b74Schristos dyn_syms = (asymbol **) xmalloc (storage);
147175fd0b74Schristos dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms);
147275fd0b74Schristos if (dyn_count < 0)
147375fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
147475fd0b74Schristos }
147575fd0b74Schristos }
147675fd0b74Schristos
147775fd0b74Schristos synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
147875fd0b74Schristos dyn_count, dyn_syms, &synthsyms);
147975fd0b74Schristos if (synth_count > 0)
148075fd0b74Schristos {
148175fd0b74Schristos asymbol **symp;
148275fd0b74Schristos long i;
148375fd0b74Schristos
1484012573ebSchristos minisyms = xrealloc (minisyms,
1485012573ebSchristos (symcount + synth_count + 1) * sizeof (*symp));
1486012573ebSchristos symp = (asymbol **) minisyms + symcount;
148775fd0b74Schristos for (i = 0; i < synth_count; i++)
148875fd0b74Schristos *symp++ = synthsyms + i;
148975fd0b74Schristos *symp = 0;
149075fd0b74Schristos symcount += synth_count;
149175fd0b74Schristos }
1492012573ebSchristos if (!dynamic && dyn_syms != NULL)
1493012573ebSchristos free (dyn_syms);
1494012573ebSchristos }
1495012573ebSchristos
1496012573ebSchristos /* lto_slim_object is set to false when a bfd is loaded with a compiler
1497012573ebSchristos LTO plugin. */
1498012573ebSchristos if (abfd->lto_slim_object)
1499012573ebSchristos {
1500*e992f068Schristos report_plugin_err = false;
1501012573ebSchristos non_fatal (_("%s: plugin needed to handle lto object"),
1502012573ebSchristos bfd_get_filename (abfd));
150375fd0b74Schristos }
150475fd0b74Schristos
150575fd0b74Schristos /* Discard the symbols we don't want to print.
150675fd0b74Schristos It's OK to do this in place; we'll free the storage anyway
150775fd0b74Schristos (after printing). */
150875fd0b74Schristos
150975fd0b74Schristos symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
151075fd0b74Schristos
151175fd0b74Schristos symsizes = NULL;
151275fd0b74Schristos if (! no_sort)
151375fd0b74Schristos {
151475fd0b74Schristos sort_bfd = abfd;
151575fd0b74Schristos sort_dynamic = dynamic;
151675fd0b74Schristos sort_x = bfd_make_empty_symbol (abfd);
151775fd0b74Schristos sort_y = bfd_make_empty_symbol (abfd);
151875fd0b74Schristos if (sort_x == NULL || sort_y == NULL)
151975fd0b74Schristos bfd_fatal (bfd_get_filename (abfd));
152075fd0b74Schristos
152175fd0b74Schristos if (! sort_by_size)
152275fd0b74Schristos qsort (minisyms, symcount, size,
152375fd0b74Schristos sorters[sort_numerically][reverse_sort]);
152475fd0b74Schristos else
152575fd0b74Schristos symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
152675fd0b74Schristos size, &symsizes);
152775fd0b74Schristos }
152875fd0b74Schristos
152975fd0b74Schristos if (! sort_by_size)
1530ede78133Schristos print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
153175fd0b74Schristos else
1532ede78133Schristos print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
153375fd0b74Schristos
1534ede78133Schristos if (synthsyms)
1535ede78133Schristos free (synthsyms);
153675fd0b74Schristos free (minisyms);
153775fd0b74Schristos free (symsizes);
153875fd0b74Schristos }
153975fd0b74Schristos
1540012573ebSchristos /* Construct a formatting string for printing symbol values. */
1541012573ebSchristos
1542012573ebSchristos static const char *
get_print_format(void)1543012573ebSchristos get_print_format (void)
1544012573ebSchristos {
1545012573ebSchristos const char * padding;
1546*e992f068Schristos if (print_format == FORMAT_POSIX || print_format == FORMAT_JUST_SYMBOLS)
1547012573ebSchristos {
1548012573ebSchristos /* POSIX compatible output does not have any padding. */
1549012573ebSchristos padding = "";
1550012573ebSchristos }
1551012573ebSchristos else if (print_width == 32)
1552012573ebSchristos {
1553012573ebSchristos padding ="08";
1554012573ebSchristos }
1555012573ebSchristos else /* print_width == 64 */
1556012573ebSchristos {
1557012573ebSchristos padding = "016";
1558012573ebSchristos }
1559012573ebSchristos
1560012573ebSchristos const char * radix = NULL;
1561012573ebSchristos switch (print_radix)
1562012573ebSchristos {
1563*e992f068Schristos case 8: radix = PRIo64; break;
1564*e992f068Schristos case 10: radix = PRId64; break;
1565*e992f068Schristos case 16: radix = PRIx64; break;
1566012573ebSchristos }
1567012573ebSchristos
1568*e992f068Schristos return concat ("%", padding, radix, NULL);
1569012573ebSchristos }
1570012573ebSchristos
157175fd0b74Schristos static void
set_print_width(bfd * file)157275fd0b74Schristos set_print_width (bfd *file)
157375fd0b74Schristos {
157475fd0b74Schristos print_width = bfd_get_arch_size (file);
157575fd0b74Schristos
157675fd0b74Schristos if (print_width == -1)
157775fd0b74Schristos {
157875fd0b74Schristos /* PR binutils/4292
157975fd0b74Schristos Guess the target's bitsize based on its name.
158075fd0b74Schristos We assume here than any 64-bit format will include
158175fd0b74Schristos "64" somewhere in its name. The only known exception
158275fd0b74Schristos is the MMO object file format. */
158375fd0b74Schristos if (strstr (bfd_get_target (file), "64") != NULL
158475fd0b74Schristos || strcmp (bfd_get_target (file), "mmo") == 0)
158575fd0b74Schristos print_width = 64;
158675fd0b74Schristos else
158775fd0b74Schristos print_width = 32;
158875fd0b74Schristos }
1589012573ebSchristos free ((char *) print_format_string);
1590012573ebSchristos print_format_string = get_print_format ();
159175fd0b74Schristos }
159275fd0b74Schristos
159375fd0b74Schristos static void
display_archive(bfd * file)159475fd0b74Schristos display_archive (bfd *file)
159575fd0b74Schristos {
159675fd0b74Schristos bfd *arfile = NULL;
159775fd0b74Schristos bfd *last_arfile = NULL;
159875fd0b74Schristos char **matching;
159975fd0b74Schristos
160075fd0b74Schristos format->print_archive_filename (bfd_get_filename (file));
160175fd0b74Schristos
160275fd0b74Schristos if (print_armap)
160375fd0b74Schristos print_symdef_entry (file);
160475fd0b74Schristos
160575fd0b74Schristos for (;;)
160675fd0b74Schristos {
160775fd0b74Schristos PROGRESS (1);
160875fd0b74Schristos
160975fd0b74Schristos arfile = bfd_openr_next_archived_file (file, arfile);
161075fd0b74Schristos
161175fd0b74Schristos if (arfile == NULL)
161275fd0b74Schristos {
161375fd0b74Schristos if (bfd_get_error () != bfd_error_no_more_archived_files)
161475fd0b74Schristos bfd_fatal (bfd_get_filename (file));
161575fd0b74Schristos break;
161675fd0b74Schristos }
161775fd0b74Schristos
161875fd0b74Schristos if (bfd_check_format_matches (arfile, bfd_object, &matching))
161975fd0b74Schristos {
162075fd0b74Schristos set_print_width (arfile);
162175fd0b74Schristos format->print_archive_member (bfd_get_filename (file),
162275fd0b74Schristos bfd_get_filename (arfile));
162375fd0b74Schristos display_rel_file (arfile, file);
162475fd0b74Schristos }
162575fd0b74Schristos else
162675fd0b74Schristos {
162775fd0b74Schristos bfd_nonfatal (bfd_get_filename (arfile));
162875fd0b74Schristos if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
162975fd0b74Schristos list_matching_formats (matching);
163075fd0b74Schristos }
163175fd0b74Schristos
163275fd0b74Schristos if (last_arfile != NULL)
163375fd0b74Schristos {
163475fd0b74Schristos bfd_close (last_arfile);
163575fd0b74Schristos lineno_cache_bfd = NULL;
163675fd0b74Schristos lineno_cache_rel_bfd = NULL;
163775fd0b74Schristos if (arfile == last_arfile)
163875fd0b74Schristos return;
163975fd0b74Schristos }
164075fd0b74Schristos last_arfile = arfile;
164175fd0b74Schristos }
164275fd0b74Schristos
164375fd0b74Schristos if (last_arfile != NULL)
164475fd0b74Schristos {
164575fd0b74Schristos bfd_close (last_arfile);
164675fd0b74Schristos lineno_cache_bfd = NULL;
164775fd0b74Schristos lineno_cache_rel_bfd = NULL;
164875fd0b74Schristos }
164975fd0b74Schristos }
165075fd0b74Schristos
1651*e992f068Schristos static bool
display_file(char * filename)165275fd0b74Schristos display_file (char *filename)
165375fd0b74Schristos {
1654*e992f068Schristos bool retval = true;
165575fd0b74Schristos bfd *file;
165675fd0b74Schristos char **matching;
165775fd0b74Schristos
165875fd0b74Schristos if (get_file_size (filename) < 1)
1659*e992f068Schristos return false;
166075fd0b74Schristos
166175fd0b74Schristos file = bfd_openr (filename, target ? target : plugin_target);
166275fd0b74Schristos if (file == NULL)
166375fd0b74Schristos {
166475fd0b74Schristos bfd_nonfatal (filename);
1665*e992f068Schristos return false;
166675fd0b74Schristos }
166775fd0b74Schristos
166875fd0b74Schristos /* If printing line numbers, decompress the debug sections. */
166975fd0b74Schristos if (line_numbers)
167075fd0b74Schristos file->flags |= BFD_DECOMPRESS;
167175fd0b74Schristos
167275fd0b74Schristos if (bfd_check_format (file, bfd_archive))
167375fd0b74Schristos {
167475fd0b74Schristos display_archive (file);
167575fd0b74Schristos }
167675fd0b74Schristos else if (bfd_check_format_matches (file, bfd_object, &matching))
167775fd0b74Schristos {
167875fd0b74Schristos set_print_width (file);
167975fd0b74Schristos format->print_object_filename (filename);
168075fd0b74Schristos display_rel_file (file, NULL);
168175fd0b74Schristos }
168275fd0b74Schristos else
168375fd0b74Schristos {
168475fd0b74Schristos bfd_nonfatal (filename);
168575fd0b74Schristos if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
168675fd0b74Schristos list_matching_formats (matching);
1687*e992f068Schristos retval = false;
168875fd0b74Schristos }
168975fd0b74Schristos
169075fd0b74Schristos if (!bfd_close (file))
169175fd0b74Schristos bfd_fatal (filename);
169275fd0b74Schristos
169375fd0b74Schristos lineno_cache_bfd = NULL;
169475fd0b74Schristos lineno_cache_rel_bfd = NULL;
169575fd0b74Schristos
169675fd0b74Schristos return retval;
169775fd0b74Schristos }
169875fd0b74Schristos
169975fd0b74Schristos /* The following 3 groups of functions are called unconditionally,
170075fd0b74Schristos once at the start of processing each file of the appropriate type.
170175fd0b74Schristos They should check `filename_per_file' and `filename_per_symbol',
170275fd0b74Schristos as appropriate for their output format, to determine whether to
170375fd0b74Schristos print anything. */
170475fd0b74Schristos
170575fd0b74Schristos /* Print the name of an object file given on the command line. */
170675fd0b74Schristos
170775fd0b74Schristos static void
print_object_filename_bsd(const char * filename)1708012573ebSchristos print_object_filename_bsd (const char *filename)
170975fd0b74Schristos {
171075fd0b74Schristos if (filename_per_file && !filename_per_symbol)
171175fd0b74Schristos printf ("\n%s:\n", filename);
171275fd0b74Schristos }
171375fd0b74Schristos
171475fd0b74Schristos static void
print_object_filename_sysv(const char * filename)1715012573ebSchristos print_object_filename_sysv (const char *filename)
171675fd0b74Schristos {
171775fd0b74Schristos if (undefined_only)
171875fd0b74Schristos printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
171975fd0b74Schristos else
172075fd0b74Schristos printf (_("\n\nSymbols from %s:\n\n"), filename);
172175fd0b74Schristos if (print_width == 32)
172275fd0b74Schristos printf (_("\
172375fd0b74Schristos Name Value Class Type Size Line Section\n\n"));
172475fd0b74Schristos else
172575fd0b74Schristos printf (_("\
172675fd0b74Schristos Name Value Class Type Size Line Section\n\n"));
172775fd0b74Schristos }
172875fd0b74Schristos
172975fd0b74Schristos static void
print_object_filename_posix(const char * filename)1730012573ebSchristos print_object_filename_posix (const char *filename)
173175fd0b74Schristos {
173275fd0b74Schristos if (filename_per_file && !filename_per_symbol)
173375fd0b74Schristos printf ("%s:\n", filename);
173475fd0b74Schristos }
1735*e992f068Schristos
1736*e992f068Schristos static void
do_not_print_object_filename(const char * filename ATTRIBUTE_UNUSED)1737*e992f068Schristos do_not_print_object_filename (const char *filename ATTRIBUTE_UNUSED)
1738*e992f068Schristos {
1739*e992f068Schristos }
174075fd0b74Schristos
174175fd0b74Schristos /* Print the name of an archive file given on the command line. */
174275fd0b74Schristos
174375fd0b74Schristos static void
print_archive_filename_bsd(const char * filename)1744012573ebSchristos print_archive_filename_bsd (const char *filename)
174575fd0b74Schristos {
174675fd0b74Schristos if (filename_per_file)
174775fd0b74Schristos printf ("\n%s:\n", filename);
174875fd0b74Schristos }
174975fd0b74Schristos
175075fd0b74Schristos static void
print_archive_filename_sysv(const char * filename ATTRIBUTE_UNUSED)1751012573ebSchristos print_archive_filename_sysv (const char *filename ATTRIBUTE_UNUSED)
175275fd0b74Schristos {
175375fd0b74Schristos }
175475fd0b74Schristos
175575fd0b74Schristos static void
print_archive_filename_posix(const char * filename ATTRIBUTE_UNUSED)1756012573ebSchristos print_archive_filename_posix (const char *filename ATTRIBUTE_UNUSED)
175775fd0b74Schristos {
175875fd0b74Schristos }
1759*e992f068Schristos
1760*e992f068Schristos static void
do_not_print_archive_filename(const char * filename ATTRIBUTE_UNUSED)1761*e992f068Schristos do_not_print_archive_filename (const char *filename ATTRIBUTE_UNUSED)
1762*e992f068Schristos {
1763*e992f068Schristos }
176475fd0b74Schristos
176575fd0b74Schristos /* Print the name of an archive member file. */
176675fd0b74Schristos
176775fd0b74Schristos static void
print_archive_member_bsd(const char * archive ATTRIBUTE_UNUSED,const char * filename)1768012573ebSchristos print_archive_member_bsd (const char *archive ATTRIBUTE_UNUSED,
176975fd0b74Schristos const char *filename)
177075fd0b74Schristos {
177175fd0b74Schristos if (!filename_per_symbol)
177275fd0b74Schristos printf ("\n%s:\n", filename);
177375fd0b74Schristos }
177475fd0b74Schristos
177575fd0b74Schristos static void
print_archive_member_sysv(const char * archive,const char * filename)1776012573ebSchristos print_archive_member_sysv (const char *archive, const char *filename)
177775fd0b74Schristos {
177875fd0b74Schristos if (undefined_only)
177975fd0b74Schristos printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
178075fd0b74Schristos else
178175fd0b74Schristos printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
178275fd0b74Schristos if (print_width == 32)
178375fd0b74Schristos printf (_("\
178475fd0b74Schristos Name Value Class Type Size Line Section\n\n"));
178575fd0b74Schristos else
178675fd0b74Schristos printf (_("\
178775fd0b74Schristos Name Value Class Type Size Line Section\n\n"));
178875fd0b74Schristos }
178975fd0b74Schristos
179075fd0b74Schristos static void
print_archive_member_posix(const char * archive,const char * filename)1791012573ebSchristos print_archive_member_posix (const char *archive, const char *filename)
179275fd0b74Schristos {
179375fd0b74Schristos if (!filename_per_symbol)
179475fd0b74Schristos printf ("%s[%s]:\n", archive, filename);
179575fd0b74Schristos }
1796*e992f068Schristos
1797*e992f068Schristos static void
do_not_print_archive_member(const char * archive ATTRIBUTE_UNUSED,const char * filename ATTRIBUTE_UNUSED)1798*e992f068Schristos do_not_print_archive_member (const char *archive ATTRIBUTE_UNUSED,
1799*e992f068Schristos const char *filename ATTRIBUTE_UNUSED)
1800*e992f068Schristos {
1801*e992f068Schristos }
1802*e992f068Schristos
180375fd0b74Schristos
180475fd0b74Schristos /* Print the name of the file (and archive, if there is one)
180575fd0b74Schristos containing a symbol. */
180675fd0b74Schristos
180775fd0b74Schristos static void
print_symbol_filename_bsd(bfd * archive_bfd,bfd * abfd)180875fd0b74Schristos print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
180975fd0b74Schristos {
181075fd0b74Schristos if (filename_per_symbol)
181175fd0b74Schristos {
181275fd0b74Schristos if (archive_bfd)
181375fd0b74Schristos printf ("%s:", bfd_get_filename (archive_bfd));
181475fd0b74Schristos printf ("%s:", bfd_get_filename (abfd));
181575fd0b74Schristos }
181675fd0b74Schristos }
181775fd0b74Schristos
181875fd0b74Schristos static void
print_symbol_filename_sysv(bfd * archive_bfd,bfd * abfd)181975fd0b74Schristos print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
182075fd0b74Schristos {
182175fd0b74Schristos if (filename_per_symbol)
182275fd0b74Schristos {
182375fd0b74Schristos if (archive_bfd)
182475fd0b74Schristos printf ("%s:", bfd_get_filename (archive_bfd));
182575fd0b74Schristos printf ("%s:", bfd_get_filename (abfd));
182675fd0b74Schristos }
182775fd0b74Schristos }
182875fd0b74Schristos
182975fd0b74Schristos static void
print_symbol_filename_posix(bfd * archive_bfd,bfd * abfd)183075fd0b74Schristos print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
183175fd0b74Schristos {
183275fd0b74Schristos if (filename_per_symbol)
183375fd0b74Schristos {
183475fd0b74Schristos if (archive_bfd)
183575fd0b74Schristos printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
183675fd0b74Schristos bfd_get_filename (abfd));
183775fd0b74Schristos else
183875fd0b74Schristos printf ("%s: ", bfd_get_filename (abfd));
183975fd0b74Schristos }
184075fd0b74Schristos }
1841*e992f068Schristos
1842*e992f068Schristos static void
do_not_print_symbol_filename(bfd * archive_bfd ATTRIBUTE_UNUSED,bfd * abfd ATTRIBUTE_UNUSED)1843*e992f068Schristos do_not_print_symbol_filename (bfd *archive_bfd ATTRIBUTE_UNUSED,
1844*e992f068Schristos bfd *abfd ATTRIBUTE_UNUSED)
1845*e992f068Schristos {
1846*e992f068Schristos }
1847*e992f068Schristos
184875fd0b74Schristos
184975fd0b74Schristos /* Print a symbol value. */
185075fd0b74Schristos
185175fd0b74Schristos static void
print_value(bfd * abfd ATTRIBUTE_UNUSED,bfd_vma val)185275fd0b74Schristos print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
185375fd0b74Schristos {
185475fd0b74Schristos switch (print_width)
185575fd0b74Schristos {
185675fd0b74Schristos case 32:
185775fd0b74Schristos case 64:
1858*e992f068Schristos printf (print_format_string, (uint64_t) val);
185975fd0b74Schristos break;
186075fd0b74Schristos
186175fd0b74Schristos default:
186275fd0b74Schristos fatal (_("Print width has not been initialized (%d)"), print_width);
186375fd0b74Schristos break;
186475fd0b74Schristos }
186575fd0b74Schristos }
186675fd0b74Schristos
186775fd0b74Schristos /* Print a line of information about a symbol. */
186875fd0b74Schristos
186975fd0b74Schristos static void
print_symbol_info_bsd(struct extended_symbol_info * info,bfd * abfd)187075fd0b74Schristos print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
187175fd0b74Schristos {
187275fd0b74Schristos if (bfd_is_undefined_symclass (SYM_TYPE (info)))
187375fd0b74Schristos {
187475fd0b74Schristos if (print_width == 64)
187575fd0b74Schristos printf (" ");
187675fd0b74Schristos printf (" ");
187775fd0b74Schristos }
187875fd0b74Schristos else
187975fd0b74Schristos {
188075fd0b74Schristos /* Normally we print the value of the symbol. If we are printing the
188175fd0b74Schristos size or sorting by size then we print its size, except for the
188275fd0b74Schristos (weird) special case where both flags are defined, in which case we
188375fd0b74Schristos print both values. This conforms to documented behaviour. */
188475fd0b74Schristos if (sort_by_size && !print_size)
188575fd0b74Schristos print_value (abfd, SYM_SIZE (info));
188675fd0b74Schristos else
188775fd0b74Schristos print_value (abfd, SYM_VALUE (info));
188875fd0b74Schristos if (print_size && SYM_SIZE (info))
188975fd0b74Schristos {
189075fd0b74Schristos printf (" ");
189175fd0b74Schristos print_value (abfd, SYM_SIZE (info));
189275fd0b74Schristos }
189375fd0b74Schristos }
189475fd0b74Schristos
189575fd0b74Schristos printf (" %c", SYM_TYPE (info));
189675fd0b74Schristos
189775fd0b74Schristos if (SYM_TYPE (info) == '-')
189875fd0b74Schristos {
189975fd0b74Schristos /* A stab. */
190075fd0b74Schristos printf (" ");
190175fd0b74Schristos printf (other_format, SYM_STAB_OTHER (info));
190275fd0b74Schristos printf (" ");
190375fd0b74Schristos printf (desc_format, SYM_STAB_DESC (info));
190475fd0b74Schristos printf (" %5s", SYM_STAB_NAME (info));
190575fd0b74Schristos }
1906*e992f068Schristos print_symname (" %s", info, NULL, abfd);
190775fd0b74Schristos }
190875fd0b74Schristos
190975fd0b74Schristos static void
print_symbol_info_sysv(struct extended_symbol_info * info,bfd * abfd)191075fd0b74Schristos print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
191175fd0b74Schristos {
1912*e992f068Schristos print_symname ("%-20s|", info, NULL, abfd);
191375fd0b74Schristos
191475fd0b74Schristos if (bfd_is_undefined_symclass (SYM_TYPE (info)))
191575fd0b74Schristos {
191675fd0b74Schristos if (print_width == 32)
191775fd0b74Schristos printf (" ");
191875fd0b74Schristos else
191975fd0b74Schristos printf (" ");
192075fd0b74Schristos }
192175fd0b74Schristos else
192275fd0b74Schristos print_value (abfd, SYM_VALUE (info));
192375fd0b74Schristos
192475fd0b74Schristos printf ("| %c |", SYM_TYPE (info));
192575fd0b74Schristos
192675fd0b74Schristos if (SYM_TYPE (info) == '-')
192775fd0b74Schristos {
192875fd0b74Schristos /* A stab. */
192975fd0b74Schristos printf ("%18s| ", SYM_STAB_NAME (info)); /* (C) Type. */
193075fd0b74Schristos printf (desc_format, SYM_STAB_DESC (info)); /* Size. */
193175fd0b74Schristos printf ("| |"); /* Line, Section. */
193275fd0b74Schristos }
193375fd0b74Schristos else
193475fd0b74Schristos {
193575fd0b74Schristos /* Type, Size, Line, Section */
193675fd0b74Schristos if (info->elfinfo)
193775fd0b74Schristos printf ("%18s|",
193875fd0b74Schristos get_elf_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
193975fd0b74Schristos else if (info->coffinfo)
194075fd0b74Schristos printf ("%18s|",
194175fd0b74Schristos get_coff_symbol_type (&info->coffinfo->native->u.syment));
194275fd0b74Schristos else
194375fd0b74Schristos printf (" |");
194475fd0b74Schristos
194575fd0b74Schristos if (SYM_SIZE (info))
194675fd0b74Schristos print_value (abfd, SYM_SIZE (info));
194775fd0b74Schristos else
194875fd0b74Schristos {
194975fd0b74Schristos if (print_width == 32)
195075fd0b74Schristos printf (" ");
195175fd0b74Schristos else
195275fd0b74Schristos printf (" ");
195375fd0b74Schristos }
195475fd0b74Schristos
195575fd0b74Schristos if (info->elfinfo)
195675fd0b74Schristos printf("| |%s", info->elfinfo->symbol.section->name);
195775fd0b74Schristos else if (info->coffinfo)
195875fd0b74Schristos printf("| |%s", info->coffinfo->symbol.section->name);
195975fd0b74Schristos else
196075fd0b74Schristos printf("| |");
196175fd0b74Schristos }
196275fd0b74Schristos }
196375fd0b74Schristos
196475fd0b74Schristos static void
print_symbol_info_posix(struct extended_symbol_info * info,bfd * abfd)196575fd0b74Schristos print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
196675fd0b74Schristos {
1967*e992f068Schristos print_symname ("%s ", info, NULL, abfd);
196875fd0b74Schristos printf ("%c ", SYM_TYPE (info));
196975fd0b74Schristos
197075fd0b74Schristos if (bfd_is_undefined_symclass (SYM_TYPE (info)))
197175fd0b74Schristos printf (" ");
197275fd0b74Schristos else
197375fd0b74Schristos {
197475fd0b74Schristos print_value (abfd, SYM_VALUE (info));
197575fd0b74Schristos printf (" ");
197675fd0b74Schristos if (SYM_SIZE (info))
197775fd0b74Schristos print_value (abfd, SYM_SIZE (info));
197875fd0b74Schristos }
197975fd0b74Schristos }
1980*e992f068Schristos
1981*e992f068Schristos static void
just_print_symbol_name(struct extended_symbol_info * info,bfd * abfd)1982*e992f068Schristos just_print_symbol_name (struct extended_symbol_info *info, bfd *abfd)
1983*e992f068Schristos {
1984*e992f068Schristos print_symname ("%s", info, NULL, abfd);
1985*e992f068Schristos }
198675fd0b74Schristos
198775fd0b74Schristos int
main(int argc,char ** argv)198875fd0b74Schristos main (int argc, char **argv)
198975fd0b74Schristos {
199075fd0b74Schristos int c;
199175fd0b74Schristos int retval;
199275fd0b74Schristos
1993*e992f068Schristos #ifdef HAVE_LC_MESSAGES
199475fd0b74Schristos setlocale (LC_MESSAGES, "");
199575fd0b74Schristos #endif
199675fd0b74Schristos setlocale (LC_CTYPE, "");
199775fd0b74Schristos setlocale (LC_COLLATE, "");
199875fd0b74Schristos bindtextdomain (PACKAGE, LOCALEDIR);
199975fd0b74Schristos textdomain (PACKAGE);
200075fd0b74Schristos
200175fd0b74Schristos program_name = *argv;
200275fd0b74Schristos xmalloc_set_program_name (program_name);
200375fd0b74Schristos bfd_set_error_program_name (program_name);
200475fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
200575fd0b74Schristos bfd_plugin_set_program_name (program_name);
200675fd0b74Schristos #endif
200775fd0b74Schristos
200875fd0b74Schristos START_PROGRESS (program_name, 0);
200975fd0b74Schristos
201075fd0b74Schristos expandargv (&argc, &argv);
201175fd0b74Schristos
2012012573ebSchristos if (bfd_init () != BFD_INIT_MAGIC)
2013012573ebSchristos fatal (_("fatal error: libbfd ABI mismatch"));
201475fd0b74Schristos set_default_bfd_target ();
201575fd0b74Schristos
2016*e992f068Schristos while ((c = getopt_long (argc, argv, "aABCDef:gHhjJlnopPrSst:uU:vVvWX:",
201775fd0b74Schristos long_options, (int *) 0)) != EOF)
201875fd0b74Schristos {
201975fd0b74Schristos switch (c)
202075fd0b74Schristos {
202175fd0b74Schristos case 'a':
202275fd0b74Schristos print_debug_syms = 1;
202375fd0b74Schristos break;
202475fd0b74Schristos case 'A':
202575fd0b74Schristos case 'o':
202675fd0b74Schristos filename_per_symbol = 1;
202775fd0b74Schristos break;
202875fd0b74Schristos case 'B': /* For MIPS compatibility. */
202975fd0b74Schristos set_output_format ("bsd");
203075fd0b74Schristos break;
203175fd0b74Schristos case 'C':
203275fd0b74Schristos do_demangle = 1;
203375fd0b74Schristos if (optarg != NULL)
203475fd0b74Schristos {
203575fd0b74Schristos enum demangling_styles style;
203675fd0b74Schristos
203775fd0b74Schristos style = cplus_demangle_name_to_style (optarg);
203875fd0b74Schristos if (style == unknown_demangling)
203975fd0b74Schristos fatal (_("unknown demangling style `%s'"),
204075fd0b74Schristos optarg);
204175fd0b74Schristos
204275fd0b74Schristos cplus_demangle_set_style (style);
204375fd0b74Schristos }
204475fd0b74Schristos break;
2045012573ebSchristos case OPTION_RECURSE_LIMIT:
2046012573ebSchristos demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
2047012573ebSchristos break;
2048012573ebSchristos case OPTION_NO_RECURSE_LIMIT:
2049012573ebSchristos demangle_flags |= DMGL_NO_RECURSE_LIMIT;
2050012573ebSchristos break;
2051*e992f068Schristos case OPTION_QUIET:
2052*e992f068Schristos quiet = 1;
2053*e992f068Schristos break;
205475fd0b74Schristos case 'D':
205575fd0b74Schristos dynamic = 1;
205675fd0b74Schristos break;
205775fd0b74Schristos case 'e':
205875fd0b74Schristos /* Ignored for HP/UX compatibility. */
205975fd0b74Schristos break;
206075fd0b74Schristos case 'f':
206175fd0b74Schristos set_output_format (optarg);
206275fd0b74Schristos break;
206375fd0b74Schristos case 'g':
206475fd0b74Schristos external_only = 1;
206575fd0b74Schristos break;
206675fd0b74Schristos case 'H':
206775fd0b74Schristos case 'h':
206875fd0b74Schristos usage (stdout, 0);
206975fd0b74Schristos case 'l':
207075fd0b74Schristos line_numbers = 1;
207175fd0b74Schristos break;
207275fd0b74Schristos case 'n':
207375fd0b74Schristos case 'v':
207475fd0b74Schristos no_sort = 0;
207575fd0b74Schristos sort_numerically = 1;
207675fd0b74Schristos sort_by_size = 0;
207775fd0b74Schristos break;
207875fd0b74Schristos case 'p':
207975fd0b74Schristos no_sort = 1;
208075fd0b74Schristos sort_numerically = 0;
208175fd0b74Schristos sort_by_size = 0;
208275fd0b74Schristos break;
208375fd0b74Schristos case OPTION_SIZE_SORT:
208475fd0b74Schristos no_sort = 0;
208575fd0b74Schristos sort_numerically = 0;
208675fd0b74Schristos sort_by_size = 1;
208775fd0b74Schristos break;
208875fd0b74Schristos case 'P':
208975fd0b74Schristos set_output_format ("posix");
209075fd0b74Schristos break;
2091*e992f068Schristos case 'j':
2092*e992f068Schristos set_output_format ("just-symbols");
2093*e992f068Schristos break;
209475fd0b74Schristos case 'r':
209575fd0b74Schristos reverse_sort = 1;
209675fd0b74Schristos break;
209775fd0b74Schristos case 's':
209875fd0b74Schristos print_armap = 1;
209975fd0b74Schristos break;
210075fd0b74Schristos case 'S':
210175fd0b74Schristos print_size = 1;
210275fd0b74Schristos break;
210375fd0b74Schristos case 't':
210475fd0b74Schristos set_print_radix (optarg);
210575fd0b74Schristos break;
210675fd0b74Schristos case 'u':
210775fd0b74Schristos undefined_only = 1;
2108*e992f068Schristos defined_only = 0;
210975fd0b74Schristos break;
2110*e992f068Schristos case 'U':
2111*e992f068Schristos defined_only = 1;
2112*e992f068Schristos undefined_only = 0;
2113*e992f068Schristos break;
2114*e992f068Schristos
2115*e992f068Schristos case OPTION_UNICODE:
2116*e992f068Schristos if (streq (optarg, "default") || streq (optarg, "d"))
2117*e992f068Schristos unicode_display = unicode_default;
2118*e992f068Schristos else if (streq (optarg, "locale") || streq (optarg, "l"))
2119*e992f068Schristos unicode_display = unicode_locale;
2120*e992f068Schristos else if (streq (optarg, "escape") || streq (optarg, "e"))
2121*e992f068Schristos unicode_display = unicode_escape;
2122*e992f068Schristos else if (streq (optarg, "invalid") || streq (optarg, "i"))
2123*e992f068Schristos unicode_display = unicode_invalid;
2124*e992f068Schristos else if (streq (optarg, "hex") || streq (optarg, "x"))
2125*e992f068Schristos unicode_display = unicode_hex;
2126*e992f068Schristos else if (streq (optarg, "highlight") || streq (optarg, "h"))
2127*e992f068Schristos unicode_display = unicode_highlight;
2128*e992f068Schristos else
2129*e992f068Schristos fatal (_("invalid argument to -U/--unicode: %s"), optarg);
2130*e992f068Schristos break;
2131*e992f068Schristos
213275fd0b74Schristos case 'V':
213375fd0b74Schristos show_version = 1;
213475fd0b74Schristos break;
2135*e992f068Schristos case 'W':
2136*e992f068Schristos non_weak = 1;
2137*e992f068Schristos break;
213875fd0b74Schristos case 'X':
213975fd0b74Schristos /* Ignored for (partial) AIX compatibility. On AIX, the
214075fd0b74Schristos argument has values 32, 64, or 32_64, and specifies that
214175fd0b74Schristos only 32-bit, only 64-bit, or both kinds of objects should
214275fd0b74Schristos be examined. The default is 32. So plain AIX nm on a
214375fd0b74Schristos library archive with both kinds of objects will ignore
214475fd0b74Schristos the 64-bit ones. For GNU nm, the default is and always
214575fd0b74Schristos has been -X 32_64, and other options are not supported. */
214675fd0b74Schristos if (strcmp (optarg, "32_64") != 0)
214775fd0b74Schristos fatal (_("Only -X 32_64 is supported"));
214875fd0b74Schristos break;
214975fd0b74Schristos
215075fd0b74Schristos case OPTION_TARGET: /* --target */
215175fd0b74Schristos target = optarg;
215275fd0b74Schristos break;
215375fd0b74Schristos
215475fd0b74Schristos case OPTION_PLUGIN: /* --plugin */
215575fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
215675fd0b74Schristos bfd_plugin_set_plugin (optarg);
215775fd0b74Schristos #else
215875fd0b74Schristos fatal (_("sorry - this program has been built without plugin support\n"));
215975fd0b74Schristos #endif
216075fd0b74Schristos break;
216175fd0b74Schristos
2162*e992f068Schristos case OPTION_IFUNC_CHARS:
2163*e992f068Schristos ifunc_type_chars = optarg;
2164*e992f068Schristos break;
2165*e992f068Schristos
216675fd0b74Schristos case 0: /* A long option that just sets a flag. */
216775fd0b74Schristos break;
216875fd0b74Schristos
216975fd0b74Schristos default:
217075fd0b74Schristos usage (stderr, 1);
217175fd0b74Schristos }
217275fd0b74Schristos }
217375fd0b74Schristos
217475fd0b74Schristos if (show_version)
217575fd0b74Schristos print_version ("nm");
217675fd0b74Schristos
217775fd0b74Schristos if (sort_by_size && undefined_only)
217875fd0b74Schristos {
217975fd0b74Schristos non_fatal (_("Using the --size-sort and --undefined-only options together"));
218075fd0b74Schristos non_fatal (_("will produce no output, since undefined symbols have no size."));
218175fd0b74Schristos return 0;
218275fd0b74Schristos }
218375fd0b74Schristos
218475fd0b74Schristos /* OK, all options now parsed. If no filename specified, do a.out. */
218575fd0b74Schristos if (optind == argc)
218675fd0b74Schristos return !display_file ("a.out");
218775fd0b74Schristos
218875fd0b74Schristos retval = 0;
218975fd0b74Schristos
219075fd0b74Schristos if (argc - optind > 1)
219175fd0b74Schristos filename_per_file = 1;
219275fd0b74Schristos
219375fd0b74Schristos /* We were given several filenames to do. */
219475fd0b74Schristos while (optind < argc)
219575fd0b74Schristos {
219675fd0b74Schristos PROGRESS (1);
219775fd0b74Schristos if (!display_file (argv[optind++]))
219875fd0b74Schristos retval++;
219975fd0b74Schristos }
220075fd0b74Schristos
220175fd0b74Schristos END_PROGRESS (program_name);
220275fd0b74Schristos
220375fd0b74Schristos exit (retval);
220475fd0b74Schristos return retval;
220575fd0b74Schristos }
2206