Back to index

cell-binutils  2.17cvs20070401
nm.c
Go to the documentation of this file.
00001 /* nm.c -- Describe symbol table of a rel file.
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
00003    2001, 2002, 2003, 2004, 2005, 2007
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "progress.h"
00025 #include "bucomm.h"
00026 #include "budemang.h"
00027 #include "getopt.h"
00028 #include "aout/stab_gnu.h"
00029 #include "aout/ranlib.h"
00030 #include "demangle.h"
00031 #include "libiberty.h"
00032 #include "elf-bfd.h"
00033 #include "elf/common.h"
00034 
00035 /* When sorting by size, we use this structure to hold the size and a
00036    pointer to the minisymbol.  */
00037 
00038 struct size_sym
00039 {
00040   const void *minisym;
00041   bfd_vma size;
00042 };
00043 
00044 /* When fetching relocs, we use this structure to pass information to
00045    get_relocs.  */
00046 
00047 struct get_relocs_info
00048 {
00049   asection **secs;
00050   arelent ***relocs;
00051   long *relcount;
00052   asymbol **syms;
00053 };
00054 
00055 struct extended_symbol_info
00056 {
00057   symbol_info *sinfo;
00058   bfd_vma ssize;
00059   elf_symbol_type *elfinfo;
00060   /* FIXME: We should add more fields for Type, Line, Section.  */
00061 };
00062 #define SYM_NAME(sym)        (sym->sinfo->name)
00063 #define SYM_VALUE(sym)       (sym->sinfo->value)
00064 #define SYM_TYPE(sym)        (sym->sinfo->type)
00065 #define SYM_STAB_NAME(sym)   (sym->sinfo->stab_name)
00066 #define SYM_STAB_DESC(sym)   (sym->sinfo->stab_desc)
00067 #define SYM_STAB_OTHER(sym)  (sym->sinfo->stab_other)
00068 #define SYM_SIZE(sym) \
00069   (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
00070 
00071 /* The output formatting functions.  */
00072 static void print_object_filename_bsd (char *);
00073 static void print_object_filename_sysv (char *);
00074 static void print_object_filename_posix (char *);
00075 static void print_archive_filename_bsd (char *);
00076 static void print_archive_filename_sysv (char *);
00077 static void print_archive_filename_posix (char *);
00078 static void print_archive_member_bsd (char *, const char *);
00079 static void print_archive_member_sysv (char *, const char *);
00080 static void print_archive_member_posix (char *, const char *);
00081 static void print_symbol_filename_bsd (bfd *, bfd *);
00082 static void print_symbol_filename_sysv (bfd *, bfd *);
00083 static void print_symbol_filename_posix (bfd *, bfd *);
00084 static void print_value (bfd *, bfd_vma);
00085 static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
00086 static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
00087 static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
00088 
00089 /* Support for different output formats.  */
00090 struct output_fns
00091   {
00092     /* Print the name of an object file given on the command line.  */
00093     void (*print_object_filename) (char *);
00094 
00095     /* Print the name of an archive file given on the command line.  */
00096     void (*print_archive_filename) (char *);
00097 
00098     /* Print the name of an archive member file.  */
00099     void (*print_archive_member) (char *, const char *);
00100 
00101     /* Print the name of the file (and archive, if there is one)
00102        containing a symbol.  */
00103     void (*print_symbol_filename) (bfd *, bfd *);
00104 
00105     /* Print a line of information about a symbol.  */
00106     void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
00107   };
00108 
00109 static struct output_fns formats[] =
00110 {
00111   {print_object_filename_bsd,
00112    print_archive_filename_bsd,
00113    print_archive_member_bsd,
00114    print_symbol_filename_bsd,
00115    print_symbol_info_bsd},
00116   {print_object_filename_sysv,
00117    print_archive_filename_sysv,
00118    print_archive_member_sysv,
00119    print_symbol_filename_sysv,
00120    print_symbol_info_sysv},
00121   {print_object_filename_posix,
00122    print_archive_filename_posix,
00123    print_archive_member_posix,
00124    print_symbol_filename_posix,
00125    print_symbol_info_posix}
00126 };
00127 
00128 /* Indices in `formats'.  */
00129 #define FORMAT_BSD 0
00130 #define FORMAT_SYSV 1
00131 #define FORMAT_POSIX 2
00132 #define FORMAT_DEFAULT FORMAT_BSD
00133 
00134 /* The output format to use.  */
00135 static struct output_fns *format = &formats[FORMAT_DEFAULT];
00136 
00137 /* Command options.  */
00138 
00139 static int do_demangle = 0; /* Pretty print C++ symbol names.  */
00140 static int external_only = 0;      /* Print external symbols only.  */
00141 static int defined_only = 0;       /* Print defined symbols only.  */
00142 static int no_sort = 0;            /* Don't sort; print syms in order found.  */
00143 static int print_debug_syms = 0;/* Print debugger-only symbols too.  */
00144 static int print_armap = 0; /* Describe __.SYMDEF data in archive files.  */
00145 static int print_size = 0;  /* Print size of defined symbols.  */
00146 static int reverse_sort = 0;       /* Sort in downward(alpha or numeric) order.  */
00147 static int sort_numerically = 0;/* Sort in numeric rather than alpha order.  */
00148 static int sort_by_size = 0;       /* Sort by size of symbol.  */
00149 static int undefined_only = 0;     /* Print undefined symbols only.  */
00150 static int dynamic = 0;            /* Print dynamic symbols.  */
00151 static int show_version = 0;       /* Show the version number.  */
00152 static int show_stats = 0;  /* Show statistics.  */
00153 static int show_synthetic = 0;     /* Display synthesized symbols too.  */
00154 static int line_numbers = 0;       /* Print line numbers for symbols.  */
00155 static int allow_special_symbols = 0;  /* Allow special symbols.  */
00156 
00157 /* When to print the names of files.  Not mutually exclusive in SYSV format.  */
00158 static int filename_per_file = 0;  /* Once per file, on its own line.  */
00159 static int filename_per_symbol = 0;       /* Once per symbol, at start of line.  */
00160 
00161 /* Print formats for printing a symbol value.  */
00162 #ifndef BFD64
00163 static char value_format[] = "%08lx";
00164 #else
00165 #if BFD_HOST_64BIT_LONG
00166 static char value_format[] = "%016lx";
00167 #else
00168 /* We don't use value_format for this case.  */
00169 #endif
00170 #endif
00171 #ifdef BFD64
00172 static int print_width = 16;
00173 #else
00174 static int print_width = 8;
00175 #endif
00176 static int print_radix = 16;
00177 /* Print formats for printing stab info.  */
00178 static char other_format[] = "%02x";
00179 static char desc_format[] = "%04x";
00180 
00181 static char *target = NULL;
00182 
00183 /* Used to cache the line numbers for a BFD.  */
00184 static bfd *lineno_cache_bfd;
00185 static bfd *lineno_cache_rel_bfd;
00186 
00187 #define OPTION_TARGET 200
00188 
00189 static struct option long_options[] =
00190 {
00191   {"debug-syms", no_argument, &print_debug_syms, 1},
00192   {"demangle", optional_argument, 0, 'C'},
00193   {"dynamic", no_argument, &dynamic, 1},
00194   {"extern-only", no_argument, &external_only, 1},
00195   {"format", required_argument, 0, 'f'},
00196   {"help", no_argument, 0, 'h'},
00197   {"line-numbers", no_argument, 0, 'l'},
00198   {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
00199   {"no-demangle", no_argument, &do_demangle, 0},
00200   {"no-sort", no_argument, &no_sort, 1},
00201   {"numeric-sort", no_argument, &sort_numerically, 1},
00202   {"portability", no_argument, 0, 'P'},
00203   {"print-armap", no_argument, &print_armap, 1},
00204   {"print-file-name", no_argument, 0, 'o'},
00205   {"print-size", no_argument, 0, 'S'},
00206   {"radix", required_argument, 0, 't'},
00207   {"reverse-sort", no_argument, &reverse_sort, 1},
00208   {"size-sort", no_argument, &sort_by_size, 1},
00209   {"special-syms", no_argument, &allow_special_symbols, 1},
00210   {"stats", no_argument, &show_stats, 1},
00211   {"synthetic", no_argument, &show_synthetic, 1},
00212   {"target", required_argument, 0, OPTION_TARGET},
00213   {"defined-only", no_argument, &defined_only, 1},
00214   {"undefined-only", no_argument, &undefined_only, 1},
00215   {"version", no_argument, &show_version, 1},
00216   {0, no_argument, 0, 0}
00217 };
00218 
00219 /* Some error-reporting functions.  */
00220 
00221 static void
00222 usage (FILE *stream, int status)
00223 {
00224   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
00225   fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
00226   fprintf (stream, _(" The options are:\n\
00227   -a, --debug-syms       Display debugger-only symbols\n\
00228   -A, --print-file-name  Print name of the input file before every symbol\n\
00229   -B                     Same as --format=bsd\n\
00230   -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
00231                           The STYLE, if specified, can be `auto' (the default),\n\
00232                           `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
00233                           or `gnat'\n\
00234       --no-demangle      Do not demangle low-level symbol names\n\
00235   -D, --dynamic          Display dynamic symbols instead of normal symbols\n\
00236       --defined-only     Display only defined symbols\n\
00237   -e                     (ignored)\n\
00238   -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',\n\
00239                            `sysv' or `posix'.  The default is `bsd'\n\
00240   -g, --extern-only      Display only external symbols\n\
00241   -l, --line-numbers     Use debugging information to find a filename and\n\
00242                            line number for each symbol\n\
00243   -n, --numeric-sort     Sort symbols numerically by address\n\
00244   -o                     Same as -A\n\
00245   -p, --no-sort          Do not sort the symbols\n\
00246   -P, --portability      Same as --format=posix\n\
00247   -r, --reverse-sort     Reverse the sense of the sort\n\
00248   -S, --print-size       Print size of defined symbols\n\
00249   -s, --print-armap      Include index for symbols from archive members\n\
00250       --size-sort        Sort symbols by size\n\
00251       --special-syms     Include special symbols in the output\n\
00252       --synthetic        Display synthetic symbols as well\n\
00253   -t, --radix=RADIX      Use RADIX for printing symbol values\n\
00254       --target=BFDNAME   Specify the target object format as BFDNAME\n\
00255   -u, --undefined-only   Display only undefined symbols\n\
00256   -X 32_64               (ignored)\n\
00257   @FILE                  Read options from FILE\n\
00258   -h, --help             Display this information\n\
00259   -V, --version          Display this program's version number\n\
00260 \n"));
00261   list_supported_targets (program_name, stream);
00262   if (REPORT_BUGS_TO[0] && status == 0)
00263     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
00264   exit (status);
00265 }
00266 
00267 /* Set the radix for the symbol value and size according to RADIX.  */
00268 
00269 static void
00270 set_print_radix (char *radix)
00271 {
00272   switch (*radix)
00273     {
00274     case 'x':
00275       break;
00276     case 'd':
00277     case 'o':
00278       if (*radix == 'd')
00279        print_radix = 10;
00280       else
00281        print_radix = 8;
00282 #ifndef BFD64
00283       value_format[4] = *radix;
00284 #else
00285 #if BFD_HOST_64BIT_LONG
00286       value_format[5] = *radix;
00287 #else
00288       /* This case requires special handling for octal and decimal
00289          printing.  */
00290 #endif
00291 #endif
00292       other_format[3] = desc_format[3] = *radix;
00293       break;
00294     default:
00295       fatal (_("%s: invalid radix"), radix);
00296     }
00297 }
00298 
00299 static void
00300 set_output_format (char *f)
00301 {
00302   int i;
00303 
00304   switch (*f)
00305     {
00306     case 'b':
00307     case 'B':
00308       i = FORMAT_BSD;
00309       break;
00310     case 'p':
00311     case 'P':
00312       i = FORMAT_POSIX;
00313       break;
00314     case 's':
00315     case 'S':
00316       i = FORMAT_SYSV;
00317       break;
00318     default:
00319       fatal (_("%s: invalid output format"), f);
00320     }
00321   format = &formats[i];
00322 }
00323 
00324 static const char *
00325 get_symbol_type (unsigned int type)
00326 {
00327   static char buff [32];
00328 
00329   switch (type)
00330     {
00331     case STT_NOTYPE:   return "NOTYPE";
00332     case STT_OBJECT:   return "OBJECT";
00333     case STT_FUNC:     return "FUNC";
00334     case STT_SECTION:  return "SECTION";
00335     case STT_FILE:     return "FILE";
00336     case STT_COMMON:   return "COMMON";
00337     case STT_TLS:      return "TLS";
00338     default:
00339       if (type >= STT_LOPROC && type <= STT_HIPROC)
00340        sprintf (buff, _("<processor specific>: %d"), type);
00341       else if (type >= STT_LOOS && type <= STT_HIOS)
00342        sprintf (buff, _("<OS specific>: %d"), type);
00343       else
00344        sprintf (buff, _("<unknown>: %d"), type);
00345       return buff;
00346     }
00347 }
00348 
00349 /* Print symbol name NAME, read from ABFD, with printf format FORMAT,
00350    demangling it if requested.  */
00351 
00352 static void
00353 print_symname (const char *format, const char *name, bfd *abfd)
00354 {
00355   if (do_demangle && *name)
00356     {
00357       char *res = demangle (abfd, name);
00358 
00359       printf (format, res);
00360       free (res);
00361       return;
00362     }
00363 
00364   printf (format, name);
00365 }
00366 
00367 static void
00368 print_symdef_entry (bfd *abfd)
00369 {
00370   symindex idx = BFD_NO_MORE_SYMBOLS;
00371   carsym *thesym;
00372   bfd_boolean everprinted = FALSE;
00373 
00374   for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
00375        idx != BFD_NO_MORE_SYMBOLS;
00376        idx = bfd_get_next_mapent (abfd, idx, &thesym))
00377     {
00378       bfd *elt;
00379       if (!everprinted)
00380        {
00381          printf (_("\nArchive index:\n"));
00382          everprinted = TRUE;
00383        }
00384       elt = bfd_get_elt_at_index (abfd, idx);
00385       if (elt == NULL)
00386        bfd_fatal ("bfd_get_elt_at_index");
00387       if (thesym->name != (char *) NULL)
00388        {
00389          print_symname ("%s", thesym->name, abfd);
00390          printf (" in %s\n", bfd_get_filename (elt));
00391        }
00392     }
00393 }
00394 
00395 /* Choose which symbol entries to print;
00396    compact them downward to get rid of the rest.
00397    Return the number of symbols to be printed.  */
00398 
00399 static long
00400 filter_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms,
00401               long symcount, unsigned int size)
00402 {
00403   bfd_byte *from, *fromend, *to;
00404   asymbol *store;
00405 
00406   store = bfd_make_empty_symbol (abfd);
00407   if (store == NULL)
00408     bfd_fatal (bfd_get_filename (abfd));
00409 
00410   from = (bfd_byte *) minisyms;
00411   fromend = from + symcount * size;
00412   to = (bfd_byte *) minisyms;
00413 
00414   for (; from < fromend; from += size)
00415     {
00416       int keep = 0;
00417       asymbol *sym;
00418 
00419       PROGRESS (1);
00420 
00421       sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from, store);
00422       if (sym == NULL)
00423        bfd_fatal (bfd_get_filename (abfd));
00424 
00425       if (undefined_only)
00426        keep = bfd_is_und_section (sym->section);
00427       else if (external_only)
00428        keep = ((sym->flags & BSF_GLOBAL) != 0
00429               || (sym->flags & BSF_WEAK) != 0
00430               || bfd_is_und_section (sym->section)
00431               || bfd_is_com_section (sym->section));
00432       else
00433        keep = 1;
00434 
00435       if (keep
00436          && ! print_debug_syms
00437          && (sym->flags & BSF_DEBUGGING) != 0)
00438        keep = 0;
00439 
00440       if (keep
00441          && sort_by_size
00442          && (bfd_is_abs_section (sym->section)
00443              || bfd_is_und_section (sym->section)))
00444        keep = 0;
00445 
00446       if (keep
00447          && defined_only)
00448        {
00449          if (bfd_is_und_section (sym->section))
00450            keep = 0;
00451        }
00452 
00453       if (keep
00454          && bfd_is_target_special_symbol (abfd, sym)
00455          && ! allow_special_symbols)
00456        keep = 0;
00457 
00458       if (keep)
00459        {
00460          memcpy (to, from, size);
00461          to += size;
00462        }
00463     }
00464 
00465   return (to - (bfd_byte *) minisyms) / size;
00466 }
00467 
00468 /* These globals are used to pass information into the sorting
00469    routines.  */
00470 static bfd *sort_bfd;
00471 static bfd_boolean sort_dynamic;
00472 static asymbol *sort_x;
00473 static asymbol *sort_y;
00474 
00475 /* Symbol-sorting predicates */
00476 #define valueof(x) ((x)->section->vma + (x)->value)
00477 
00478 /* Numeric sorts.  Undefined symbols are always considered "less than"
00479    defined symbols with zero values.  Common symbols are not treated
00480    specially -- i.e., their sizes are used as their "values".  */
00481 
00482 static int
00483 non_numeric_forward (const void *P_x, const void *P_y)
00484 {
00485   asymbol *x, *y;
00486   const char *xn, *yn;
00487 
00488   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
00489   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
00490   if (x == NULL || y == NULL)
00491     bfd_fatal (bfd_get_filename (sort_bfd));
00492 
00493   xn = bfd_asymbol_name (x);
00494   yn = bfd_asymbol_name (y);
00495 
00496   if (yn == NULL)
00497     return xn != NULL;
00498   if (xn == NULL)
00499     return -1;
00500 
00501 #ifdef HAVE_STRCOLL
00502   /* Solaris 2.5 has a bug in strcoll.
00503      strcoll returns invalid values when confronted with empty strings.  */
00504   if (*yn == '\0')
00505     return *xn != '\0';
00506   if (*xn == '\0')
00507     return -1;
00508 
00509   return strcoll (xn, yn);
00510 #else
00511   return strcmp (xn, yn);
00512 #endif
00513 }
00514 
00515 static int
00516 non_numeric_reverse (const void *x, const void *y)
00517 {
00518   return - non_numeric_forward (x, y);
00519 }
00520 
00521 static int
00522 numeric_forward (const void *P_x, const void *P_y)
00523 {
00524   asymbol *x, *y;
00525   asection *xs, *ys;
00526 
00527   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
00528   y =  bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
00529   if (x == NULL || y == NULL)
00530     bfd_fatal (bfd_get_filename (sort_bfd));
00531 
00532   xs = bfd_get_section (x);
00533   ys = bfd_get_section (y);
00534 
00535   if (bfd_is_und_section (xs))
00536     {
00537       if (! bfd_is_und_section (ys))
00538        return -1;
00539     }
00540   else if (bfd_is_und_section (ys))
00541     return 1;
00542   else if (valueof (x) != valueof (y))
00543     return valueof (x) < valueof (y) ? -1 : 1;
00544 
00545   return non_numeric_forward (P_x, P_y);
00546 }
00547 
00548 static int
00549 numeric_reverse (const void *x, const void *y)
00550 {
00551   return - numeric_forward (x, y);
00552 }
00553 
00554 static int (*(sorters[2][2])) (const void *, const void *) =
00555 {
00556   { non_numeric_forward, non_numeric_reverse },
00557   { numeric_forward, numeric_reverse }
00558 };
00559 
00560 /* This sort routine is used by sort_symbols_by_size.  It is similar
00561    to numeric_forward, but when symbols have the same value it sorts
00562    by section VMA.  This simplifies the sort_symbols_by_size code
00563    which handles symbols at the end of sections.  Also, this routine
00564    tries to sort file names before other symbols with the same value.
00565    That will make the file name have a zero size, which will make
00566    sort_symbols_by_size choose the non file name symbol, leading to
00567    more meaningful output.  For similar reasons, this code sorts
00568    gnu_compiled_* and gcc2_compiled before other symbols with the same
00569    value.  */
00570 
00571 static int
00572 size_forward1 (const void *P_x, const void *P_y)
00573 {
00574   asymbol *x, *y;
00575   asection *xs, *ys;
00576   const char *xn, *yn;
00577   size_t xnl, ynl;
00578   int xf, yf;
00579 
00580   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
00581   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
00582   if (x == NULL || y == NULL)
00583     bfd_fatal (bfd_get_filename (sort_bfd));
00584 
00585   xs = bfd_get_section (x);
00586   ys = bfd_get_section (y);
00587 
00588   if (bfd_is_und_section (xs))
00589     abort ();
00590   if (bfd_is_und_section (ys))
00591     abort ();
00592 
00593   if (valueof (x) != valueof (y))
00594     return valueof (x) < valueof (y) ? -1 : 1;
00595 
00596   if (xs->vma != ys->vma)
00597     return xs->vma < ys->vma ? -1 : 1;
00598 
00599   xn = bfd_asymbol_name (x);
00600   yn = bfd_asymbol_name (y);
00601   xnl = strlen (xn);
00602   ynl = strlen (yn);
00603 
00604   /* The symbols gnu_compiled and gcc2_compiled convey even less
00605      information than the file name, so sort them out first.  */
00606 
00607   xf = (strstr (xn, "gnu_compiled") != NULL
00608        || strstr (xn, "gcc2_compiled") != NULL);
00609   yf = (strstr (yn, "gnu_compiled") != NULL
00610        || strstr (yn, "gcc2_compiled") != NULL);
00611 
00612   if (xf && ! yf)
00613     return -1;
00614   if (! xf && yf)
00615     return 1;
00616 
00617   /* We use a heuristic for the file name.  It may not work on non
00618      Unix systems, but it doesn't really matter; the only difference
00619      is precisely which symbol names get printed.  */
00620 
00621 #define file_symbol(s, sn, snl)                  \
00622   (((s)->flags & BSF_FILE) != 0                  \
00623    || ((sn)[(snl) - 2] == '.'                    \
00624        && ((sn)[(snl) - 1] == 'o'         \
00625           || (sn)[(snl) - 1] == 'a')))
00626 
00627   xf = file_symbol (x, xn, xnl);
00628   yf = file_symbol (y, yn, ynl);
00629 
00630   if (xf && ! yf)
00631     return -1;
00632   if (! xf && yf)
00633     return 1;
00634 
00635   return non_numeric_forward (P_x, P_y);
00636 }
00637 
00638 /* This sort routine is used by sort_symbols_by_size.  It is sorting
00639    an array of size_sym structures into size order.  */
00640 
00641 static int
00642 size_forward2 (const void *P_x, const void *P_y)
00643 {
00644   const struct size_sym *x = (const struct size_sym *) P_x;
00645   const struct size_sym *y = (const struct size_sym *) P_y;
00646 
00647   if (x->size < y->size)
00648     return reverse_sort ? 1 : -1;
00649   else if (x->size > y->size)
00650     return reverse_sort ? -1 : 1;
00651   else
00652     return sorters[0][reverse_sort] (x->minisym, y->minisym);
00653 }
00654 
00655 /* Sort the symbols by size.  ELF provides a size but for other formats
00656    we have to make a guess by assuming that the difference between the
00657    address of a symbol and the address of the next higher symbol is the
00658    size.  */
00659 
00660 static long
00661 sort_symbols_by_size (bfd *abfd, bfd_boolean dynamic, void *minisyms,
00662                     long symcount, unsigned int size,
00663                     struct size_sym **symsizesp)
00664 {
00665   struct size_sym *symsizes;
00666   bfd_byte *from, *fromend;
00667   asymbol *sym = NULL;
00668   asymbol *store_sym, *store_next;
00669 
00670   qsort (minisyms, symcount, size, size_forward1);
00671 
00672   /* We are going to return a special set of symbols and sizes to
00673      print.  */
00674   symsizes = xmalloc (symcount * sizeof (struct size_sym));
00675   *symsizesp = symsizes;
00676 
00677   /* Note that filter_symbols has already removed all absolute and
00678      undefined symbols.  Here we remove all symbols whose size winds
00679      up as zero.  */
00680   from = (bfd_byte *) minisyms;
00681   fromend = from + symcount * size;
00682 
00683   store_sym = sort_x;
00684   store_next = sort_y;
00685 
00686   if (from < fromend)
00687     {
00688       sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from,
00689                                   store_sym);
00690       if (sym == NULL)
00691        bfd_fatal (bfd_get_filename (abfd));
00692     }
00693 
00694   for (; from < fromend; from += size)
00695     {
00696       asymbol *next;
00697       asection *sec;
00698       bfd_vma sz;
00699       asymbol *temp;
00700 
00701       if (from + size < fromend)
00702        {
00703          next = bfd_minisymbol_to_symbol (abfd,
00704                                       dynamic,
00705                                       (const void *) (from + size),
00706                                       store_next);
00707          if (next == NULL)
00708            bfd_fatal (bfd_get_filename (abfd));
00709        }
00710       else
00711        next = NULL;
00712 
00713       sec = bfd_get_section (sym);
00714 
00715       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
00716        sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
00717       else if (bfd_is_com_section (sec))
00718        sz = sym->value;
00719       else
00720        {
00721          if (from + size < fromend
00722              && sec == bfd_get_section (next))
00723            sz = valueof (next) - valueof (sym);
00724          else
00725            sz = (bfd_get_section_vma (abfd, sec)
00726                 + bfd_section_size (abfd, sec)
00727                 - valueof (sym));
00728        }
00729 
00730       if (sz != 0)
00731        {
00732          symsizes->minisym = (const void *) from;
00733          symsizes->size = sz;
00734          ++symsizes;
00735        }
00736 
00737       sym = next;
00738 
00739       temp = store_sym;
00740       store_sym = store_next;
00741       store_next = temp;
00742     }
00743 
00744   symcount = symsizes - *symsizesp;
00745 
00746   /* We must now sort again by size.  */
00747   qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
00748 
00749   return symcount;
00750 }
00751 
00752 /* This function is used to get the relocs for a particular section.
00753    It is called via bfd_map_over_sections.  */
00754 
00755 static void
00756 get_relocs (bfd *abfd, asection *sec, void *dataarg)
00757 {
00758   struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
00759 
00760   *data->secs = sec;
00761 
00762   if ((sec->flags & SEC_RELOC) == 0)
00763     {
00764       *data->relocs = NULL;
00765       *data->relcount = 0;
00766     }
00767   else
00768     {
00769       long relsize;
00770 
00771       relsize = bfd_get_reloc_upper_bound (abfd, sec);
00772       if (relsize < 0)
00773        bfd_fatal (bfd_get_filename (abfd));
00774 
00775       *data->relocs = xmalloc (relsize);
00776       *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
00777                                           data->syms);
00778       if (*data->relcount < 0)
00779        bfd_fatal (bfd_get_filename (abfd));
00780     }
00781 
00782   ++data->secs;
00783   ++data->relocs;
00784   ++data->relcount;
00785 }
00786 
00787 /* Print a single symbol.  */
00788 
00789 static void
00790 print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
00791 {
00792   symbol_info syminfo;
00793   struct extended_symbol_info info;
00794 
00795   PROGRESS (1);
00796 
00797   format->print_symbol_filename (archive_bfd, abfd);
00798 
00799   bfd_get_symbol_info (abfd, sym, &syminfo);
00800   info.sinfo = &syminfo;
00801   info.ssize = ssize;
00802   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
00803     info.elfinfo = (elf_symbol_type *) sym;
00804   else
00805     info.elfinfo = NULL;
00806   format->print_symbol_info (&info, abfd);
00807 
00808   if (line_numbers)
00809     {
00810       static asymbol **syms;
00811       static long symcount;
00812       const char *filename, *functionname;
00813       unsigned int lineno;
00814 
00815       /* We need to get the canonical symbols in order to call
00816          bfd_find_nearest_line.  This is inefficient, but, then, you
00817          don't have to use --line-numbers.  */
00818       if (abfd != lineno_cache_bfd && syms != NULL)
00819        {
00820          free (syms);
00821          syms = NULL;
00822        }
00823       if (syms == NULL)
00824        {
00825          long symsize;
00826 
00827          symsize = bfd_get_symtab_upper_bound (abfd);
00828          if (symsize < 0)
00829            bfd_fatal (bfd_get_filename (abfd));
00830          syms = xmalloc (symsize);
00831          symcount = bfd_canonicalize_symtab (abfd, syms);
00832          if (symcount < 0)
00833            bfd_fatal (bfd_get_filename (abfd));
00834          lineno_cache_bfd = abfd;
00835        }
00836 
00837       if (bfd_is_und_section (bfd_get_section (sym)))
00838        {
00839          static asection **secs;
00840          static arelent ***relocs;
00841          static long *relcount;
00842          static unsigned int seccount;
00843          unsigned int i;
00844          const char *symname;
00845 
00846          /* For an undefined symbol, we try to find a reloc for the
00847              symbol, and print the line number of the reloc.  */
00848          if (abfd != lineno_cache_rel_bfd && relocs != NULL)
00849            {
00850              for (i = 0; i < seccount; i++)
00851               if (relocs[i] != NULL)
00852                 free (relocs[i]);
00853              free (secs);
00854              free (relocs);
00855              free (relcount);
00856              secs = NULL;
00857              relocs = NULL;
00858              relcount = NULL;
00859            }
00860 
00861          if (relocs == NULL)
00862            {
00863              struct get_relocs_info info;
00864 
00865              seccount = bfd_count_sections (abfd);
00866 
00867              secs = xmalloc (seccount * sizeof *secs);
00868              relocs = xmalloc (seccount * sizeof *relocs);
00869              relcount = xmalloc (seccount * sizeof *relcount);
00870 
00871              info.secs = secs;
00872              info.relocs = relocs;
00873              info.relcount = relcount;
00874              info.syms = syms;
00875              bfd_map_over_sections (abfd, get_relocs, (void *) &info);
00876              lineno_cache_rel_bfd = abfd;
00877            }
00878 
00879          symname = bfd_asymbol_name (sym);
00880          for (i = 0; i < seccount; i++)
00881            {
00882              long j;
00883 
00884              for (j = 0; j < relcount[i]; j++)
00885               {
00886                 arelent *r;
00887 
00888                 r = relocs[i][j];
00889                 if (r->sym_ptr_ptr != NULL
00890                     && (*r->sym_ptr_ptr)->section == sym->section
00891                     && (*r->sym_ptr_ptr)->value == sym->value
00892                     && strcmp (symname,
00893                              bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
00894                     && bfd_find_nearest_line (abfd, secs[i], syms,
00895                                           r->address, &filename,
00896                                           &functionname, &lineno)
00897                     && filename != NULL)
00898                   {
00899                     /* We only print the first one we find.  */
00900                     printf ("\t%s:%u", filename, lineno);
00901                     i = seccount;
00902                     break;
00903                   }
00904               }
00905            }
00906        }
00907       else if (bfd_get_section (sym)->owner == abfd)
00908        {
00909          if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
00910               || bfd_find_nearest_line (abfd, bfd_get_section (sym),
00911                                     syms, sym->value, &filename,
00912                                     &functionname, &lineno))
00913              && filename != NULL
00914              && lineno != 0)
00915            printf ("\t%s:%u", filename, lineno);
00916        }
00917     }
00918 
00919   putchar ('\n');
00920 }
00921 
00922 /* Print the symbols when sorting by size.  */
00923 
00924 static void
00925 print_size_symbols (bfd *abfd, bfd_boolean dynamic,
00926                   struct size_sym *symsizes, long symcount,
00927                   bfd *archive_bfd)
00928 {
00929   asymbol *store;
00930   struct size_sym *from, *fromend;
00931 
00932   store = bfd_make_empty_symbol (abfd);
00933   if (store == NULL)
00934     bfd_fatal (bfd_get_filename (abfd));
00935 
00936   from = symsizes;
00937   fromend = from + symcount;
00938   for (; from < fromend; from++)
00939     {
00940       asymbol *sym;
00941       bfd_vma ssize;
00942 
00943       sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
00944       if (sym == NULL)
00945        bfd_fatal (bfd_get_filename (abfd));
00946 
00947       /* For elf we have already computed the correct symbol size.  */
00948       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
00949        ssize = from->size;
00950       else
00951        ssize = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
00952 
00953       print_symbol (abfd, sym, ssize, archive_bfd);
00954     }
00955 }
00956 
00957 
00958 /* Print the symbols.  If ARCHIVE_BFD is non-NULL, it is the archive
00959    containing ABFD.  */
00960 
00961 static void
00962 print_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms, long symcount,
00963               unsigned int size, bfd *archive_bfd)
00964 {
00965   asymbol *store;
00966   bfd_byte *from, *fromend;
00967 
00968   store = bfd_make_empty_symbol (abfd);
00969   if (store == NULL)
00970     bfd_fatal (bfd_get_filename (abfd));
00971 
00972   from = (bfd_byte *) minisyms;
00973   fromend = from + symcount * size;
00974   for (; from < fromend; from += size)
00975     {
00976       asymbol *sym;
00977 
00978       sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
00979       if (sym == NULL)
00980        bfd_fatal (bfd_get_filename (abfd));
00981 
00982       print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
00983     }
00984 }
00985 
00986 /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.  */
00987 
00988 static void
00989 display_rel_file (bfd *abfd, bfd *archive_bfd)
00990 {
00991   long symcount;
00992   void *minisyms;
00993   unsigned int size;
00994   struct size_sym *symsizes;
00995 
00996   if (! dynamic)
00997     {
00998       if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
00999        {
01000          non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
01001          return;
01002        }
01003     }
01004 
01005   symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
01006   if (symcount < 0)
01007     bfd_fatal (bfd_get_filename (abfd));
01008 
01009   if (symcount == 0)
01010     {
01011       non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
01012       return;
01013     }
01014 
01015   if (show_synthetic && size == sizeof (asymbol *))
01016     {
01017       asymbol *synthsyms;
01018       long synth_count;
01019       asymbol **static_syms = NULL;
01020       asymbol **dyn_syms = NULL;
01021       long static_count = 0;
01022       long dyn_count = 0;
01023 
01024       if (dynamic)
01025        {
01026          dyn_count = symcount;
01027          dyn_syms = minisyms;
01028        }
01029       else
01030        {
01031          long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
01032 
01033          static_count = symcount;
01034          static_syms = minisyms;
01035 
01036          if (storage > 0)
01037            {
01038              dyn_syms = xmalloc (storage);
01039              dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms);
01040              if (dyn_count < 0)
01041               bfd_fatal (bfd_get_filename (abfd));
01042            }
01043        }
01044       synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
01045                                          dyn_count, dyn_syms, &synthsyms);
01046       if (synth_count > 0)
01047        {
01048          asymbol **symp;
01049          void *new_mini;
01050          long i;
01051 
01052          new_mini = xmalloc ((symcount + synth_count + 1) * sizeof (*symp));
01053          symp = new_mini;
01054          memcpy (symp, minisyms, symcount * sizeof (*symp));
01055          symp += symcount;
01056          for (i = 0; i < synth_count; i++)
01057            *symp++ = synthsyms + i;
01058          *symp = 0;
01059          minisyms = new_mini;
01060          symcount += synth_count;
01061        }
01062     }
01063 
01064   /* Discard the symbols we don't want to print.
01065      It's OK to do this in place; we'll free the storage anyway
01066      (after printing).  */
01067 
01068   symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
01069 
01070   symsizes = NULL;
01071   if (! no_sort)
01072     {
01073       sort_bfd = abfd;
01074       sort_dynamic = dynamic;
01075       sort_x = bfd_make_empty_symbol (abfd);
01076       sort_y = bfd_make_empty_symbol (abfd);
01077       if (sort_x == NULL || sort_y == NULL)
01078        bfd_fatal (bfd_get_filename (abfd));
01079 
01080       if (! sort_by_size)
01081        qsort (minisyms, symcount, size,
01082               sorters[sort_numerically][reverse_sort]);
01083       else
01084        symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
01085                                     size, &symsizes);
01086     }
01087 
01088   if (! sort_by_size)
01089     print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
01090   else
01091     print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
01092 
01093   free (minisyms);
01094 }
01095 
01096 static void
01097 display_archive (bfd *file)
01098 {
01099   bfd *arfile = NULL;
01100   bfd *last_arfile = NULL;
01101   char **matching;
01102 
01103   format->print_archive_filename (bfd_get_filename (file));
01104 
01105   if (print_armap)
01106     print_symdef_entry (file);
01107 
01108   for (;;)
01109     {
01110       PROGRESS (1);
01111 
01112       arfile = bfd_openr_next_archived_file (file, arfile);
01113 
01114       if (arfile == NULL)
01115        {
01116          if (bfd_get_error () != bfd_error_no_more_archived_files)
01117            bfd_fatal (bfd_get_filename (file));
01118          break;
01119        }
01120 
01121       if (bfd_check_format_matches (arfile, bfd_object, &matching))
01122        {
01123          char buf[30];
01124 
01125          bfd_sprintf_vma (arfile, buf, (bfd_vma) -1);
01126          print_width = strlen (buf);
01127          format->print_archive_member (bfd_get_filename (file),
01128                                    bfd_get_filename (arfile));
01129          display_rel_file (arfile, file);
01130        }
01131       else
01132        {
01133          bfd_nonfatal (bfd_get_filename (arfile));
01134          if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
01135            {
01136              list_matching_formats (matching);
01137              free (matching);
01138            }
01139        }
01140 
01141       if (last_arfile != NULL)
01142        {
01143          bfd_close (last_arfile);
01144          lineno_cache_bfd = NULL;
01145          lineno_cache_rel_bfd = NULL;
01146        }
01147       last_arfile = arfile;
01148     }
01149 
01150   if (last_arfile != NULL)
01151     {
01152       bfd_close (last_arfile);
01153       lineno_cache_bfd = NULL;
01154       lineno_cache_rel_bfd = NULL;
01155     }
01156 }
01157 
01158 static bfd_boolean
01159 display_file (char *filename)
01160 {
01161   bfd_boolean retval = TRUE;
01162   bfd *file;
01163   char **matching;
01164 
01165   if (get_file_size (filename) < 1)
01166     return FALSE;
01167 
01168   file = bfd_openr (filename, target);
01169   if (file == NULL)
01170     {
01171       bfd_nonfatal (filename);
01172       return FALSE;
01173     }
01174 
01175   if (bfd_check_format (file, bfd_archive))
01176     {
01177       display_archive (file);
01178     }
01179   else if (bfd_check_format_matches (file, bfd_object, &matching))
01180     {
01181       char buf[30];
01182 
01183       bfd_sprintf_vma (file, buf, (bfd_vma) -1);
01184       print_width = strlen (buf);
01185       format->print_object_filename (filename);
01186       display_rel_file (file, NULL);
01187     }
01188   else
01189     {
01190       bfd_nonfatal (filename);
01191       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
01192        {
01193          list_matching_formats (matching);
01194          free (matching);
01195        }
01196       retval = FALSE;
01197     }
01198 
01199   if (!bfd_close (file))
01200     bfd_fatal (filename);
01201 
01202   lineno_cache_bfd = NULL;
01203   lineno_cache_rel_bfd = NULL;
01204 
01205   return retval;
01206 }
01207 
01208 /* The following 3 groups of functions are called unconditionally,
01209    once at the start of processing each file of the appropriate type.
01210    They should check `filename_per_file' and `filename_per_symbol',
01211    as appropriate for their output format, to determine whether to
01212    print anything.  */
01213 
01214 /* Print the name of an object file given on the command line.  */
01215 
01216 static void
01217 print_object_filename_bsd (char *filename)
01218 {
01219   if (filename_per_file && !filename_per_symbol)
01220     printf ("\n%s:\n", filename);
01221 }
01222 
01223 static void
01224 print_object_filename_sysv (char *filename)
01225 {
01226   if (undefined_only)
01227     printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
01228   else
01229     printf (_("\n\nSymbols from %s:\n\n"), filename);
01230   if (print_width == 8)
01231     printf (_("\
01232 Name                  Value   Class        Type         Size     Line  Section\n\n"));
01233   else
01234     printf (_("\
01235 Name                  Value           Class        Type         Size             Line  Section\n\n"));
01236 }
01237 
01238 static void
01239 print_object_filename_posix (char *filename)
01240 {
01241   if (filename_per_file && !filename_per_symbol)
01242     printf ("%s:\n", filename);
01243 }
01244 
01245 /* Print the name of an archive file given on the command line.  */
01246 
01247 static void
01248 print_archive_filename_bsd (char *filename)
01249 {
01250   if (filename_per_file)
01251     printf ("\n%s:\n", filename);
01252 }
01253 
01254 static void
01255 print_archive_filename_sysv (char *filename ATTRIBUTE_UNUSED)
01256 {
01257 }
01258 
01259 static void
01260 print_archive_filename_posix (char *filename ATTRIBUTE_UNUSED)
01261 {
01262 }
01263 
01264 /* Print the name of an archive member file.  */
01265 
01266 static void
01267 print_archive_member_bsd (char *archive ATTRIBUTE_UNUSED,
01268                        const char *filename)
01269 {
01270   if (!filename_per_symbol)
01271     printf ("\n%s:\n", filename);
01272 }
01273 
01274 static void
01275 print_archive_member_sysv (char *archive, const char *filename)
01276 {
01277   if (undefined_only)
01278     printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
01279   else
01280     printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
01281   if (print_width == 8)
01282     printf (_("\
01283 Name                  Value   Class        Type         Size     Line  Section\n\n"));
01284   else
01285     printf (_("\
01286 Name                  Value           Class        Type         Size             Line  Section\n\n"));
01287 }
01288 
01289 static void
01290 print_archive_member_posix (char *archive, const char *filename)
01291 {
01292   if (!filename_per_symbol)
01293     printf ("%s[%s]:\n", archive, filename);
01294 }
01295 
01296 /* Print the name of the file (and archive, if there is one)
01297    containing a symbol.  */
01298 
01299 static void
01300 print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
01301 {
01302   if (filename_per_symbol)
01303     {
01304       if (archive_bfd)
01305        printf ("%s:", bfd_get_filename (archive_bfd));
01306       printf ("%s:", bfd_get_filename (abfd));
01307     }
01308 }
01309 
01310 static void
01311 print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
01312 {
01313   if (filename_per_symbol)
01314     {
01315       if (archive_bfd)
01316        printf ("%s:", bfd_get_filename (archive_bfd));
01317       printf ("%s:", bfd_get_filename (abfd));
01318     }
01319 }
01320 
01321 static void
01322 print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
01323 {
01324   if (filename_per_symbol)
01325     {
01326       if (archive_bfd)
01327        printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
01328               bfd_get_filename (abfd));
01329       else
01330        printf ("%s: ", bfd_get_filename (abfd));
01331     }
01332 }
01333 
01334 /* Print a symbol value.  */
01335 
01336 static void
01337 print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
01338 {
01339 #if ! defined (BFD64) || BFD_HOST_64BIT_LONG
01340   printf (value_format, val);
01341 #else
01342   /* We have a 64 bit value to print, but the host is only 32 bit.  */
01343   if (print_radix == 16)
01344     bfd_fprintf_vma (abfd, stdout, val);
01345   else
01346     {
01347       char buf[30];
01348       char *s;
01349 
01350       s = buf + sizeof buf;
01351       *--s = '\0';
01352       while (val > 0)
01353        {
01354          *--s = (val % print_radix) + '0';
01355          val /= print_radix;
01356        }
01357       while ((buf + sizeof buf - 1) - s < 16)
01358        *--s = '0';
01359       printf ("%s", s);
01360     }
01361 #endif
01362 }
01363 
01364 /* Print a line of information about a symbol.  */
01365 
01366 static void
01367 print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
01368 {
01369   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
01370     {
01371       if (print_width == 16)
01372        printf ("        ");
01373       printf ("        ");
01374     }
01375   else
01376     {
01377       /* Normally we print the value of the symbol.  If we are printing the
01378         size or sorting by size then we print its size, except for the
01379         (weird) special case where both flags are defined, in which case we
01380         print both values.  This conforms to documented behaviour.  */
01381       if (sort_by_size && !print_size)
01382        print_value (abfd, SYM_SIZE (info));
01383       else
01384        print_value (abfd, SYM_VALUE (info));
01385 
01386       if (print_size && SYM_SIZE (info))
01387        {
01388          printf (" ");
01389          print_value (abfd, SYM_SIZE (info));
01390        }
01391     }
01392 
01393   printf (" %c", SYM_TYPE (info));
01394 
01395   if (SYM_TYPE (info) == '-')
01396     {
01397       /* A stab.  */
01398       printf (" ");
01399       printf (other_format, SYM_STAB_OTHER (info));
01400       printf (" ");
01401       printf (desc_format, SYM_STAB_DESC (info));
01402       printf (" %5s", SYM_STAB_NAME (info));
01403     }
01404   print_symname (" %s", SYM_NAME (info), abfd);
01405 }
01406 
01407 static void
01408 print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
01409 {
01410   print_symname ("%-20s|", SYM_NAME (info), abfd);
01411 
01412   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
01413     {
01414       if (print_width == 8)
01415        printf ("        ");
01416       else
01417        printf ("                ");
01418     }
01419   else
01420     print_value (abfd, SYM_VALUE (info));
01421 
01422   printf ("|   %c  |", SYM_TYPE (info));
01423 
01424   if (SYM_TYPE (info) == '-')
01425     {
01426       /* A stab.  */
01427       printf ("%18s|  ", SYM_STAB_NAME (info));         /* (C) Type.  */
01428       printf (desc_format, SYM_STAB_DESC (info));       /* Size.  */
01429       printf ("|     |");                        /* Line, Section.  */
01430     }
01431   else
01432     {
01433       /* Type, Size, Line, Section */
01434       if (info->elfinfo)
01435        printf ("%18s|",
01436               get_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
01437       else
01438        printf ("                  |");
01439 
01440       if (SYM_SIZE (info))
01441        print_value (abfd, SYM_SIZE (info));
01442       else
01443        {
01444          if (print_width == 8)
01445            printf ("        ");
01446          else
01447            printf ("                ");
01448        }
01449 
01450       if (info->elfinfo)
01451        printf("|     |%s", info->elfinfo->symbol.section->name);
01452       else
01453        printf("|     |");
01454     }
01455 }
01456 
01457 static void
01458 print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
01459 {
01460   print_symname ("%s ", SYM_NAME (info), abfd);
01461   printf ("%c ", SYM_TYPE (info));
01462 
01463   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
01464     printf ("        ");
01465   else
01466     {
01467       print_value (abfd, SYM_VALUE (info));
01468       printf (" ");
01469       if (SYM_SIZE (info))
01470        print_value (abfd, SYM_SIZE (info));
01471     }
01472 }
01473 
01474 int
01475 main (int argc, char **argv)
01476 {
01477   int c;
01478   int retval;
01479 
01480 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
01481   setlocale (LC_MESSAGES, "");
01482 #endif
01483 #if defined (HAVE_SETLOCALE)
01484   setlocale (LC_CTYPE, "");
01485   setlocale (LC_COLLATE, "");
01486 #endif
01487   bindtextdomain (PACKAGE, LOCALEDIR);
01488   textdomain (PACKAGE);
01489 
01490   program_name = *argv;
01491   xmalloc_set_program_name (program_name);
01492 
01493   START_PROGRESS (program_name, 0);
01494 
01495   expandargv (&argc, &argv);
01496 
01497   bfd_init ();
01498   set_default_bfd_target ();
01499 
01500   while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
01501                         long_options, (int *) 0)) != EOF)
01502     {
01503       switch (c)
01504        {
01505        case 'a':
01506          print_debug_syms = 1;
01507          break;
01508        case 'A':
01509        case 'o':
01510          filename_per_symbol = 1;
01511          break;
01512        case 'B':            /* For MIPS compatibility.  */
01513          set_output_format ("bsd");
01514          break;
01515        case 'C':
01516          do_demangle = 1;
01517          if (optarg != NULL)
01518            {
01519              enum demangling_styles style;
01520 
01521              style = cplus_demangle_name_to_style (optarg);
01522              if (style == unknown_demangling)
01523               fatal (_("unknown demangling style `%s'"),
01524                      optarg);
01525 
01526              cplus_demangle_set_style (style);
01527            }
01528          break;
01529        case 'D':
01530          dynamic = 1;
01531          break;
01532        case 'e':
01533          /* Ignored for HP/UX compatibility.  */
01534          break;
01535        case 'f':
01536          set_output_format (optarg);
01537          break;
01538        case 'g':
01539          external_only = 1;
01540          break;
01541        case 'H':
01542        case 'h':
01543          usage (stdout, 0);
01544        case 'l':
01545          line_numbers = 1;
01546          break;
01547        case 'n':
01548        case 'v':
01549          sort_numerically = 1;
01550          break;
01551        case 'p':
01552          no_sort = 1;
01553          break;
01554        case 'P':
01555          set_output_format ("posix");
01556          break;
01557        case 'r':
01558          reverse_sort = 1;
01559          break;
01560        case 's':
01561          print_armap = 1;
01562          break;
01563        case 'S':
01564          print_size = 1;
01565          break;
01566        case 't':
01567          set_print_radix (optarg);
01568          break;
01569        case 'u':
01570          undefined_only = 1;
01571          break;
01572        case 'V':
01573          show_version = 1;
01574          break;
01575        case 'X':
01576          /* Ignored for (partial) AIX compatibility.  On AIX, the
01577             argument has values 32, 64, or 32_64, and specifies that
01578             only 32-bit, only 64-bit, or both kinds of objects should
01579             be examined.  The default is 32.  So plain AIX nm on a
01580             library archive with both kinds of objects will ignore
01581             the 64-bit ones.  For GNU nm, the default is and always
01582             has been -X 32_64, and other options are not supported.  */
01583          if (strcmp (optarg, "32_64") != 0)
01584            fatal (_("Only -X 32_64 is supported"));
01585          break;
01586 
01587        case OPTION_TARGET:  /* --target */
01588          target = optarg;
01589          break;
01590 
01591        case 0:              /* A long option that just sets a flag.  */
01592          break;
01593 
01594        default:
01595          usage (stderr, 1);
01596        }
01597     }
01598 
01599   if (show_version)
01600     print_version ("nm");
01601 
01602   if (sort_by_size && undefined_only)
01603     {
01604       non_fatal (_("Using the --size-sort and --undefined-only options together"));
01605       non_fatal (_("will produce no output, since undefined symbols have no size."));
01606       return 0;
01607     }
01608 
01609   /* OK, all options now parsed.  If no filename specified, do a.out.  */
01610   if (optind == argc)
01611     return !display_file ("a.out");
01612 
01613   retval = 0;
01614 
01615   if (argc - optind > 1)
01616     filename_per_file = 1;
01617 
01618   /* We were given several filenames to do.  */
01619   while (optind < argc)
01620     {
01621       PROGRESS (1);
01622       if (!display_file (argv[optind++]))
01623        retval++;
01624     }
01625 
01626   END_PROGRESS (program_name);
01627 
01628 #ifdef HAVE_SBRK
01629   if (show_stats)
01630     {
01631       char *lim = (char *) sbrk (0);
01632 
01633       non_fatal (_("data size %ld"), (long) (lim - (char *) &environ));
01634     }
01635 #endif
01636 
01637   exit (retval);
01638   return retval;
01639 }