xref: /openbsd-src/gnu/usr.bin/binutils/binutils/nm.c (revision a95e6fec581636af2a82a971254c0719e6204648)
12159047fSniklas /* nm.c -- Describe symbol table of a rel file.
2b55d4692Sfgsch    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3c074d1c9Sdrahn    2001, 2002, 2003
4b305b0f1Sespie    Free Software Foundation, Inc.
52159047fSniklas 
62159047fSniklas    This file is part of GNU Binutils.
72159047fSniklas 
82159047fSniklas    This program is free software; you can redistribute it and/or modify
92159047fSniklas    it under the terms of the GNU General Public License as published by
102159047fSniklas    the Free Software Foundation; either version 2 of the License, or
112159047fSniklas    (at your option) any later version.
122159047fSniklas 
132159047fSniklas    This program is distributed in the hope that it will be useful,
142159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas    GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas    You should have received a copy of the GNU General Public License
192159047fSniklas    along with this program; if not, write to the Free Software
20b305b0f1Sespie    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21b305b0f1Sespie    02111-1307, USA.  */
222159047fSniklas 
232159047fSniklas #include "bfd.h"
242159047fSniklas #include "progress.h"
252159047fSniklas #include "bucomm.h"
26c074d1c9Sdrahn #include "budemang.h"
272159047fSniklas #include "getopt.h"
282159047fSniklas #include "aout/stab_gnu.h"
292159047fSniklas #include "aout/ranlib.h"
302159047fSniklas #include "demangle.h"
312159047fSniklas #include "libiberty.h"
32c074d1c9Sdrahn #include "elf-bfd.h"
33c074d1c9Sdrahn #include "elf/common.h"
342159047fSniklas 
352159047fSniklas /* When sorting by size, we use this structure to hold the size and a
362159047fSniklas    pointer to the minisymbol.  */
372159047fSniklas 
382159047fSniklas struct size_sym
392159047fSniklas {
40007c2a45Smiod   const void *minisym;
412159047fSniklas   bfd_vma size;
422159047fSniklas };
432159047fSniklas 
440c6d0228Sniklas /* When fetching relocs, we use this structure to pass information to
450c6d0228Sniklas    get_relocs.  */
460c6d0228Sniklas 
470c6d0228Sniklas struct get_relocs_info
480c6d0228Sniklas {
490c6d0228Sniklas   asection **secs;
500c6d0228Sniklas   arelent ***relocs;
510c6d0228Sniklas   long *relcount;
520c6d0228Sniklas   asymbol **syms;
530c6d0228Sniklas };
540c6d0228Sniklas 
55c074d1c9Sdrahn struct extended_symbol_info
56c074d1c9Sdrahn {
57c074d1c9Sdrahn   symbol_info *sinfo;
58c074d1c9Sdrahn   bfd_vma ssize;
59c074d1c9Sdrahn   elf_symbol_type *elfinfo;
60c074d1c9Sdrahn   /* FIXME: We should add more fields for Type, Line, Section.  */
61c074d1c9Sdrahn };
62c074d1c9Sdrahn #define SYM_NAME(sym)        (sym->sinfo->name)
63c074d1c9Sdrahn #define SYM_VALUE(sym)       (sym->sinfo->value)
64c074d1c9Sdrahn #define SYM_TYPE(sym)        (sym->sinfo->type)
65c074d1c9Sdrahn #define SYM_STAB_NAME(sym)   (sym->sinfo->stab_name)
66c074d1c9Sdrahn #define SYM_STAB_DESC(sym)   (sym->sinfo->stab_desc)
67c074d1c9Sdrahn #define SYM_STAB_OTHER(sym)  (sym->sinfo->stab_other)
68c074d1c9Sdrahn #define SYM_SIZE(sym) \
69c074d1c9Sdrahn   (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
70b305b0f1Sespie 
71007c2a45Smiod static void usage (FILE *, int);
72007c2a45Smiod static void set_print_radix (char *);
73007c2a45Smiod static void set_output_format (char *);
74007c2a45Smiod static void display_archive (bfd *);
75007c2a45Smiod static bfd_boolean display_file (char *);
76007c2a45Smiod static void display_rel_file (bfd *, bfd *);
77007c2a45Smiod static long filter_symbols (bfd *, bfd_boolean, void *, long, unsigned int);
78c074d1c9Sdrahn static long sort_symbols_by_size
79007c2a45Smiod   (bfd *, bfd_boolean, void *, long, unsigned int, struct size_sym **);
80c074d1c9Sdrahn static void print_symbols
81007c2a45Smiod   (bfd *, bfd_boolean, void *, long, unsigned int, bfd *);
82c074d1c9Sdrahn static void print_size_symbols
83007c2a45Smiod   (bfd *, bfd_boolean, struct size_sym *, long, bfd *);
84007c2a45Smiod static void print_symname (const char *, const char *, bfd *);
85007c2a45Smiod static void print_symbol (bfd *, asymbol *, bfd_vma ssize, bfd *);
86007c2a45Smiod static void print_symdef_entry (bfd *);
872159047fSniklas 
882159047fSniklas /* The sorting functions.  */
89007c2a45Smiod static int numeric_forward (const void *, const void *);
90007c2a45Smiod static int numeric_reverse (const void *, const void *);
91007c2a45Smiod static int non_numeric_forward (const void *, const void *);
92007c2a45Smiod static int non_numeric_reverse (const void *, const void *);
93007c2a45Smiod static int size_forward1 (const void *, const void *);
94007c2a45Smiod static int size_forward2 (const void *, const void *);
952159047fSniklas 
962159047fSniklas /* The output formatting functions.  */
97007c2a45Smiod static void print_object_filename_bsd (char *);
98007c2a45Smiod static void print_object_filename_sysv (char *);
99007c2a45Smiod static void print_object_filename_posix (char *);
100007c2a45Smiod static void print_archive_filename_bsd (char *);
101007c2a45Smiod static void print_archive_filename_sysv (char *);
102007c2a45Smiod static void print_archive_filename_posix (char *);
103007c2a45Smiod static void print_archive_member_bsd (char *, const char *);
104007c2a45Smiod static void print_archive_member_sysv (char *, const char *);
105007c2a45Smiod static void print_archive_member_posix (char *, const char *);
106007c2a45Smiod static void print_symbol_filename_bsd (bfd *, bfd *);
107007c2a45Smiod static void print_symbol_filename_sysv (bfd *, bfd *);
108007c2a45Smiod static void print_symbol_filename_posix (bfd *, bfd *);
109007c2a45Smiod static void print_value (bfd *, bfd_vma);
110007c2a45Smiod static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
111007c2a45Smiod static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
112007c2a45Smiod static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
113007c2a45Smiod static void get_relocs (bfd *, asection *, void *);
114007c2a45Smiod static const char * get_symbol_type (unsigned int);
1152159047fSniklas 
1162159047fSniklas /* Support for different output formats.  */
1172159047fSniklas struct output_fns
1182159047fSniklas   {
1192159047fSniklas     /* Print the name of an object file given on the command line.  */
120007c2a45Smiod     void (*print_object_filename) (char *);
1212159047fSniklas 
1222159047fSniklas     /* Print the name of an archive file given on the command line.  */
123007c2a45Smiod     void (*print_archive_filename) (char *);
1242159047fSniklas 
1252159047fSniklas     /* Print the name of an archive member file.  */
126007c2a45Smiod     void (*print_archive_member) (char *, const char *);
1272159047fSniklas 
1282159047fSniklas     /* Print the name of the file (and archive, if there is one)
1292159047fSniklas        containing a symbol.  */
130007c2a45Smiod     void (*print_symbol_filename) (bfd *, bfd *);
1312159047fSniklas 
1322159047fSniklas     /* Print a line of information about a symbol.  */
133007c2a45Smiod     void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
1342159047fSniklas   };
135c074d1c9Sdrahn 
1362159047fSniklas static struct output_fns formats[] =
1372159047fSniklas {
1382159047fSniklas   {print_object_filename_bsd,
1392159047fSniklas    print_archive_filename_bsd,
1402159047fSniklas    print_archive_member_bsd,
1412159047fSniklas    print_symbol_filename_bsd,
1422159047fSniklas    print_symbol_info_bsd},
1432159047fSniklas   {print_object_filename_sysv,
1442159047fSniklas    print_archive_filename_sysv,
1452159047fSniklas    print_archive_member_sysv,
1462159047fSniklas    print_symbol_filename_sysv,
1472159047fSniklas    print_symbol_info_sysv},
1482159047fSniklas   {print_object_filename_posix,
1492159047fSniklas    print_archive_filename_posix,
1502159047fSniklas    print_archive_member_posix,
1512159047fSniklas    print_symbol_filename_posix,
1522159047fSniklas    print_symbol_info_posix}
1532159047fSniklas };
1542159047fSniklas 
1552159047fSniklas /* Indices in `formats'.  */
1562159047fSniklas #define FORMAT_BSD 0
1572159047fSniklas #define FORMAT_SYSV 1
1582159047fSniklas #define FORMAT_POSIX 2
1592159047fSniklas #define FORMAT_DEFAULT FORMAT_BSD
1602159047fSniklas 
1612159047fSniklas /* The output format to use.  */
1622159047fSniklas static struct output_fns *format = &formats[FORMAT_DEFAULT];
1632159047fSniklas 
1642159047fSniklas /* Command options.  */
1652159047fSniklas 
1662159047fSniklas static int do_demangle = 0;	/* Pretty print C++ symbol names.  */
167c074d1c9Sdrahn static int external_only = 0;	/* Print external symbols only.  */
168c074d1c9Sdrahn static int defined_only = 0;	/* Print defined symbols only.  */
169c074d1c9Sdrahn static int no_sort = 0;		/* Don't sort; print syms in order found.  */
170c074d1c9Sdrahn static int print_debug_syms = 0;/* Print debugger-only symbols too.  */
171c074d1c9Sdrahn static int print_armap = 0;	/* Describe __.SYMDEF data in archive files.  */
172c074d1c9Sdrahn static int print_size = 0;	/* Print size of defined symbols.  */
173c074d1c9Sdrahn static int reverse_sort = 0;	/* Sort in downward(alpha or numeric) order.  */
174c074d1c9Sdrahn static int sort_numerically = 0;/* Sort in numeric rather than alpha order.  */
175c074d1c9Sdrahn static int sort_by_size = 0;	/* Sort by size of symbol.  */
176c074d1c9Sdrahn static int undefined_only = 0;	/* Print undefined symbols only.  */
177c074d1c9Sdrahn static int dynamic = 0;		/* Print dynamic symbols.  */
178c074d1c9Sdrahn static int show_version = 0;	/* Show the version number.  */
179c074d1c9Sdrahn static int show_stats = 0;	/* Show statistics.  */
180c074d1c9Sdrahn static int line_numbers = 0;	/* Print line numbers for symbols.  */
1812159047fSniklas 
1822159047fSniklas /* When to print the names of files.  Not mutually exclusive in SYSV format.  */
1832159047fSniklas static int filename_per_file = 0;	/* Once per file, on its own line.  */
1842159047fSniklas static int filename_per_symbol = 0;	/* Once per symbol, at start of line.  */
1852159047fSniklas 
1862159047fSniklas /* Print formats for printing a symbol value.  */
1872159047fSniklas #ifndef BFD64
1882159047fSniklas static char value_format[] = "%08lx";
1892159047fSniklas #else
1902159047fSniklas #if BFD_HOST_64BIT_LONG
1912159047fSniklas static char value_format[] = "%016lx";
1922159047fSniklas #else
1932159047fSniklas /* We don't use value_format for this case.  */
1942159047fSniklas #endif
1952159047fSniklas #endif
196c074d1c9Sdrahn #ifdef BFD64
197c074d1c9Sdrahn static int print_width = 16;
198c074d1c9Sdrahn #else
199c074d1c9Sdrahn static int print_width = 8;
200c074d1c9Sdrahn #endif
2012159047fSniklas static int print_radix = 16;
2022159047fSniklas /* Print formats for printing stab info.  */
2032159047fSniklas static char other_format[] = "%02x";
2042159047fSniklas static char desc_format[] = "%04x";
2052159047fSniklas 
206b305b0f1Sespie static char *target = NULL;
207b305b0f1Sespie 
208b305b0f1Sespie /* Used to cache the line numbers for a BFD.  */
209b305b0f1Sespie static bfd *lineno_cache_bfd;
210b305b0f1Sespie static bfd *lineno_cache_rel_bfd;
211b305b0f1Sespie 
212b305b0f1Sespie #define OPTION_TARGET 200
2132159047fSniklas 
2142159047fSniklas static struct option long_options[] =
2152159047fSniklas {
2162159047fSniklas   {"debug-syms", no_argument, &print_debug_syms, 1},
217b55d4692Sfgsch   {"demangle", optional_argument, 0, 'C'},
2182159047fSniklas   {"dynamic", no_argument, &dynamic, 1},
2192159047fSniklas   {"extern-only", no_argument, &external_only, 1},
2202159047fSniklas   {"format", required_argument, 0, 'f'},
2212159047fSniklas   {"help", no_argument, 0, 'h'},
2220c6d0228Sniklas   {"line-numbers", no_argument, 0, 'l'},
2232159047fSniklas   {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
2242159047fSniklas   {"no-demangle", no_argument, &do_demangle, 0},
2252159047fSniklas   {"no-sort", no_argument, &no_sort, 1},
2262159047fSniklas   {"numeric-sort", no_argument, &sort_numerically, 1},
2272159047fSniklas   {"portability", no_argument, 0, 'P'},
2282159047fSniklas   {"print-armap", no_argument, &print_armap, 1},
2292159047fSniklas   {"print-file-name", no_argument, 0, 'o'},
230c074d1c9Sdrahn   {"print-size", no_argument, 0, 'S'},
2312159047fSniklas   {"radix", required_argument, 0, 't'},
2322159047fSniklas   {"reverse-sort", no_argument, &reverse_sort, 1},
2332159047fSniklas   {"size-sort", no_argument, &sort_by_size, 1},
2342159047fSniklas   {"stats", no_argument, &show_stats, 1},
235b305b0f1Sespie   {"target", required_argument, 0, OPTION_TARGET},
236c88b1d6cSniklas   {"defined-only", no_argument, &defined_only, 1},
2372159047fSniklas   {"undefined-only", no_argument, &undefined_only, 1},
2382159047fSniklas   {"version", no_argument, &show_version, 1},
2392159047fSniklas   {0, no_argument, 0, 0}
2402159047fSniklas };
2412159047fSniklas 
242c074d1c9Sdrahn /* Some error-reporting functions.  */
2432159047fSniklas 
244b305b0f1Sespie static void
usage(FILE * stream,int status)245007c2a45Smiod usage (FILE *stream, int status)
2462159047fSniklas {
247c074d1c9Sdrahn   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
248c074d1c9Sdrahn   fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
249c074d1c9Sdrahn   fprintf (stream, _(" The options are:\n\
2506978ef19Sespie   -a, --debug-syms       Display debugger-only symbols\n\
2516978ef19Sespie   -A, --print-file-name  Print name of the input file before every symbol\n\
2526978ef19Sespie   -B                     Same as --format=bsd\n\
253b55d4692Sfgsch   -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
254b55d4692Sfgsch                           The STYLE, if specified, can be `auto' (the default),\n\
255c074d1c9Sdrahn                           `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
256c074d1c9Sdrahn                           or `gnat'\n\
2576978ef19Sespie       --no-demangle      Do not demangle low-level symbol names\n\
2586978ef19Sespie   -D, --dynamic          Display dynamic symbols instead of normal symbols\n\
2596978ef19Sespie       --defined-only     Display only defined symbols\n\
2606978ef19Sespie   -e                     (ignored)\n\
2616978ef19Sespie   -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',\n\
2626978ef19Sespie                            `sysv' or `posix'.  The default is `bsd'\n\
2636978ef19Sespie   -g, --extern-only      Display only external symbols\n\
2646978ef19Sespie   -l, --line-numbers     Use debugging information to find a filename and\n\
2656978ef19Sespie                            line number for each symbol\n\
2666978ef19Sespie   -n, --numeric-sort     Sort symbols numerically by address\n\
2676978ef19Sespie   -o                     Same as -A\n\
2686978ef19Sespie   -p, --no-sort          Do not sort the symbols\n\
2696978ef19Sespie   -P, --portability      Same as --format=posix\n\
2706978ef19Sespie   -r, --reverse-sort     Reverse the sense of the sort\n\
271c074d1c9Sdrahn   -S, --print-size       Print size of defined symbols\n\
2726978ef19Sespie   -s, --print-armap      Include index for symbols from archive members\n\
2736978ef19Sespie       --size-sort        Sort symbols by size\n\
2746978ef19Sespie   -t, --radix=RADIX      Use RADIX for printing symbol values\n\
2756978ef19Sespie       --target=BFDNAME   Specify the target object format as BFDNAME\n\
2766978ef19Sespie   -u, --undefined-only   Display only undefined symbols\n\
277b55d4692Sfgsch   -X 32_64               (ignored)\n\
278c074d1c9Sdrahn   -h, --help             Display this information\n\
279c074d1c9Sdrahn   -V, --version          Display this program's version number\n\
2806978ef19Sespie \n"));
2812159047fSniklas   list_supported_targets (program_name, stream);
282e93f7393Sniklas   if (status == 0)
2836978ef19Sespie     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
2842159047fSniklas   exit (status);
2852159047fSniklas }
2862159047fSniklas 
2872159047fSniklas /* Set the radix for the symbol value and size according to RADIX.  */
2882159047fSniklas 
289b305b0f1Sespie static void
set_print_radix(char * radix)290007c2a45Smiod set_print_radix (char *radix)
2912159047fSniklas {
2922159047fSniklas   switch (*radix)
2932159047fSniklas     {
2942159047fSniklas     case 'x':
2952159047fSniklas       break;
2962159047fSniklas     case 'd':
2972159047fSniklas     case 'o':
2982159047fSniklas       if (*radix == 'd')
2992159047fSniklas 	print_radix = 10;
3002159047fSniklas       else
3012159047fSniklas 	print_radix = 8;
3022159047fSniklas #ifndef BFD64
3032159047fSniklas       value_format[4] = *radix;
3042159047fSniklas #else
3052159047fSniklas #if BFD_HOST_64BIT_LONG
3062159047fSniklas       value_format[5] = *radix;
3072159047fSniklas #else
3082159047fSniklas       /* This case requires special handling for octal and decimal
3092159047fSniklas          printing.  */
3102159047fSniklas #endif
3112159047fSniklas #endif
3122159047fSniklas       other_format[3] = desc_format[3] = *radix;
3132159047fSniklas       break;
3142159047fSniklas     default:
315b305b0f1Sespie       fatal (_("%s: invalid radix"), radix);
3162159047fSniklas     }
3172159047fSniklas }
3182159047fSniklas 
319b305b0f1Sespie static void
set_output_format(char * f)320007c2a45Smiod set_output_format (char *f)
3212159047fSniklas {
3222159047fSniklas   int i;
3232159047fSniklas 
3242159047fSniklas   switch (*f)
3252159047fSniklas     {
3262159047fSniklas     case 'b':
3272159047fSniklas     case 'B':
3282159047fSniklas       i = FORMAT_BSD;
3292159047fSniklas       break;
3302159047fSniklas     case 'p':
3312159047fSniklas     case 'P':
3322159047fSniklas       i = FORMAT_POSIX;
3332159047fSniklas       break;
3342159047fSniklas     case 's':
3352159047fSniklas     case 'S':
3362159047fSniklas       i = FORMAT_SYSV;
3372159047fSniklas       break;
3382159047fSniklas     default:
339b305b0f1Sespie       fatal (_("%s: invalid output format"), f);
3402159047fSniklas     }
3412159047fSniklas   format = &formats[i];
3422159047fSniklas }
3432159047fSniklas 
344007c2a45Smiod int main (int, char **);
345c074d1c9Sdrahn 
3462159047fSniklas int
main(int argc,char ** argv)347007c2a45Smiod main (int argc, char **argv)
3482159047fSniklas {
3492159047fSniklas   int c;
3502159047fSniklas   int retval;
3512159047fSniklas 
352b305b0f1Sespie #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
353b305b0f1Sespie   setlocale (LC_MESSAGES, "");
354b305b0f1Sespie #endif
355c074d1c9Sdrahn #if defined (HAVE_SETLOCALE)
356c074d1c9Sdrahn   setlocale (LC_CTYPE, "");
357c074d1c9Sdrahn   setlocale (LC_COLLATE, "");
358c074d1c9Sdrahn #endif
359b305b0f1Sespie   bindtextdomain (PACKAGE, LOCALEDIR);
360b305b0f1Sespie   textdomain (PACKAGE);
361b305b0f1Sespie 
3622159047fSniklas   program_name = *argv;
3632159047fSniklas   xmalloc_set_program_name (program_name);
3642159047fSniklas 
3652159047fSniklas   START_PROGRESS (program_name, 0);
3662159047fSniklas 
367*a95e6fecStobiasu   expandargv (&argc, &argv);
368*a95e6fecStobiasu 
3692159047fSniklas   bfd_init ();
370b305b0f1Sespie   set_default_bfd_target ();
3712159047fSniklas 
372c074d1c9Sdrahn   while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
373b55d4692Sfgsch 			   long_options, (int *) 0)) != EOF)
3742159047fSniklas     {
3752159047fSniklas       switch (c)
3762159047fSniklas 	{
3772159047fSniklas 	case 'a':
3782159047fSniklas 	  print_debug_syms = 1;
3792159047fSniklas 	  break;
3802159047fSniklas 	case 'A':
3812159047fSniklas 	case 'o':
3822159047fSniklas 	  filename_per_symbol = 1;
3832159047fSniklas 	  break;
3842159047fSniklas 	case 'B':		/* For MIPS compatibility.  */
3852159047fSniklas 	  set_output_format ("bsd");
3862159047fSniklas 	  break;
3872159047fSniklas 	case 'C':
3882159047fSniklas 	  do_demangle = 1;
389b55d4692Sfgsch 	  if (optarg != NULL)
390b55d4692Sfgsch 	    {
391b55d4692Sfgsch 	      enum demangling_styles style;
392b55d4692Sfgsch 
393b55d4692Sfgsch 	      style = cplus_demangle_name_to_style (optarg);
394b55d4692Sfgsch 	      if (style == unknown_demangling)
395b55d4692Sfgsch 		fatal (_("unknown demangling style `%s'"),
396b55d4692Sfgsch 		       optarg);
397b55d4692Sfgsch 
398b55d4692Sfgsch 	      cplus_demangle_set_style (style);
399b55d4692Sfgsch 	    }
4002159047fSniklas 	  break;
4012159047fSniklas 	case 'D':
4022159047fSniklas 	  dynamic = 1;
4032159047fSniklas 	  break;
4042159047fSniklas 	case 'e':
4052159047fSniklas 	  /* Ignored for HP/UX compatibility.  */
4062159047fSniklas 	  break;
4072159047fSniklas 	case 'f':
4082159047fSniklas 	  set_output_format (optarg);
4092159047fSniklas 	  break;
4102159047fSniklas 	case 'g':
4112159047fSniklas 	  external_only = 1;
4122159047fSniklas 	  break;
413c074d1c9Sdrahn 	case 'H':
4142159047fSniklas 	case 'h':
4152159047fSniklas 	  usage (stdout, 0);
4160c6d0228Sniklas 	case 'l':
4170c6d0228Sniklas 	  line_numbers = 1;
4180c6d0228Sniklas 	  break;
4192159047fSniklas 	case 'n':
4202159047fSniklas 	case 'v':
4212159047fSniklas 	  sort_numerically = 1;
4222159047fSniklas 	  break;
4232159047fSniklas 	case 'p':
4242159047fSniklas 	  no_sort = 1;
4252159047fSniklas 	  break;
4262159047fSniklas 	case 'P':
4272159047fSniklas 	  set_output_format ("posix");
4282159047fSniklas 	  break;
4292159047fSniklas 	case 'r':
4302159047fSniklas 	  reverse_sort = 1;
4312159047fSniklas 	  break;
4322159047fSniklas 	case 's':
4332159047fSniklas 	  print_armap = 1;
4342159047fSniklas 	  break;
435c074d1c9Sdrahn 	case 'S':
436c074d1c9Sdrahn 	  print_size = 1;
437c074d1c9Sdrahn 	  break;
4382159047fSniklas 	case 't':
4392159047fSniklas 	  set_print_radix (optarg);
4402159047fSniklas 	  break;
4412159047fSniklas 	case 'u':
4422159047fSniklas 	  undefined_only = 1;
4432159047fSniklas 	  break;
4442159047fSniklas 	case 'V':
4452159047fSniklas 	  show_version = 1;
4462159047fSniklas 	  break;
447b55d4692Sfgsch 	case 'X':
448b55d4692Sfgsch 	  /* Ignored for (partial) AIX compatibility.  On AIX, the
449007c2a45Smiod 	     argument has values 32, 64, or 32_64, and specifies that
450b55d4692Sfgsch 	     only 32-bit, only 64-bit, or both kinds of objects should
451b55d4692Sfgsch 	     be examined.  The default is 32.  So plain AIX nm on a
452b55d4692Sfgsch 	     library archive with both kinds of objects will ignore
453b55d4692Sfgsch 	     the 64-bit ones.  For GNU nm, the default is and always
454b55d4692Sfgsch 	     has been -X 32_64, and other options are not supported.  */
455b55d4692Sfgsch 	  if (strcmp (optarg, "32_64") != 0)
456b55d4692Sfgsch 	    fatal (_("Only -X 32_64 is supported"));
457b55d4692Sfgsch 	  break;
4582159047fSniklas 
459b305b0f1Sespie 	case OPTION_TARGET:	/* --target */
4602159047fSniklas 	  target = optarg;
4612159047fSniklas 	  break;
4622159047fSniklas 
4632159047fSniklas 	case 0:		/* A long option that just sets a flag.  */
4642159047fSniklas 	  break;
4652159047fSniklas 
4662159047fSniklas 	default:
4672159047fSniklas 	  usage (stderr, 1);
4682159047fSniklas 	}
4692159047fSniklas     }
4702159047fSniklas 
4712159047fSniklas   if (show_version)
472e93f7393Sniklas     print_version ("nm");
4732159047fSniklas 
474c074d1c9Sdrahn   if (sort_by_size && undefined_only)
475c074d1c9Sdrahn     {
476c074d1c9Sdrahn       non_fatal (_("Using the --size-sort and --undefined-only options together"));
477c074d1c9Sdrahn       non_fatal (_("will produce no output, since undefined symbols have no size."));
478c074d1c9Sdrahn       return 0;
479c074d1c9Sdrahn     }
480c074d1c9Sdrahn 
4812159047fSniklas   /* OK, all options now parsed.  If no filename specified, do a.out.  */
4822159047fSniklas   if (optind == argc)
4832159047fSniklas     return !display_file ("a.out");
4842159047fSniklas 
4852159047fSniklas   retval = 0;
4862159047fSniklas 
4872159047fSniklas   if (argc - optind > 1)
4882159047fSniklas     filename_per_file = 1;
4892159047fSniklas 
4902159047fSniklas   /* We were given several filenames to do.  */
4912159047fSniklas   while (optind < argc)
4922159047fSniklas     {
4932159047fSniklas       PROGRESS (1);
4942159047fSniklas       if (!display_file (argv[optind++]))
4952159047fSniklas 	retval++;
4962159047fSniklas     }
4972159047fSniklas 
4982159047fSniklas   END_PROGRESS (program_name);
4992159047fSniklas 
5002159047fSniklas #ifdef HAVE_SBRK
5012159047fSniklas   if (show_stats)
5022159047fSniklas     {
5032159047fSniklas       char *lim = (char *) sbrk (0);
5042159047fSniklas 
505b305b0f1Sespie       non_fatal (_("data size %ld"), (long) (lim - (char *) &environ));
5062159047fSniklas     }
5072159047fSniklas #endif
5082159047fSniklas 
5092159047fSniklas   exit (retval);
5102159047fSniklas   return retval;
5112159047fSniklas }
5122159047fSniklas 
513c074d1c9Sdrahn static const char *
get_symbol_type(unsigned int type)514007c2a45Smiod get_symbol_type (unsigned int type)
515c074d1c9Sdrahn {
516c074d1c9Sdrahn   static char buff [32];
517c074d1c9Sdrahn 
518c074d1c9Sdrahn   switch (type)
519c074d1c9Sdrahn     {
520c074d1c9Sdrahn     case STT_NOTYPE:   return "NOTYPE";
521c074d1c9Sdrahn     case STT_OBJECT:   return "OBJECT";
522c074d1c9Sdrahn     case STT_FUNC:     return "FUNC";
523c074d1c9Sdrahn     case STT_SECTION:  return "SECTION";
524c074d1c9Sdrahn     case STT_FILE:     return "FILE";
525c074d1c9Sdrahn     case STT_COMMON:   return "COMMON";
526c074d1c9Sdrahn     case STT_TLS:      return "TLS";
527c074d1c9Sdrahn     default:
528c074d1c9Sdrahn       if (type >= STT_LOPROC && type <= STT_HIPROC)
529c074d1c9Sdrahn 	sprintf (buff, _("<processor specific>: %d"), type);
530c074d1c9Sdrahn       else if (type >= STT_LOOS && type <= STT_HIOS)
531c074d1c9Sdrahn 	sprintf (buff, _("<OS specific>: %d"), type);
532c074d1c9Sdrahn       else
533c074d1c9Sdrahn 	sprintf (buff, _("<unknown>: %d"), type);
534c074d1c9Sdrahn       return buff;
535c074d1c9Sdrahn     }
536c074d1c9Sdrahn }
537c074d1c9Sdrahn 
5382159047fSniklas static void
display_archive(bfd * file)539007c2a45Smiod display_archive (bfd *file)
5402159047fSniklas {
5412159047fSniklas   bfd *arfile = NULL;
5422159047fSniklas   bfd *last_arfile = NULL;
5432159047fSniklas   char **matching;
5442159047fSniklas 
5452159047fSniklas   (*format->print_archive_filename) (bfd_get_filename (file));
5462159047fSniklas 
5472159047fSniklas   if (print_armap)
5482159047fSniklas     print_symdef_entry (file);
5492159047fSniklas 
5502159047fSniklas   for (;;)
5512159047fSniklas     {
5522159047fSniklas       PROGRESS (1);
5532159047fSniklas 
5542159047fSniklas       arfile = bfd_openr_next_archived_file (file, arfile);
5552159047fSniklas 
5562159047fSniklas       if (arfile == NULL)
5572159047fSniklas 	{
5582159047fSniklas 	  if (bfd_get_error () != bfd_error_no_more_archived_files)
5592159047fSniklas 	    bfd_fatal (bfd_get_filename (file));
5602159047fSniklas 	  break;
5612159047fSniklas 	}
5622159047fSniklas 
5632159047fSniklas       if (bfd_check_format_matches (arfile, bfd_object, &matching))
5642159047fSniklas 	{
565c074d1c9Sdrahn 	  char buf[30];
566c074d1c9Sdrahn 
567c074d1c9Sdrahn 	  bfd_sprintf_vma (arfile, buf, (bfd_vma) -1);
568c074d1c9Sdrahn 	  print_width = strlen (buf);
5692159047fSniklas 	  (*format->print_archive_member) (bfd_get_filename (file),
5702159047fSniklas 					   bfd_get_filename (arfile));
5712159047fSniklas 	  display_rel_file (arfile, file);
5722159047fSniklas 	}
5732159047fSniklas       else
5742159047fSniklas 	{
5752159047fSniklas 	  bfd_nonfatal (bfd_get_filename (arfile));
5762159047fSniklas 	  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
5772159047fSniklas 	    {
5782159047fSniklas 	      list_matching_formats (matching);
5792159047fSniklas 	      free (matching);
5802159047fSniklas 	    }
5812159047fSniklas 	}
5822159047fSniklas 
5832159047fSniklas       if (last_arfile != NULL)
584b305b0f1Sespie 	{
5852159047fSniklas 	  bfd_close (last_arfile);
586b305b0f1Sespie 	  lineno_cache_bfd = NULL;
587b305b0f1Sespie 	  lineno_cache_rel_bfd = NULL;
588b305b0f1Sespie 	}
5892159047fSniklas       last_arfile = arfile;
5902159047fSniklas     }
5912159047fSniklas 
5922159047fSniklas   if (last_arfile != NULL)
593b305b0f1Sespie     {
5942159047fSniklas       bfd_close (last_arfile);
595b305b0f1Sespie       lineno_cache_bfd = NULL;
596b305b0f1Sespie       lineno_cache_rel_bfd = NULL;
597b305b0f1Sespie     }
5982159047fSniklas }
5992159047fSniklas 
600c074d1c9Sdrahn static bfd_boolean
display_file(char * filename)601007c2a45Smiod display_file (char *filename)
6022159047fSniklas {
603c074d1c9Sdrahn   bfd_boolean retval = TRUE;
6042159047fSniklas   bfd *file;
6052159047fSniklas   char **matching;
6062159047fSniklas 
607007c2a45Smiod   if (get_file_size (filename) < 1)
608007c2a45Smiod     return FALSE;
609007c2a45Smiod 
6102159047fSniklas   file = bfd_openr (filename, target);
6112159047fSniklas   if (file == NULL)
6122159047fSniklas     {
6132159047fSniklas       bfd_nonfatal (filename);
614c074d1c9Sdrahn       return FALSE;
6152159047fSniklas     }
6162159047fSniklas 
6172159047fSniklas   if (bfd_check_format (file, bfd_archive))
6182159047fSniklas     {
6192159047fSniklas       display_archive (file);
6202159047fSniklas     }
6212159047fSniklas   else if (bfd_check_format_matches (file, bfd_object, &matching))
6222159047fSniklas     {
623c074d1c9Sdrahn       char buf[30];
624c074d1c9Sdrahn 
625c074d1c9Sdrahn       bfd_sprintf_vma (file, buf, (bfd_vma) -1);
626c074d1c9Sdrahn       print_width = strlen (buf);
6272159047fSniklas       (*format->print_object_filename) (filename);
6282159047fSniklas       display_rel_file (file, NULL);
6292159047fSniklas     }
6302159047fSniklas   else
6312159047fSniklas     {
6322159047fSniklas       bfd_nonfatal (filename);
6332159047fSniklas       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
6342159047fSniklas 	{
6352159047fSniklas 	  list_matching_formats (matching);
6362159047fSniklas 	  free (matching);
6372159047fSniklas 	}
638c074d1c9Sdrahn       retval = FALSE;
6392159047fSniklas     }
6402159047fSniklas 
641c074d1c9Sdrahn   if (!bfd_close (file))
6422159047fSniklas     bfd_fatal (filename);
6432159047fSniklas 
644b305b0f1Sespie   lineno_cache_bfd = NULL;
645b305b0f1Sespie   lineno_cache_rel_bfd = NULL;
646b305b0f1Sespie 
6472159047fSniklas   return retval;
6482159047fSniklas }
6492159047fSniklas 
6502159047fSniklas /* These globals are used to pass information into the sorting
6512159047fSniklas    routines.  */
6522159047fSniklas static bfd *sort_bfd;
653c074d1c9Sdrahn static bfd_boolean sort_dynamic;
6542159047fSniklas static asymbol *sort_x;
6552159047fSniklas static asymbol *sort_y;
6562159047fSniklas 
6572159047fSniklas /* Symbol-sorting predicates */
6582159047fSniklas #define valueof(x) ((x)->section->vma + (x)->value)
6592159047fSniklas 
6602159047fSniklas /* Numeric sorts.  Undefined symbols are always considered "less than"
6612159047fSniklas    defined symbols with zero values.  Common symbols are not treated
6622159047fSniklas    specially -- i.e., their sizes are used as their "values".  */
6632159047fSniklas 
6642159047fSniklas static int
numeric_forward(const void * P_x,const void * P_y)665007c2a45Smiod numeric_forward (const void *P_x, const void *P_y)
6662159047fSniklas {
6672159047fSniklas   asymbol *x, *y;
6682159047fSniklas   asection *xs, *ys;
6692159047fSniklas 
6702159047fSniklas   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
6712159047fSniklas   y =  bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
6722159047fSniklas   if (x == NULL || y == NULL)
6732159047fSniklas     bfd_fatal (bfd_get_filename (sort_bfd));
6742159047fSniklas 
6752159047fSniklas   xs = bfd_get_section (x);
6762159047fSniklas   ys = bfd_get_section (y);
6772159047fSniklas 
6782159047fSniklas   if (bfd_is_und_section (xs))
6792159047fSniklas     {
6802159047fSniklas       if (! bfd_is_und_section (ys))
6812159047fSniklas 	return -1;
6822159047fSniklas     }
6832159047fSniklas   else if (bfd_is_und_section (ys))
6842159047fSniklas     return 1;
6852159047fSniklas   else if (valueof (x) != valueof (y))
6862159047fSniklas     return valueof (x) < valueof (y) ? -1 : 1;
6872159047fSniklas 
6882159047fSniklas   return non_numeric_forward (P_x, P_y);
6892159047fSniklas }
6902159047fSniklas 
6912159047fSniklas static int
numeric_reverse(const void * x,const void * y)692007c2a45Smiod numeric_reverse (const void *x, const void *y)
6932159047fSniklas {
6942159047fSniklas   return - numeric_forward (x, y);
6952159047fSniklas }
6962159047fSniklas 
6972159047fSniklas static int
non_numeric_forward(const void * P_x,const void * P_y)698007c2a45Smiod non_numeric_forward (const void *P_x, const void *P_y)
6992159047fSniklas {
7002159047fSniklas   asymbol *x, *y;
7012159047fSniklas   const char *xn, *yn;
7022159047fSniklas 
7032159047fSniklas   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
7042159047fSniklas   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
7052159047fSniklas   if (x == NULL || y == NULL)
7062159047fSniklas     bfd_fatal (bfd_get_filename (sort_bfd));
7072159047fSniklas 
7082159047fSniklas   xn = bfd_asymbol_name (x);
7092159047fSniklas   yn = bfd_asymbol_name (y);
7102159047fSniklas 
711c074d1c9Sdrahn   if (yn == NULL)
712c074d1c9Sdrahn     return xn != NULL;
713c074d1c9Sdrahn   if (xn == NULL)
714c074d1c9Sdrahn     return -1;
715c074d1c9Sdrahn 
716c074d1c9Sdrahn #ifdef HAVE_STRCOLL
717c074d1c9Sdrahn   /* Solaris 2.5 has a bug in strcoll.
718c074d1c9Sdrahn      strcoll returns invalid values when confronted with empty strings.  */
719c074d1c9Sdrahn   if (*yn == '\0')
720c074d1c9Sdrahn     return *xn != '\0';
721c074d1c9Sdrahn   if (*xn == '\0')
722c074d1c9Sdrahn     return -1;
723c074d1c9Sdrahn 
724c074d1c9Sdrahn   return strcoll (xn, yn);
725c074d1c9Sdrahn #else
726c074d1c9Sdrahn   return strcmp (xn, yn);
727c074d1c9Sdrahn #endif
7282159047fSniklas }
7292159047fSniklas 
7302159047fSniklas static int
non_numeric_reverse(const void * x,const void * y)731007c2a45Smiod non_numeric_reverse (const void *x, const void *y)
7322159047fSniklas {
7332159047fSniklas   return - non_numeric_forward (x, y);
7342159047fSniklas }
7352159047fSniklas 
736007c2a45Smiod static int (*(sorters[2][2])) (const void *, const void *) =
7372159047fSniklas {
7382159047fSniklas   { non_numeric_forward, non_numeric_reverse },
7392159047fSniklas   { numeric_forward, numeric_reverse }
7402159047fSniklas };
7412159047fSniklas 
7422159047fSniklas /* This sort routine is used by sort_symbols_by_size.  It is similar
7432159047fSniklas    to numeric_forward, but when symbols have the same value it sorts
7442159047fSniklas    by section VMA.  This simplifies the sort_symbols_by_size code
7452159047fSniklas    which handles symbols at the end of sections.  Also, this routine
7462159047fSniklas    tries to sort file names before other symbols with the same value.
7472159047fSniklas    That will make the file name have a zero size, which will make
7482159047fSniklas    sort_symbols_by_size choose the non file name symbol, leading to
7492159047fSniklas    more meaningful output.  For similar reasons, this code sorts
7502159047fSniklas    gnu_compiled_* and gcc2_compiled before other symbols with the same
7512159047fSniklas    value.  */
7522159047fSniklas 
7532159047fSniklas static int
size_forward1(const void * P_x,const void * P_y)754007c2a45Smiod size_forward1 (const void *P_x, const void *P_y)
7552159047fSniklas {
7562159047fSniklas   asymbol *x, *y;
7572159047fSniklas   asection *xs, *ys;
7582159047fSniklas   const char *xn, *yn;
7592159047fSniklas   size_t xnl, ynl;
7602159047fSniklas   int xf, yf;
7612159047fSniklas 
7622159047fSniklas   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
7632159047fSniklas   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
7642159047fSniklas   if (x == NULL || y == NULL)
7652159047fSniklas     bfd_fatal (bfd_get_filename (sort_bfd));
7662159047fSniklas 
7672159047fSniklas   xs = bfd_get_section (x);
7682159047fSniklas   ys = bfd_get_section (y);
7692159047fSniklas 
7702159047fSniklas   if (bfd_is_und_section (xs))
7712159047fSniklas     abort ();
7722159047fSniklas   if (bfd_is_und_section (ys))
7732159047fSniklas     abort ();
7742159047fSniklas 
7752159047fSniklas   if (valueof (x) != valueof (y))
7762159047fSniklas     return valueof (x) < valueof (y) ? -1 : 1;
7772159047fSniklas 
7782159047fSniklas   if (xs->vma != ys->vma)
7792159047fSniklas     return xs->vma < ys->vma ? -1 : 1;
7802159047fSniklas 
7812159047fSniklas   xn = bfd_asymbol_name (x);
7822159047fSniklas   yn = bfd_asymbol_name (y);
7832159047fSniklas   xnl = strlen (xn);
7842159047fSniklas   ynl = strlen (yn);
7852159047fSniklas 
7862159047fSniklas   /* The symbols gnu_compiled and gcc2_compiled convey even less
7872159047fSniklas      information than the file name, so sort them out first.  */
7882159047fSniklas 
7892159047fSniklas   xf = (strstr (xn, "gnu_compiled") != NULL
7902159047fSniklas 	|| strstr (xn, "gcc2_compiled") != NULL);
7912159047fSniklas   yf = (strstr (yn, "gnu_compiled") != NULL
7922159047fSniklas 	|| strstr (yn, "gcc2_compiled") != NULL);
7932159047fSniklas 
7942159047fSniklas   if (xf && ! yf)
7952159047fSniklas     return -1;
7962159047fSniklas   if (! xf && yf)
7972159047fSniklas     return 1;
7982159047fSniklas 
7992159047fSniklas   /* We use a heuristic for the file name.  It may not work on non
8002159047fSniklas      Unix systems, but it doesn't really matter; the only difference
8012159047fSniklas      is precisely which symbol names get printed.  */
8022159047fSniklas 
8032159047fSniklas #define file_symbol(s, sn, snl)			\
8042159047fSniklas   (((s)->flags & BSF_FILE) != 0			\
8052159047fSniklas    || ((sn)[(snl) - 2] == '.'			\
8062159047fSniklas        && ((sn)[(snl) - 1] == 'o'		\
8072159047fSniklas 	   || (sn)[(snl) - 1] == 'a')))
8082159047fSniklas 
8092159047fSniklas   xf = file_symbol (x, xn, xnl);
8102159047fSniklas   yf = file_symbol (y, yn, ynl);
8112159047fSniklas 
8122159047fSniklas   if (xf && ! yf)
8132159047fSniklas     return -1;
8142159047fSniklas   if (! xf && yf)
8152159047fSniklas     return 1;
8162159047fSniklas 
8172159047fSniklas   return non_numeric_forward (P_x, P_y);
8182159047fSniklas }
8192159047fSniklas 
8202159047fSniklas /* This sort routine is used by sort_symbols_by_size.  It is sorting
8212159047fSniklas    an array of size_sym structures into size order.  */
8222159047fSniklas 
8232159047fSniklas static int
size_forward2(const void * P_x,const void * P_y)824007c2a45Smiod size_forward2 (const void *P_x, const void *P_y)
8252159047fSniklas {
8262159047fSniklas   const struct size_sym *x = (const struct size_sym *) P_x;
8272159047fSniklas   const struct size_sym *y = (const struct size_sym *) P_y;
8282159047fSniklas 
8292159047fSniklas   if (x->size < y->size)
8302159047fSniklas     return reverse_sort ? 1 : -1;
8312159047fSniklas   else if (x->size > y->size)
8322159047fSniklas     return reverse_sort ? -1 : 1;
8332159047fSniklas   else
8342159047fSniklas     return sorters[0][reverse_sort] (x->minisym, y->minisym);
8352159047fSniklas }
8362159047fSniklas 
837c074d1c9Sdrahn /* Sort the symbols by size.  ELF provides a size but for other formats
838c074d1c9Sdrahn    we have to make a guess by assuming that the difference between the
839c074d1c9Sdrahn    address of a symbol and the address of the next higher symbol is the
840c074d1c9Sdrahn    size.  */
8412159047fSniklas 
8422159047fSniklas static long
sort_symbols_by_size(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,struct size_sym ** symsizesp)843007c2a45Smiod sort_symbols_by_size (bfd *abfd, bfd_boolean dynamic, void *minisyms,
844007c2a45Smiod 		      long symcount, unsigned int size,
845007c2a45Smiod 		      struct size_sym **symsizesp)
8462159047fSniklas {
8472159047fSniklas   struct size_sym *symsizes;
8482159047fSniklas   bfd_byte *from, *fromend;
849b305b0f1Sespie   asymbol *sym = NULL;
8502159047fSniklas   asymbol *store_sym, *store_next;
8512159047fSniklas 
8522159047fSniklas   qsort (minisyms, symcount, size, size_forward1);
8532159047fSniklas 
8542159047fSniklas   /* We are going to return a special set of symbols and sizes to
8552159047fSniklas      print.  */
8562159047fSniklas   symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym));
8572159047fSniklas   *symsizesp = symsizes;
8582159047fSniklas 
8592159047fSniklas   /* Note that filter_symbols has already removed all absolute and
8602159047fSniklas      undefined symbols.  Here we remove all symbols whose size winds
8612159047fSniklas      up as zero.  */
8622159047fSniklas   from = (bfd_byte *) minisyms;
8632159047fSniklas   fromend = from + symcount * size;
8642159047fSniklas 
8652159047fSniklas   store_sym = sort_x;
8662159047fSniklas   store_next = sort_y;
8672159047fSniklas 
8682159047fSniklas   if (from < fromend)
8692159047fSniklas     {
870007c2a45Smiod       sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from,
8712159047fSniklas 				      store_sym);
8722159047fSniklas       if (sym == NULL)
8732159047fSniklas 	bfd_fatal (bfd_get_filename (abfd));
8742159047fSniklas     }
8752159047fSniklas 
8762159047fSniklas   for (; from < fromend; from += size)
8772159047fSniklas     {
8782159047fSniklas       asymbol *next;
8792159047fSniklas       asection *sec;
8802159047fSniklas       bfd_vma sz;
8812159047fSniklas       asymbol *temp;
8822159047fSniklas 
8832159047fSniklas       if (from + size < fromend)
8842159047fSniklas 	{
8852159047fSniklas 	  next = bfd_minisymbol_to_symbol (abfd,
8862159047fSniklas 					   dynamic,
887007c2a45Smiod 					   (const void *) (from + size),
8882159047fSniklas 					   store_next);
8892159047fSniklas 	  if (next == NULL)
8902159047fSniklas 	    bfd_fatal (bfd_get_filename (abfd));
8912159047fSniklas 	}
8920c6d0228Sniklas       else
8930c6d0228Sniklas 	next = NULL;
8942159047fSniklas 
8952159047fSniklas       sec = bfd_get_section (sym);
8962159047fSniklas 
897c074d1c9Sdrahn       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
898c074d1c9Sdrahn 	sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
899c074d1c9Sdrahn       else if (bfd_is_com_section (sec))
9002159047fSniklas 	sz = sym->value;
9012159047fSniklas       else
9022159047fSniklas 	{
9032159047fSniklas 	  if (from + size < fromend
9042159047fSniklas 	      && sec == bfd_get_section (next))
9052159047fSniklas 	    sz = valueof (next) - valueof (sym);
9062159047fSniklas 	  else
9072159047fSniklas 	    sz = (bfd_get_section_vma (abfd, sec)
9082159047fSniklas 		  + bfd_section_size (abfd, sec)
9092159047fSniklas 		  - valueof (sym));
9102159047fSniklas 	}
9112159047fSniklas 
9122159047fSniklas       if (sz != 0)
9132159047fSniklas 	{
914007c2a45Smiod 	  symsizes->minisym = (const void *) from;
9152159047fSniklas 	  symsizes->size = sz;
9162159047fSniklas 	  ++symsizes;
9172159047fSniklas 	}
9182159047fSniklas 
9192159047fSniklas       sym = next;
9202159047fSniklas 
9212159047fSniklas       temp = store_sym;
9222159047fSniklas       store_sym = store_next;
9232159047fSniklas       store_next = temp;
9242159047fSniklas     }
9252159047fSniklas 
9262159047fSniklas   symcount = symsizes - *symsizesp;
9272159047fSniklas 
9282159047fSniklas   /* We must now sort again by size.  */
929007c2a45Smiod   qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
9302159047fSniklas 
9312159047fSniklas   return symcount;
9322159047fSniklas }
9332159047fSniklas 
9342159047fSniklas /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.  */
9352159047fSniklas 
9362159047fSniklas static void
display_rel_file(bfd * abfd,bfd * archive_bfd)937007c2a45Smiod display_rel_file (bfd *abfd, bfd *archive_bfd)
9382159047fSniklas {
9392159047fSniklas   long symcount;
940007c2a45Smiod   void *minisyms;
9412159047fSniklas   unsigned int size;
9422159047fSniklas   struct size_sym *symsizes;
9432159047fSniklas 
9442159047fSniklas   if (! dynamic)
9452159047fSniklas     {
9462159047fSniklas       if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
9472159047fSniklas 	{
948b305b0f1Sespie 	  non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
9492159047fSniklas 	  return;
9502159047fSniklas 	}
9512159047fSniklas     }
9522159047fSniklas 
9532159047fSniklas   symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
9542159047fSniklas   if (symcount < 0)
9552159047fSniklas     bfd_fatal (bfd_get_filename (abfd));
9562159047fSniklas 
9572159047fSniklas   if (symcount == 0)
9582159047fSniklas     {
959b305b0f1Sespie       non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
9602159047fSniklas       return;
9612159047fSniklas     }
9622159047fSniklas 
9632159047fSniklas   /* Discard the symbols we don't want to print.
9642159047fSniklas      It's OK to do this in place; we'll free the storage anyway
9652159047fSniklas      (after printing).  */
9662159047fSniklas 
9672159047fSniklas   symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
9682159047fSniklas 
9692159047fSniklas   symsizes = NULL;
9702159047fSniklas   if (! no_sort)
9712159047fSniklas     {
9722159047fSniklas       sort_bfd = abfd;
9732159047fSniklas       sort_dynamic = dynamic;
9742159047fSniklas       sort_x = bfd_make_empty_symbol (abfd);
9752159047fSniklas       sort_y = bfd_make_empty_symbol (abfd);
9762159047fSniklas       if (sort_x == NULL || sort_y == NULL)
9772159047fSniklas 	bfd_fatal (bfd_get_filename (abfd));
9782159047fSniklas 
9792159047fSniklas       if (! sort_by_size)
9802159047fSniklas 	qsort (minisyms, symcount, size,
9812159047fSniklas 	       sorters[sort_numerically][reverse_sort]);
9822159047fSniklas       else
9832159047fSniklas 	symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
9842159047fSniklas 					 size, &symsizes);
9852159047fSniklas     }
9862159047fSniklas 
9872159047fSniklas   if (! sort_by_size)
9882159047fSniklas     print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
9892159047fSniklas   else
9902159047fSniklas     print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
9912159047fSniklas 
9922159047fSniklas   free (minisyms);
9932159047fSniklas }
9942159047fSniklas 
9952159047fSniklas /* Choose which symbol entries to print;
9962159047fSniklas    compact them downward to get rid of the rest.
9972159047fSniklas    Return the number of symbols to be printed.  */
9982159047fSniklas 
9992159047fSniklas static long
filter_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size)1000007c2a45Smiod filter_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms,
1001007c2a45Smiod 		long symcount, unsigned int size)
10022159047fSniklas {
10032159047fSniklas   bfd_byte *from, *fromend, *to;
10042159047fSniklas   asymbol *store;
10052159047fSniklas 
10062159047fSniklas   store = bfd_make_empty_symbol (abfd);
10072159047fSniklas   if (store == NULL)
10082159047fSniklas     bfd_fatal (bfd_get_filename (abfd));
10092159047fSniklas 
10102159047fSniklas   from = (bfd_byte *) minisyms;
10112159047fSniklas   fromend = from + symcount * size;
10122159047fSniklas   to = (bfd_byte *) minisyms;
10132159047fSniklas 
10142159047fSniklas   for (; from < fromend; from += size)
10152159047fSniklas     {
10162159047fSniklas       int keep = 0;
10172159047fSniklas       asymbol *sym;
10182159047fSniklas 
10192159047fSniklas       PROGRESS (1);
10202159047fSniklas 
1021007c2a45Smiod       sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from, store);
10222159047fSniklas       if (sym == NULL)
10232159047fSniklas 	bfd_fatal (bfd_get_filename (abfd));
10242159047fSniklas 
10252159047fSniklas       if (undefined_only)
10262159047fSniklas 	keep = bfd_is_und_section (sym->section);
10272159047fSniklas       else if (external_only)
10282159047fSniklas 	keep = ((sym->flags & BSF_GLOBAL) != 0
1029c88b1d6cSniklas 		|| (sym->flags & BSF_WEAK) != 0
10302159047fSniklas 		|| bfd_is_und_section (sym->section)
10312159047fSniklas 		|| bfd_is_com_section (sym->section));
10322159047fSniklas       else
10332159047fSniklas 	keep = 1;
10342159047fSniklas 
10352159047fSniklas       if (keep
10362159047fSniklas 	  && ! print_debug_syms
10372159047fSniklas 	  && (sym->flags & BSF_DEBUGGING) != 0)
10382159047fSniklas 	keep = 0;
10392159047fSniklas 
10402159047fSniklas       if (keep
10412159047fSniklas 	  && sort_by_size
10422159047fSniklas 	  && (bfd_is_abs_section (sym->section)
10432159047fSniklas 	      || bfd_is_und_section (sym->section)))
10442159047fSniklas 	keep = 0;
10452159047fSniklas 
1046c88b1d6cSniklas       if (keep
1047c88b1d6cSniklas 	  && defined_only)
1048c88b1d6cSniklas 	{
1049c88b1d6cSniklas 	  if (bfd_is_und_section (sym->section))
1050c88b1d6cSniklas 	    keep = 0;
1051c88b1d6cSniklas 	}
1052c88b1d6cSniklas 
10532159047fSniklas       if (keep)
10542159047fSniklas 	{
10552159047fSniklas 	  memcpy (to, from, size);
10562159047fSniklas 	  to += size;
10572159047fSniklas 	}
10582159047fSniklas     }
10592159047fSniklas 
10602159047fSniklas   return (to - (bfd_byte *) minisyms) / size;
10612159047fSniklas }
10622159047fSniklas 
10632159047fSniklas /* Print symbol name NAME, read from ABFD, with printf format FORMAT,
10642159047fSniklas    demangling it if requested.  */
10652159047fSniklas 
10662159047fSniklas static void
print_symname(const char * format,const char * name,bfd * abfd)1067007c2a45Smiod print_symname (const char *format, const char *name, bfd *abfd)
10682159047fSniklas {
10692159047fSniklas   if (do_demangle && *name)
10702159047fSniklas     {
1071c074d1c9Sdrahn       char *res = demangle (abfd, name);
10722159047fSniklas 
10732159047fSniklas       printf (format, res);
10742159047fSniklas       free (res);
10752159047fSniklas       return;
10762159047fSniklas     }
10772159047fSniklas 
10782159047fSniklas   printf (format, name);
10792159047fSniklas }
10802159047fSniklas 
10812159047fSniklas /* Print the symbols.  If ARCHIVE_BFD is non-NULL, it is the archive
10822159047fSniklas    containing ABFD.  */
10832159047fSniklas 
10842159047fSniklas static void
print_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,bfd * archive_bfd)1085007c2a45Smiod print_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms, long symcount,
1086007c2a45Smiod 	       unsigned int size, bfd *archive_bfd)
10872159047fSniklas {
10882159047fSniklas   asymbol *store;
10892159047fSniklas   bfd_byte *from, *fromend;
10902159047fSniklas 
10912159047fSniklas   store = bfd_make_empty_symbol (abfd);
10922159047fSniklas   if (store == NULL)
10932159047fSniklas     bfd_fatal (bfd_get_filename (abfd));
10942159047fSniklas 
10952159047fSniklas   from = (bfd_byte *) minisyms;
10962159047fSniklas   fromend = from + symcount * size;
10972159047fSniklas   for (; from < fromend; from += size)
10982159047fSniklas     {
10992159047fSniklas       asymbol *sym;
11002159047fSniklas 
11012159047fSniklas       sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
11022159047fSniklas       if (sym == NULL)
11032159047fSniklas 	bfd_fatal (bfd_get_filename (abfd));
11042159047fSniklas 
1105c074d1c9Sdrahn       print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
11062159047fSniklas     }
11072159047fSniklas }
11082159047fSniklas 
11092159047fSniklas /* Print the symbols when sorting by size.  */
11102159047fSniklas 
11112159047fSniklas static void
print_size_symbols(bfd * abfd,bfd_boolean dynamic,struct size_sym * symsizes,long symcount,bfd * archive_bfd)1112007c2a45Smiod print_size_symbols (bfd *abfd, bfd_boolean dynamic,
1113007c2a45Smiod 		    struct size_sym *symsizes, long symcount,
1114007c2a45Smiod 		    bfd *archive_bfd)
11152159047fSniklas {
11162159047fSniklas   asymbol *store;
11172159047fSniklas   struct size_sym *from, *fromend;
11182159047fSniklas 
11192159047fSniklas   store = bfd_make_empty_symbol (abfd);
11202159047fSniklas   if (store == NULL)
11212159047fSniklas     bfd_fatal (bfd_get_filename (abfd));
11222159047fSniklas 
11232159047fSniklas   from = symsizes;
11242159047fSniklas   fromend = from + symcount;
11252159047fSniklas   for (; from < fromend; from++)
11262159047fSniklas     {
11272159047fSniklas       asymbol *sym;
1128c074d1c9Sdrahn       bfd_vma ssize;
11292159047fSniklas 
11302159047fSniklas       sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
11312159047fSniklas       if (sym == NULL)
11322159047fSniklas 	bfd_fatal (bfd_get_filename (abfd));
11332159047fSniklas 
1134c074d1c9Sdrahn       /* For elf we have already computed the correct symbol size.  */
1135c074d1c9Sdrahn       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1136c074d1c9Sdrahn 	ssize = from->size;
1137c074d1c9Sdrahn       else
1138c074d1c9Sdrahn 	ssize = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
11392159047fSniklas 
1140c074d1c9Sdrahn       print_symbol (abfd, sym, ssize, archive_bfd);
11412159047fSniklas     }
11422159047fSniklas }
11432159047fSniklas 
11442159047fSniklas /* Print a single symbol.  */
11452159047fSniklas 
11462159047fSniklas static void
print_symbol(bfd * abfd,asymbol * sym,bfd_vma ssize,bfd * archive_bfd)1147007c2a45Smiod print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
11482159047fSniklas {
1149c074d1c9Sdrahn   symbol_info syminfo;
1150c074d1c9Sdrahn   struct extended_symbol_info info;
1151c074d1c9Sdrahn 
11522159047fSniklas   PROGRESS (1);
11532159047fSniklas 
11542159047fSniklas   (*format->print_symbol_filename) (archive_bfd, abfd);
11552159047fSniklas 
11562159047fSniklas   bfd_get_symbol_info (abfd, sym, &syminfo);
1157c074d1c9Sdrahn   info.sinfo = &syminfo;
1158c074d1c9Sdrahn   info.ssize = ssize;
1159c074d1c9Sdrahn   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1160c074d1c9Sdrahn     info.elfinfo = (elf_symbol_type *) sym;
1161c074d1c9Sdrahn   else
1162c074d1c9Sdrahn     info.elfinfo = NULL;
1163c074d1c9Sdrahn   (*format->print_symbol_info) (&info, abfd);
11640c6d0228Sniklas 
11650c6d0228Sniklas   if (line_numbers)
11660c6d0228Sniklas     {
11670c6d0228Sniklas       static asymbol **syms;
11680c6d0228Sniklas       static long symcount;
11690c6d0228Sniklas       const char *filename, *functionname;
11700c6d0228Sniklas       unsigned int lineno;
11710c6d0228Sniklas 
11720c6d0228Sniklas       /* We need to get the canonical symbols in order to call
11730c6d0228Sniklas          bfd_find_nearest_line.  This is inefficient, but, then, you
11740c6d0228Sniklas          don't have to use --line-numbers.  */
1175b305b0f1Sespie       if (abfd != lineno_cache_bfd && syms != NULL)
1176b305b0f1Sespie 	{
1177b305b0f1Sespie 	  free (syms);
1178b305b0f1Sespie 	  syms = NULL;
1179b305b0f1Sespie 	}
11800c6d0228Sniklas       if (syms == NULL)
11810c6d0228Sniklas 	{
11820c6d0228Sniklas 	  long symsize;
11830c6d0228Sniklas 
11840c6d0228Sniklas 	  symsize = bfd_get_symtab_upper_bound (abfd);
11850c6d0228Sniklas 	  if (symsize < 0)
11860c6d0228Sniklas 	    bfd_fatal (bfd_get_filename (abfd));
11870c6d0228Sniklas 	  syms = (asymbol **) xmalloc (symsize);
11880c6d0228Sniklas 	  symcount = bfd_canonicalize_symtab (abfd, syms);
11890c6d0228Sniklas 	  if (symcount < 0)
11900c6d0228Sniklas 	    bfd_fatal (bfd_get_filename (abfd));
1191b305b0f1Sespie 	  lineno_cache_bfd = abfd;
11920c6d0228Sniklas 	}
11930c6d0228Sniklas 
11940c6d0228Sniklas       if (bfd_is_und_section (bfd_get_section (sym)))
11950c6d0228Sniklas 	{
11960c6d0228Sniklas 	  static asection **secs;
11970c6d0228Sniklas 	  static arelent ***relocs;
11980c6d0228Sniklas 	  static long *relcount;
1199b305b0f1Sespie 	  static unsigned int seccount;
1200b305b0f1Sespie 	  unsigned int i;
12010c6d0228Sniklas 	  const char *symname;
12020c6d0228Sniklas 
12030c6d0228Sniklas 	  /* For an undefined symbol, we try to find a reloc for the
12040c6d0228Sniklas              symbol, and print the line number of the reloc.  */
1205b305b0f1Sespie 	  if (abfd != lineno_cache_rel_bfd && relocs != NULL)
1206b305b0f1Sespie 	    {
1207b305b0f1Sespie 	      for (i = 0; i < seccount; i++)
1208b305b0f1Sespie 		if (relocs[i] != NULL)
1209b305b0f1Sespie 		  free (relocs[i]);
1210b305b0f1Sespie 	      free (secs);
1211b305b0f1Sespie 	      free (relocs);
1212b305b0f1Sespie 	      free (relcount);
1213b305b0f1Sespie 	      secs = NULL;
1214b305b0f1Sespie 	      relocs = NULL;
1215b305b0f1Sespie 	      relcount = NULL;
1216b305b0f1Sespie 	    }
12170c6d0228Sniklas 
12180c6d0228Sniklas 	  if (relocs == NULL)
12190c6d0228Sniklas 	    {
12200c6d0228Sniklas 	      struct get_relocs_info info;
12210c6d0228Sniklas 
1222b305b0f1Sespie 	      seccount = bfd_count_sections (abfd);
1223b305b0f1Sespie 
12240c6d0228Sniklas 	      secs = (asection **) xmalloc (seccount * sizeof *secs);
12250c6d0228Sniklas 	      relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
12260c6d0228Sniklas 	      relcount = (long *) xmalloc (seccount * sizeof *relcount);
12270c6d0228Sniklas 
12280c6d0228Sniklas 	      info.secs = secs;
12290c6d0228Sniklas 	      info.relocs = relocs;
12300c6d0228Sniklas 	      info.relcount = relcount;
12310c6d0228Sniklas 	      info.syms = syms;
1232007c2a45Smiod 	      bfd_map_over_sections (abfd, get_relocs, (void *) &info);
1233b305b0f1Sespie 	      lineno_cache_rel_bfd = abfd;
12340c6d0228Sniklas 	    }
12350c6d0228Sniklas 
12360c6d0228Sniklas 	  symname = bfd_asymbol_name (sym);
12370c6d0228Sniklas 	  for (i = 0; i < seccount; i++)
12380c6d0228Sniklas 	    {
1239b305b0f1Sespie 	      long j;
12400c6d0228Sniklas 
12410c6d0228Sniklas 	      for (j = 0; j < relcount[i]; j++)
12420c6d0228Sniklas 		{
12430c6d0228Sniklas 		  arelent *r;
12440c6d0228Sniklas 
12450c6d0228Sniklas 		  r = relocs[i][j];
12460c6d0228Sniklas 		  if (r->sym_ptr_ptr != NULL
12470c6d0228Sniklas 		      && (*r->sym_ptr_ptr)->section == sym->section
12480c6d0228Sniklas 		      && (*r->sym_ptr_ptr)->value == sym->value
12490c6d0228Sniklas 		      && strcmp (symname,
12500c6d0228Sniklas 				 bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
12510c6d0228Sniklas 		      && bfd_find_nearest_line (abfd, secs[i], syms,
12520c6d0228Sniklas 						r->address, &filename,
1253c074d1c9Sdrahn 						&functionname, &lineno)
1254c074d1c9Sdrahn 		      && filename != NULL)
12550c6d0228Sniklas 		    {
12560c6d0228Sniklas 		      /* We only print the first one we find.  */
12570c6d0228Sniklas 		      printf ("\t%s:%u", filename, lineno);
12580c6d0228Sniklas 		      i = seccount;
12590c6d0228Sniklas 		      break;
12600c6d0228Sniklas 		    }
12610c6d0228Sniklas 		}
12620c6d0228Sniklas 	    }
12630c6d0228Sniklas 	}
12640c6d0228Sniklas       else if (bfd_get_section (sym)->owner == abfd)
12650c6d0228Sniklas 	{
12660c6d0228Sniklas 	  if (bfd_find_nearest_line (abfd, bfd_get_section (sym), syms,
12670c6d0228Sniklas 				     sym->value, &filename, &functionname,
12680c6d0228Sniklas 				     &lineno)
12690c6d0228Sniklas 	      && filename != NULL
12700c6d0228Sniklas 	      && lineno != 0)
12710c6d0228Sniklas 	    {
12720c6d0228Sniklas 	      printf ("\t%s:%u", filename, lineno);
12730c6d0228Sniklas 	    }
12740c6d0228Sniklas 	}
12750c6d0228Sniklas     }
12760c6d0228Sniklas 
12770c6d0228Sniklas   putchar ('\n');
12782159047fSniklas }
12792159047fSniklas 
12802159047fSniklas /* The following 3 groups of functions are called unconditionally,
12812159047fSniklas    once at the start of processing each file of the appropriate type.
12822159047fSniklas    They should check `filename_per_file' and `filename_per_symbol',
12832159047fSniklas    as appropriate for their output format, to determine whether to
12842159047fSniklas    print anything.  */
12852159047fSniklas 
12862159047fSniklas /* Print the name of an object file given on the command line.  */
12872159047fSniklas 
12882159047fSniklas static void
print_object_filename_bsd(char * filename)1289007c2a45Smiod print_object_filename_bsd (char *filename)
12902159047fSniklas {
12912159047fSniklas   if (filename_per_file && !filename_per_symbol)
12922159047fSniklas     printf ("\n%s:\n", filename);
12932159047fSniklas }
12942159047fSniklas 
12952159047fSniklas static void
print_object_filename_sysv(char * filename)1296007c2a45Smiod print_object_filename_sysv (char *filename)
12972159047fSniklas {
12982159047fSniklas   if (undefined_only)
1299b305b0f1Sespie     printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
13002159047fSniklas   else
1301b305b0f1Sespie     printf (_("\n\nSymbols from %s:\n\n"), filename);
1302c074d1c9Sdrahn   if (print_width == 8)
1303c074d1c9Sdrahn     printf (_("\
1304c074d1c9Sdrahn Name                  Value   Class        Type         Size     Line  Section\n\n"));
1305c074d1c9Sdrahn   else
1306b305b0f1Sespie     printf (_("\
1307b305b0f1Sespie Name                  Value           Class        Type         Size             Line  Section\n\n"));
13082159047fSniklas }
13092159047fSniklas 
13102159047fSniklas static void
print_object_filename_posix(char * filename)1311007c2a45Smiod print_object_filename_posix (char *filename)
13122159047fSniklas {
13132159047fSniklas   if (filename_per_file && !filename_per_symbol)
13142159047fSniklas     printf ("%s:\n", filename);
13152159047fSniklas }
13162159047fSniklas 
13172159047fSniklas /* Print the name of an archive file given on the command line.  */
13182159047fSniklas 
13192159047fSniklas static void
print_archive_filename_bsd(char * filename)1320007c2a45Smiod print_archive_filename_bsd (char *filename)
13212159047fSniklas {
13222159047fSniklas   if (filename_per_file)
13232159047fSniklas     printf ("\n%s:\n", filename);
13242159047fSniklas }
13252159047fSniklas 
13262159047fSniklas static void
print_archive_filename_sysv(char * filename ATTRIBUTE_UNUSED)1327007c2a45Smiod print_archive_filename_sysv (char *filename ATTRIBUTE_UNUSED)
13282159047fSniklas {
13292159047fSniklas }
13302159047fSniklas 
13312159047fSniklas static void
print_archive_filename_posix(char * filename ATTRIBUTE_UNUSED)1332007c2a45Smiod print_archive_filename_posix (char *filename ATTRIBUTE_UNUSED)
13332159047fSniklas {
13342159047fSniklas }
13352159047fSniklas 
13362159047fSniklas /* Print the name of an archive member file.  */
13372159047fSniklas 
13382159047fSniklas static void
print_archive_member_bsd(char * archive ATTRIBUTE_UNUSED,const char * filename)1339007c2a45Smiod print_archive_member_bsd (char *archive ATTRIBUTE_UNUSED,
1340007c2a45Smiod 			  const char *filename)
13412159047fSniklas {
13422159047fSniklas   if (!filename_per_symbol)
13432159047fSniklas     printf ("\n%s:\n", filename);
13442159047fSniklas }
13452159047fSniklas 
13462159047fSniklas static void
print_archive_member_sysv(char * archive,const char * filename)1347007c2a45Smiod print_archive_member_sysv (char *archive, const char *filename)
13482159047fSniklas {
13492159047fSniklas   if (undefined_only)
1350b305b0f1Sespie     printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
13512159047fSniklas   else
1352b305b0f1Sespie     printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
1353c074d1c9Sdrahn   if (print_width == 8)
1354c074d1c9Sdrahn     printf (_("\
1355c074d1c9Sdrahn Name                  Value   Class        Type         Size     Line  Section\n\n"));
1356c074d1c9Sdrahn   else
1357b305b0f1Sespie     printf (_("\
1358b305b0f1Sespie Name                  Value           Class        Type         Size             Line  Section\n\n"));
13592159047fSniklas }
13602159047fSniklas 
13612159047fSniklas static void
print_archive_member_posix(char * archive,const char * filename)1362007c2a45Smiod print_archive_member_posix (char *archive, const char *filename)
13632159047fSniklas {
13642159047fSniklas   if (!filename_per_symbol)
13652159047fSniklas     printf ("%s[%s]:\n", archive, filename);
13662159047fSniklas }
13672159047fSniklas 
13682159047fSniklas /* Print the name of the file (and archive, if there is one)
13692159047fSniklas    containing a symbol.  */
13702159047fSniklas 
13712159047fSniklas static void
print_symbol_filename_bsd(bfd * archive_bfd,bfd * abfd)1372007c2a45Smiod print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
13732159047fSniklas {
13742159047fSniklas   if (filename_per_symbol)
13752159047fSniklas     {
13762159047fSniklas       if (archive_bfd)
13772159047fSniklas 	printf ("%s:", bfd_get_filename (archive_bfd));
13782159047fSniklas       printf ("%s:", bfd_get_filename (abfd));
13792159047fSniklas     }
13802159047fSniklas }
13812159047fSniklas 
13822159047fSniklas static void
print_symbol_filename_sysv(bfd * archive_bfd,bfd * abfd)1383007c2a45Smiod print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
13842159047fSniklas {
13852159047fSniklas   if (filename_per_symbol)
13862159047fSniklas     {
13872159047fSniklas       if (archive_bfd)
13882159047fSniklas 	printf ("%s:", bfd_get_filename (archive_bfd));
13892159047fSniklas       printf ("%s:", bfd_get_filename (abfd));
13902159047fSniklas     }
13912159047fSniklas }
13922159047fSniklas 
13932159047fSniklas static void
print_symbol_filename_posix(bfd * archive_bfd,bfd * abfd)1394007c2a45Smiod print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
13952159047fSniklas {
13962159047fSniklas   if (filename_per_symbol)
13972159047fSniklas     {
13982159047fSniklas       if (archive_bfd)
13992159047fSniklas 	printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
14002159047fSniklas 		bfd_get_filename (abfd));
14012159047fSniklas       else
14022159047fSniklas 	printf ("%s: ", bfd_get_filename (abfd));
14032159047fSniklas     }
14042159047fSniklas }
14052159047fSniklas 
14062159047fSniklas /* Print a symbol value.  */
14072159047fSniklas 
14082159047fSniklas static void
print_value(bfd * abfd ATTRIBUTE_UNUSED,bfd_vma val)1409007c2a45Smiod print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
14102159047fSniklas {
14112159047fSniklas #if ! defined (BFD64) || BFD_HOST_64BIT_LONG
14122159047fSniklas   printf (value_format, val);
14132159047fSniklas #else
14142159047fSniklas   /* We have a 64 bit value to print, but the host is only 32 bit.  */
14152159047fSniklas   if (print_radix == 16)
1416c074d1c9Sdrahn     bfd_fprintf_vma (abfd, stdout, val);
14172159047fSniklas   else
14182159047fSniklas     {
14192159047fSniklas       char buf[30];
14202159047fSniklas       char *s;
14212159047fSniklas 
14222159047fSniklas       s = buf + sizeof buf;
14232159047fSniklas       *--s = '\0';
14242159047fSniklas       while (val > 0)
14252159047fSniklas 	{
14262159047fSniklas 	  *--s = (val % print_radix) + '0';
14272159047fSniklas 	  val /= print_radix;
14282159047fSniklas 	}
14292159047fSniklas       while ((buf + sizeof buf - 1) - s < 16)
14302159047fSniklas 	*--s = '0';
14312159047fSniklas       printf ("%s", s);
14322159047fSniklas     }
14332159047fSniklas #endif
14342159047fSniklas }
14352159047fSniklas 
14362159047fSniklas /* Print a line of information about a symbol.  */
14372159047fSniklas 
14382159047fSniklas static void
print_symbol_info_bsd(struct extended_symbol_info * info,bfd * abfd)1439007c2a45Smiod print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
14402159047fSniklas {
1441c074d1c9Sdrahn   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
14422159047fSniklas     {
1443c074d1c9Sdrahn       if (print_width == 16)
1444b55d4692Sfgsch 	printf ("        ");
1445b55d4692Sfgsch       printf ("        ");
14462159047fSniklas     }
14472159047fSniklas   else
1448c074d1c9Sdrahn     {
1449c074d1c9Sdrahn       /* Normally we print the value of the symbol.  If we are printing the
1450007c2a45Smiod 	 size or sorting by size then we print its size, except for the
1451c074d1c9Sdrahn 	 (weird) special case where both flags are defined, in which case we
1452c074d1c9Sdrahn 	 print both values.  This conforms to documented behaviour.  */
1453c074d1c9Sdrahn       if (sort_by_size && !print_size)
1454c074d1c9Sdrahn 	print_value (abfd, SYM_SIZE (info));
1455c074d1c9Sdrahn       else
1456c074d1c9Sdrahn 	print_value (abfd, SYM_VALUE (info));
1457c074d1c9Sdrahn 
1458c074d1c9Sdrahn       if (print_size && SYM_SIZE (info))
1459c074d1c9Sdrahn 	{
1460c074d1c9Sdrahn 	  printf (" ");
1461c074d1c9Sdrahn 	  print_value (abfd, SYM_SIZE (info));
1462c074d1c9Sdrahn 	}
1463c074d1c9Sdrahn     }
1464c074d1c9Sdrahn 
1465c074d1c9Sdrahn   printf (" %c", SYM_TYPE (info));
1466c074d1c9Sdrahn 
1467c074d1c9Sdrahn   if (SYM_TYPE (info) == '-')
14682159047fSniklas     {
14692159047fSniklas       /* A stab.  */
14702159047fSniklas       printf (" ");
1471c074d1c9Sdrahn       printf (other_format, SYM_STAB_OTHER (info));
14722159047fSniklas       printf (" ");
1473c074d1c9Sdrahn       printf (desc_format, SYM_STAB_DESC (info));
1474c074d1c9Sdrahn       printf (" %5s", SYM_STAB_NAME (info));
14752159047fSniklas     }
1476c074d1c9Sdrahn   print_symname (" %s", SYM_NAME (info), abfd);
14772159047fSniklas }
14782159047fSniklas 
14792159047fSniklas static void
print_symbol_info_sysv(struct extended_symbol_info * info,bfd * abfd)1480007c2a45Smiod print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
14812159047fSniklas {
1482c074d1c9Sdrahn   print_symname ("%-20s|", SYM_NAME (info), abfd);
1483c074d1c9Sdrahn 
1484c074d1c9Sdrahn   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
14852159047fSniklas     {
1486c074d1c9Sdrahn       if (print_width == 8)
1487c074d1c9Sdrahn 	printf ("        ");
1488c074d1c9Sdrahn       else
1489c074d1c9Sdrahn 	printf ("                ");
14902159047fSniklas     }
14912159047fSniklas   else
1492c074d1c9Sdrahn     print_value (abfd, SYM_VALUE (info));
1493c074d1c9Sdrahn 
1494c074d1c9Sdrahn   printf ("|   %c  |", SYM_TYPE (info));
1495c074d1c9Sdrahn 
1496c074d1c9Sdrahn   if (SYM_TYPE (info) == '-')
1497c074d1c9Sdrahn     {
1498c074d1c9Sdrahn       /* A stab.  */
1499c074d1c9Sdrahn       printf ("%18s|  ", SYM_STAB_NAME (info));		/* (C) Type.  */
1500c074d1c9Sdrahn       printf (desc_format, SYM_STAB_DESC (info));	/* Size.  */
1501c074d1c9Sdrahn       printf ("|     |");				/* Line, Section.  */
1502c074d1c9Sdrahn     }
1503c074d1c9Sdrahn   else
1504c074d1c9Sdrahn     {
1505c074d1c9Sdrahn       /* Type, Size, Line, Section */
1506c074d1c9Sdrahn       if (info->elfinfo)
1507c074d1c9Sdrahn 	printf ("%18s|",
1508c074d1c9Sdrahn 		get_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
1509c074d1c9Sdrahn       else
1510c074d1c9Sdrahn 	printf ("                  |");
1511c074d1c9Sdrahn 
1512c074d1c9Sdrahn       if (SYM_SIZE (info))
1513c074d1c9Sdrahn 	print_value (abfd, SYM_SIZE (info));
1514c074d1c9Sdrahn       else
1515c074d1c9Sdrahn 	{
1516c074d1c9Sdrahn 	  if (print_width == 8)
1517c074d1c9Sdrahn 	    printf ("        ");
1518c074d1c9Sdrahn 	  else
1519c074d1c9Sdrahn 	    printf ("                ");
1520c074d1c9Sdrahn 	}
1521c074d1c9Sdrahn 
1522c074d1c9Sdrahn       if (info->elfinfo)
1523c074d1c9Sdrahn 	printf("|     |%s", info->elfinfo->symbol.section->name);
1524c074d1c9Sdrahn       else
1525c074d1c9Sdrahn 	printf("|     |");
1526c074d1c9Sdrahn     }
15272159047fSniklas }
15282159047fSniklas 
15292159047fSniklas static void
print_symbol_info_posix(struct extended_symbol_info * info,bfd * abfd)1530007c2a45Smiod print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
15312159047fSniklas {
1532c074d1c9Sdrahn   print_symname ("%s ", SYM_NAME (info), abfd);
1533c074d1c9Sdrahn   printf ("%c ", SYM_TYPE (info));
1534c074d1c9Sdrahn 
1535c074d1c9Sdrahn   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
15362159047fSniklas     printf ("        ");
15372159047fSniklas   else
1538c074d1c9Sdrahn     {
1539c074d1c9Sdrahn       print_value (abfd, SYM_VALUE (info));
1540c074d1c9Sdrahn       printf (" ");
1541c074d1c9Sdrahn       if (SYM_SIZE (info))
1542c074d1c9Sdrahn 	print_value (abfd, SYM_SIZE (info));
1543c074d1c9Sdrahn     }
15442159047fSniklas }
15452159047fSniklas 
15462159047fSniklas static void
print_symdef_entry(bfd * abfd)1547007c2a45Smiod print_symdef_entry (bfd *abfd)
15482159047fSniklas {
15492159047fSniklas   symindex idx = BFD_NO_MORE_SYMBOLS;
15502159047fSniklas   carsym *thesym;
1551c074d1c9Sdrahn   bfd_boolean everprinted = FALSE;
15522159047fSniklas 
15532159047fSniklas   for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
15542159047fSniklas        idx != BFD_NO_MORE_SYMBOLS;
15552159047fSniklas        idx = bfd_get_next_mapent (abfd, idx, &thesym))
15562159047fSniklas     {
15572159047fSniklas       bfd *elt;
15582159047fSniklas       if (!everprinted)
15592159047fSniklas 	{
1560b305b0f1Sespie 	  printf (_("\nArchive index:\n"));
1561c074d1c9Sdrahn 	  everprinted = TRUE;
15622159047fSniklas 	}
15632159047fSniklas       elt = bfd_get_elt_at_index (abfd, idx);
1564c88b1d6cSniklas       if (elt == NULL)
1565c88b1d6cSniklas 	bfd_fatal ("bfd_get_elt_at_index");
15662159047fSniklas       if (thesym->name != (char *) NULL)
15672159047fSniklas 	{
15682159047fSniklas 	  print_symname ("%s", thesym->name, abfd);
15692159047fSniklas 	  printf (" in %s\n", bfd_get_filename (elt));
15702159047fSniklas 	}
15712159047fSniklas     }
15722159047fSniklas }
15730c6d0228Sniklas 
15740c6d0228Sniklas /* This function is used to get the relocs for a particular section.
15750c6d0228Sniklas    It is called via bfd_map_over_sections.  */
15760c6d0228Sniklas 
15770c6d0228Sniklas static void
get_relocs(bfd * abfd,asection * sec,void * dataarg)1578007c2a45Smiod get_relocs (bfd *abfd, asection *sec, void *dataarg)
15790c6d0228Sniklas {
15800c6d0228Sniklas   struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
15810c6d0228Sniklas 
15820c6d0228Sniklas   *data->secs = sec;
15830c6d0228Sniklas 
15840c6d0228Sniklas   if ((sec->flags & SEC_RELOC) == 0)
15850c6d0228Sniklas     {
15860c6d0228Sniklas       *data->relocs = NULL;
15870c6d0228Sniklas       *data->relcount = 0;
15880c6d0228Sniklas     }
15890c6d0228Sniklas   else
15900c6d0228Sniklas     {
15910c6d0228Sniklas       long relsize;
15920c6d0228Sniklas 
15930c6d0228Sniklas       relsize = bfd_get_reloc_upper_bound (abfd, sec);
15940c6d0228Sniklas       if (relsize < 0)
15950c6d0228Sniklas 	bfd_fatal (bfd_get_filename (abfd));
15960c6d0228Sniklas 
15970c6d0228Sniklas       *data->relocs = (arelent **) xmalloc (relsize);
15980c6d0228Sniklas       *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
15990c6d0228Sniklas 						data->syms);
16000c6d0228Sniklas       if (*data->relcount < 0)
16010c6d0228Sniklas 	bfd_fatal (bfd_get_filename (abfd));
16020c6d0228Sniklas     }
16030c6d0228Sniklas 
16040c6d0228Sniklas   ++data->secs;
16050c6d0228Sniklas   ++data->relocs;
16060c6d0228Sniklas   ++data->relcount;
16070c6d0228Sniklas }
1608