Home | History | Annotate | Download | only in src
      1 /* Print symbol information from ELF file in human-readable form.
      2    Copyright (C) 2000-2008, 2009, 2011, 2012 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2000.
      5 
      6    Red Hat elfutils is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by the
      8    Free Software Foundation; version 2 of the License.
      9 
     10    Red Hat elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License along
     16    with Red Hat elfutils; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     18 
     19    Red Hat elfutils is an included package of the Open Invention Network.
     20    An included package of the Open Invention Network is a package for which
     21    Open Invention Network licensees cross-license their patents.  No patent
     22    license is granted, either expressly or impliedly, by designation as an
     23    included package.  Should you wish to participate in the Open Invention
     24    Network licensing program, please visit www.openinventionnetwork.com
     25    <http://www.openinventionnetwork.com>.  */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 # include <config.h>
     29 #endif
     30 
     31 #include <ar.h>
     32 #include <argp.h>
     33 #include <assert.h>
     34 #include <ctype.h>
     35 #include <dwarf.h>
     36 #include <errno.h>
     37 #include <error.h>
     38 #include <fcntl.h>
     39 #include <gelf.h>
     40 #include <inttypes.h>
     41 #include <libdw.h>
     42 #include <libintl.h>
     43 #include <locale.h>
     44 #include <mcheck.h>
     45 #include <obstack.h>
     46 #include <search.h>
     47 #include <stdbool.h>
     48 #include <stdio.h>
     49 #include <stdio_ext.h>
     50 #include <stdlib.h>
     51 #include <string.h>
     52 #include <unistd.h>
     53 #include <sys/param.h>
     54 
     55 #include <system.h>
     56 #include "../libebl/libeblP.h"
     57 
     58 
     59 /* Name and version of program.  */
     60 static void print_version (FILE *stream, struct argp_state *state);
     61 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
     62 
     63 /* Bug report address.  */
     64 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
     65 
     66 
     67 /* Values for the parameters which have no short form.  */
     68 #define OPT_DEFINED		0x100
     69 #define OPT_MARK_SPECIAL	0x101
     70 
     71 /* Definitions of arguments for argp functions.  */
     72 static const struct argp_option options[] =
     73 {
     74   { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
     75   { "debug-syms", 'a', NULL, 0, N_("Display debugger-only symbols"), 0 },
     76   { "defined-only", OPT_DEFINED, NULL, 0, N_("Display only defined symbols"),
     77     0 },
     78   { "dynamic", 'D', NULL, 0,
     79     N_("Display dynamic symbols instead of normal symbols"), 0 },
     80   { "extern-only", 'g', NULL, 0, N_("Display only external symbols"), 0 },
     81   { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols"), 0 },
     82   { "print-armap", 's', NULL, 0,
     83     N_("Include index for symbols from archive members"), 0 },
     84 
     85   { NULL, 0, NULL, 0, N_("Output format:"), 0 },
     86   { "print-file-name", 'A', NULL, 0,
     87     N_("Print name of the input file before every symbol"), 0 },
     88   { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A", 0 },
     89   { "format", 'f', "FORMAT", 0,
     90     N_("Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The default is `sysv'"),
     91     0 },
     92   { NULL, 'B', NULL, 0, N_("Same as --format=bsd"), 0 },
     93   { "portability", 'P', NULL, 0, N_("Same as --format=posix"), 0 },
     94   { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values"), 0 },
     95   { "mark-special", OPT_MARK_SPECIAL, NULL, 0, N_("Mark special symbols"), 0 },
     96   { "mark-weak", OPT_MARK_SPECIAL, NULL, OPTION_HIDDEN, "", 0 },
     97   { "print-size", 'S', NULL, 0, N_("Print size of defined symbols"), 0 },
     98 
     99   { NULL, 0, NULL, 0, N_("Output options:"), 0 },
    100   { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address"),
    101     0 },
    102   { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols"), 0 },
    103   { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort"), 0 },
    104 #ifdef USE_DEMANGLE
    105   { "demangle", 'C', NULL, 0,
    106     N_("Decode low-level symbol names into source code names"), 0 },
    107 #endif
    108   { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
    109   { NULL, 0, NULL, 0, NULL, 0 }
    110 };
    111 
    112 /* Short description of program.  */
    113 static const char doc[] = N_("List symbols from FILEs (a.out by default).");
    114 
    115 /* Strings for arguments in help texts.  */
    116 static const char args_doc[] = N_("[FILE...]");
    117 
    118 /* Prototype for option handler.  */
    119 static error_t parse_opt (int key, char *arg, struct argp_state *state);
    120 
    121 /* Parser children.  */
    122 static struct argp_child argp_children[] =
    123   {
    124     { &color_argp, 0, N_("Output formatting"), 2 },
    125     { NULL, 0, NULL, 0}
    126   };
    127 
    128 /* Data structure to communicate with argp functions.  */
    129 static struct argp argp =
    130 {
    131   options, parse_opt, args_doc, doc, argp_children, NULL, NULL
    132 };
    133 
    134 
    135 /* Print symbols in file named FNAME.  */
    136 static int process_file (const char *fname, bool more_than_one);
    137 
    138 /* Handle content of archive.  */
    139 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
    140 		      const char *suffix);
    141 
    142 /* Handle ELF file.  */
    143 static int handle_elf (Elf *elf, const char *prefix, const char *fname,
    144 		       const char *suffix);
    145 
    146 
    147 #define INTERNAL_ERROR(fname) \
    148   error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"),      \
    149 	 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
    150 
    151 
    152 /* Internal representation of symbols.  */
    153 typedef struct GElf_SymX
    154 {
    155   GElf_Sym sym;
    156   Elf32_Word xndx;
    157   char *where;
    158 } GElf_SymX;
    159 
    160 
    161 /* User-selectable options.  */
    162 
    163 /* The selected output format.  */
    164 static enum
    165 {
    166   format_sysv = 0,
    167   format_bsd,
    168   format_posix
    169 } format;
    170 
    171 /* Print defined, undefined, or both?  */
    172 static bool hide_undefined;
    173 static bool hide_defined;
    174 
    175 /* Print local symbols also?  */
    176 static bool hide_local;
    177 
    178 /* Nonzero if full filename should precede every symbol.  */
    179 static bool print_file_name;
    180 
    181 /* If true print size of defined symbols in BSD format.  */
    182 static bool print_size;
    183 
    184 /* If true print archive index.  */
    185 static bool print_armap;
    186 
    187 /* If true reverse sorting.  */
    188 static bool reverse_sort;
    189 
    190 #ifdef USE_DEMANGLE
    191 /* If true demangle symbols.  */
    192 static bool demangle;
    193 #endif
    194 
    195 /* Type of the section we are printing.  */
    196 static GElf_Word symsec_type = SHT_SYMTAB;
    197 
    198 /* Sorting selection.  */
    199 static enum
    200 {
    201   sort_name = 0,
    202   sort_numeric,
    203   sort_nosort
    204 } sort;
    205 
    206 /* Radix for printed numbers.  */
    207 static enum
    208 {
    209   radix_hex = 0,
    210   radix_decimal,
    211   radix_octal
    212 } radix;
    213 
    214 /* If nonzero mark special symbols:
    215    - weak symbols are distinguished from global symbols by adding
    216      a `*' after the identifying letter for the symbol class and type.
    217    - TLS symbols are distinguished from normal symbols by adding
    218      a '@' after the identifying letter for the symbol class and type.  */
    219 static bool mark_special;
    220 
    221 
    222 int
    223 main (int argc, char *argv[])
    224 {
    225   int remaining;
    226   int result = 0;
    227 
    228   /* Make memory leak detection possible.  */
    229   mtrace ();
    230 
    231   /* We use no threads here which can interfere with handling a stream.  */
    232   (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
    233   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
    234   (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
    235 
    236   /* Set locale.  */
    237   (void) setlocale (LC_ALL, "");
    238 
    239   /* Make sure the message catalog can be found.  */
    240   (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
    241 
    242   /* Initialize the message catalog.  */
    243   (void) textdomain (PACKAGE_TARNAME);
    244 
    245   /* Parse and process arguments.  */
    246   (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
    247 
    248   /* Tell the library which version we are expecting.  */
    249   (void) elf_version (EV_CURRENT);
    250 
    251   if (remaining == argc)
    252     /* The user didn't specify a name so we use a.out.  */
    253     result = process_file ("a.out", false);
    254   else
    255     {
    256       /* Process all the remaining files.  */
    257       const bool more_than_one = remaining + 1 < argc;
    258 
    259       do
    260 	result |= process_file (argv[remaining], more_than_one);
    261       while (++remaining < argc);
    262     }
    263 
    264   return result;
    265 }
    266 
    267 
    268 /* Print the version information.  */
    269 static void
    270 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
    271 {
    272   fprintf (stream, "nm (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
    273   fprintf (stream, gettext ("\
    274 Copyright (C) %s Red Hat, Inc.\n\
    275 This is free software; see the source for copying conditions.  There is NO\n\
    276 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    277 "), "2012");
    278   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
    279 }
    280 
    281 
    282 /* Handle program arguments.  */
    283 static error_t
    284 parse_opt (int key, char *arg,
    285 	   struct argp_state *state __attribute__ ((unused)))
    286 {
    287   switch (key)
    288     {
    289     case 'a':
    290       /* XXX */
    291       break;
    292 
    293 #ifdef USE_DEMANGLE
    294     case 'C':
    295       demangle = true;
    296       break;
    297 #endif
    298 
    299     case 'f':
    300       if (strcmp (arg, "bsd") == 0)
    301 	format = format_bsd;
    302       else if (strcmp (arg, "posix") == 0)
    303 	format = format_posix;
    304       else
    305 	/* Be bug compatible.  The BFD implementation also defaulted to
    306 	   using the SysV format if nothing else matches.  */
    307 	format = format_sysv;
    308       break;
    309 
    310     case 'g':
    311       hide_local = true;
    312       break;
    313 
    314     case 'n':
    315       sort = sort_numeric;
    316       break;
    317 
    318     case 'p':
    319       sort = sort_nosort;
    320       break;
    321 
    322     case 't':
    323       if (strcmp (arg, "10") == 0 || strcmp (arg, "d") == 0)
    324 	radix = radix_decimal;
    325       else if (strcmp (arg, "8") == 0 || strcmp (arg, "o") == 0)
    326 	radix = radix_octal;
    327       else
    328 	radix = radix_hex;
    329       break;
    330 
    331     case 'u':
    332       hide_undefined = false;
    333       hide_defined = true;
    334       break;
    335 
    336     case 'A':
    337     case 'o':
    338       print_file_name = true;
    339       break;
    340 
    341     case 'B':
    342       format = format_bsd;
    343       break;
    344 
    345     case 'D':
    346       symsec_type = SHT_DYNSYM;
    347       break;
    348 
    349     case 'P':
    350       format = format_posix;
    351       break;
    352 
    353     case OPT_DEFINED:
    354       hide_undefined = true;
    355       hide_defined = false;
    356       break;
    357 
    358     case OPT_MARK_SPECIAL:
    359       mark_special = true;
    360       break;
    361 
    362     case 'S':
    363       print_size = true;
    364       break;
    365 
    366     case 's':
    367       print_armap = true;
    368       break;
    369 
    370     case 'r':
    371       reverse_sort = true;
    372       break;
    373 
    374     default:
    375       return ARGP_ERR_UNKNOWN;
    376     }
    377   return 0;
    378 }
    379 
    380 
    381 /* Open the file and determine the type.  */
    382 static int
    383 process_file (const char *fname, bool more_than_one)
    384 {
    385   /* Open the file.  */
    386   int fd = open (fname, O_RDONLY);
    387   if (fd == -1)
    388     {
    389       error (0, errno, gettext ("cannot open '%s'"), fname);
    390       return 1;
    391     }
    392 
    393   /* Now get the ELF descriptor.  */
    394   Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
    395   if (elf != NULL)
    396     {
    397       if (elf_kind (elf) == ELF_K_ELF)
    398 	{
    399 	  int result = handle_elf (elf, more_than_one ? "" : NULL,
    400 				   fname, NULL);
    401 
    402 	  if (elf_end (elf) != 0)
    403 	    INTERNAL_ERROR (fname);
    404 
    405 	  if (close (fd) != 0)
    406 	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
    407 
    408 	  return result;
    409 	}
    410       else if (elf_kind (elf) == ELF_K_AR)
    411 	{
    412 	  int result = handle_ar (fd, elf, NULL, fname, NULL);
    413 
    414 	  if (elf_end (elf) != 0)
    415 	    INTERNAL_ERROR (fname);
    416 
    417 	  if (close (fd) != 0)
    418 	    error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
    419 
    420 	  return result;
    421 	}
    422 
    423       /* We cannot handle this type.  Close the descriptor anyway.  */
    424       if (elf_end (elf) != 0)
    425 	INTERNAL_ERROR (fname);
    426     }
    427 
    428   error (0, 0, gettext ("%s: File format not recognized"), fname);
    429 
    430   return 1;
    431 }
    432 
    433 
    434 static int
    435 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
    436 	   const char *suffix)
    437 {
    438   size_t fname_len = strlen (fname) + 1;
    439   size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
    440   char new_prefix[prefix_len + fname_len + 2];
    441   size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
    442   char new_suffix[suffix_len + 2];
    443   Elf *subelf;
    444   Elf_Cmd cmd = ELF_C_READ_MMAP;
    445   int result = 0;
    446 
    447   char *cp = new_prefix;
    448   if (prefix != NULL)
    449     cp = stpcpy (cp, prefix);
    450   cp = stpcpy (cp, fname);
    451   stpcpy (cp, "[");
    452 
    453   cp = new_suffix;
    454   if (suffix != NULL)
    455     cp = stpcpy (cp, suffix);
    456   stpcpy (cp, "]");
    457 
    458   /* First print the archive index if this is wanted.  */
    459   if (print_armap)
    460     {
    461       Elf_Arsym *arsym = elf_getarsym (elf, NULL);
    462 
    463       if (arsym != NULL)
    464 	{
    465 	  Elf_Arhdr *arhdr = NULL;
    466 	  size_t arhdr_off = 0;	/* Note: 0 is no valid offset.  */
    467 
    468 	  fputs_unlocked (gettext("\nArchive index:\n"), stdout);
    469 
    470 	  while (arsym->as_off != 0)
    471 	    {
    472 	      if (arhdr_off != arsym->as_off
    473 		  && (elf_rand (elf, arsym->as_off) != arsym->as_off
    474 		      || (subelf = elf_begin (fd, cmd, elf)) == NULL
    475 		      || (arhdr = elf_getarhdr (subelf)) == NULL))
    476 		{
    477 		  error (0, 0, gettext ("invalid offset %zu for symbol %s"),
    478 			 arsym->as_off, arsym->as_name);
    479 		  continue;
    480 		}
    481 
    482 	      printf (gettext ("%s in %s\n"), arsym->as_name, arhdr->ar_name);
    483 
    484 	      ++arsym;
    485 	    }
    486 
    487 	  if (elf_rand (elf, SARMAG) != SARMAG)
    488 	    {
    489 	      error (0, 0,
    490 		     gettext ("cannot reset archive offset to beginning"));
    491 	      return 1;
    492 	    }
    493 	}
    494     }
    495 
    496   /* Process all the files contained in the archive.  */
    497   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
    498     {
    499       /* The the header for this element.  */
    500       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
    501 
    502       /* Skip over the index entries.  */
    503       if (strcmp (arhdr->ar_name, "/") != 0
    504 	  && strcmp (arhdr->ar_name, "//") != 0)
    505 	{
    506 	  if (elf_kind (subelf) == ELF_K_ELF)
    507 	    result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
    508 				  new_suffix);
    509 	  else if (elf_kind (subelf) == ELF_K_AR)
    510 	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
    511 				 new_suffix);
    512 	  else
    513 	    {
    514 	      error (0, 0, gettext ("%s%s%s: file format not recognized"),
    515 		     new_prefix, arhdr->ar_name, new_suffix);
    516 	      result = 1;
    517 	    }
    518 	}
    519 
    520       /* Get next archive element.  */
    521       cmd = elf_next (subelf);
    522       if (elf_end (subelf) != 0)
    523 	INTERNAL_ERROR (fname);
    524     }
    525 
    526   return result;
    527 }
    528 
    529 
    530 /* Mapping of radix and binary class to length.  */
    531 static const int length_map[2][3] =
    532 {
    533   [ELFCLASS32 - 1] =
    534   {
    535     [radix_hex] = 8,
    536     [radix_decimal] = 10,
    537     [radix_octal] = 11
    538   },
    539   [ELFCLASS64 - 1] =
    540   {
    541     [radix_hex] = 16,
    542     [radix_decimal] = 20,
    543     [radix_octal] = 22
    544   }
    545 };
    546 
    547 
    548 static int
    549 global_compare (const void *p1, const void *p2)
    550 {
    551   const Dwarf_Global *g1 = (const Dwarf_Global *) p1;
    552   const Dwarf_Global *g2 = (const Dwarf_Global *) p2;
    553 
    554   return strcmp (g1->name, g2->name);
    555 }
    556 
    557 
    558 static void *global_root;
    559 
    560 
    561 static int
    562 get_global (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
    563 	    void *arg __attribute__ ((unused)))
    564 {
    565   tsearch (memcpy (xmalloc (sizeof (Dwarf_Global)), global,
    566 		   sizeof (Dwarf_Global)),
    567 	   &global_root, global_compare);
    568 
    569   return DWARF_CB_OK;
    570 }
    571 
    572 
    573 struct local_name
    574 {
    575   const char *name;
    576   const char *file;
    577   Dwarf_Word lineno;
    578   Dwarf_Addr lowpc;
    579   Dwarf_Addr highpc;
    580 };
    581 
    582 
    583 static int
    584 local_compare (const void *p1, const void *p2)
    585 {
    586   struct local_name *g1 = (struct local_name *) p1;
    587   struct local_name *g2 = (struct local_name *) p2;
    588   int result;
    589 
    590   result = strcmp (g1->name, g2->name);
    591   if (result == 0)
    592     {
    593       if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
    594 	{
    595 	  /* g2 is contained in g1.  Update the data.  */
    596 	  g2->lowpc = g1->lowpc;
    597 	  g2->highpc = g1->highpc;
    598 	  result = 0;
    599 	}
    600       else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
    601 	{
    602 	  /* g1 is contained in g2.  Update the data.  */
    603 	  g1->lowpc = g2->lowpc;
    604 	  g1->highpc = g2->highpc;
    605 	  result = 0;
    606 	}
    607       else
    608 	result = g1->lowpc < g2->lowpc ? -1 : 1;
    609     }
    610 
    611   return result;
    612 }
    613 
    614 
    615 static int
    616 get_var_range (Dwarf_Die *die, Dwarf_Word *lowpc, Dwarf_Word *highpc)
    617 {
    618   Dwarf_Attribute locattr_mem;
    619   Dwarf_Attribute *locattr = dwarf_attr (die, DW_AT_location, &locattr_mem);
    620   if  (locattr == NULL)
    621     return 1;
    622 
    623   Dwarf_Op *loc;
    624   size_t nloc;
    625   if (dwarf_getlocation (locattr, &loc, &nloc) != 0)
    626     return 1;
    627 
    628   /* Interpret the location expressions.  */
    629   // XXX For now just the simple one:
    630   if (nloc == 1 && loc[0].atom == DW_OP_addr)
    631     {
    632       *lowpc = *highpc = loc[0].number;
    633       return 0;
    634     }
    635 
    636   return 1;
    637 }
    638 
    639 
    640 
    641 static void *local_root;
    642 
    643 
    644 static void
    645 get_local_names (Dwarf *dbg)
    646 {
    647   Dwarf_Off offset = 0;
    648   Dwarf_Off old_offset;
    649   size_t hsize;
    650 
    651   while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL,
    652 		       NULL) == 0)
    653     {
    654       Dwarf_Die cudie_mem;
    655       Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
    656 
    657       /* If we cannot get the CU DIE there is no need to go on with
    658 	 this CU.  */
    659       if (cudie == NULL)
    660 	continue;
    661       /* This better be a CU DIE.  */
    662       if (dwarf_tag (cudie) != DW_TAG_compile_unit)
    663 	continue;
    664 
    665       /* Get the line information.  */
    666       Dwarf_Files *files;
    667       size_t nfiles;
    668       if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
    669 	continue;
    670 
    671       Dwarf_Die die_mem;
    672       Dwarf_Die *die = &die_mem;
    673       if (dwarf_child (cudie, die) == 0)
    674 	/* Iterate over all immediate children of the CU DIE.  */
    675 	do
    676 	  {
    677 	    int tag = dwarf_tag (die);
    678 	    if (tag != DW_TAG_subprogram && tag != DW_TAG_variable)
    679 	      continue;
    680 
    681 	    /* We are interested in five attributes: name, decl_file,
    682 	       decl_line, low_pc, and high_pc.  */
    683 	    Dwarf_Attribute attr_mem;
    684 	    Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
    685 	    const char *name = dwarf_formstring (attr);
    686 	    if (name == NULL)
    687 	      continue;
    688 
    689 	    Dwarf_Word fileidx;
    690 	    attr = dwarf_attr (die, DW_AT_decl_file, &attr_mem);
    691 	    if (dwarf_formudata (attr, &fileidx) != 0 || fileidx >= nfiles)
    692 	      continue;
    693 
    694 	    Dwarf_Word lineno;
    695 	    attr = dwarf_attr (die, DW_AT_decl_line, &attr_mem);
    696 	    if (dwarf_formudata (attr, &lineno) != 0 || lineno == 0)
    697 	      continue;
    698 
    699 	    Dwarf_Addr lowpc;
    700 	    Dwarf_Addr highpc;
    701 	    if (tag == DW_TAG_subprogram)
    702 	      {
    703 		if (dwarf_lowpc (die, &lowpc) != 0
    704 		    || dwarf_highpc (die, &highpc) != 0)
    705 		  continue;
    706 	      }
    707 	    else
    708 	      {
    709 		if (get_var_range (die, &lowpc, &highpc) != 0)
    710 		  continue;
    711 	      }
    712 
    713 	    /* We have all the information.  Create a record.  */
    714 	    struct local_name *newp
    715 	      = (struct local_name *) xmalloc (sizeof (*newp));
    716 	    newp->name = name;
    717 	    newp->file = dwarf_filesrc (files, fileidx, NULL, NULL);
    718 	    newp->lineno = lineno;
    719 	    newp->lowpc = lowpc;
    720 	    newp->highpc = highpc;
    721 
    722 	    /* Since we cannot deallocate individual memory we do not test
    723 	       for duplicates in the tree.  This should not happen anyway.  */
    724 	    if (tsearch (newp, &local_root, local_compare) == NULL)
    725 	      error (EXIT_FAILURE, errno,
    726 		     gettext ("cannot create search tree"));
    727 	  }
    728 	while (dwarf_siblingof (die, die) == 0);
    729     }
    730 }
    731 
    732 /* Do elf_strptr, but return a backup string and never NULL.  */
    733 static const char *
    734 sym_name (Elf *elf, GElf_Word strndx, GElf_Word st_name, char buf[], size_t n)
    735 {
    736   const char *symstr = elf_strptr (elf, strndx, st_name);
    737   if (symstr == NULL)
    738     {
    739       snprintf (buf, n, "[invalid st_name %#" PRIx32 "]", st_name);
    740       symstr = buf;
    741     }
    742   return symstr;
    743 }
    744 
    745 /* Show symbols in SysV format.  */
    746 static void
    747 show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
    748 		   GElf_SymX *syms, size_t nsyms, int longest_name,
    749 		   int longest_where)
    750 {
    751   size_t shnum;
    752   if (elf_getshdrnum (ebl->elf, &shnum) < 0)
    753     INTERNAL_ERROR (fullname);
    754 
    755   bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024;
    756   const char **scnnames;
    757   if (scnnames_malloced)
    758     scnnames = (const char **) xmalloc (sizeof (const char *) * shnum);
    759   else
    760     scnnames = (const char **) alloca (sizeof (const char *) * shnum);
    761   /* Get the section header string table index.  */
    762   size_t shstrndx;
    763   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
    764     error (EXIT_FAILURE, 0,
    765 	   gettext ("cannot get section header string table index"));
    766 
    767   /* Cache the section names.  */
    768   Elf_Scn *scn = NULL;
    769   size_t cnt = 1;
    770   while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
    771     {
    772       GElf_Shdr shdr_mem;
    773 
    774       assert (elf_ndxscn (scn) == cnt++);
    775 
    776       char *name = elf_strptr (ebl->elf, shstrndx,
    777 			       gelf_getshdr (scn, &shdr_mem)->sh_name);
    778       if (unlikely (name == NULL))
    779 	{
    780 	  name = alloca (sizeof "[invalid sh_name 0x12345678]");
    781 	  snprintf (name, sizeof name, "[invalid sh_name %#" PRIx32 "]",
    782 		    gelf_getshdr (scn, &shdr_mem)->sh_name);
    783 	}
    784       scnnames[elf_ndxscn (scn)] = name;
    785     }
    786 
    787   int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
    788 
    789   /* We always print this prolog.  */
    790   printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
    791 
    792   /* The header line.  */
    793   printf (gettext ("%*s%-*s %-*s Class  Type     %-*s %*s Section\n\n"),
    794 	  print_file_name ? (int) strlen (fullname) + 1: 0, "",
    795 	  longest_name, sgettext ("sysv|Name"),
    796 	  /* TRANS: the "sysv|" parts makes the string unique.  */
    797 	  digits, sgettext ("sysv|Value"),
    798 	  /* TRANS: the "sysv|" parts makes the string unique.  */
    799 	  digits, sgettext ("sysv|Size"),
    800 	  /* TRANS: the "sysv|" parts makes the string unique.  */
    801 	  longest_where, sgettext ("sysv|Line"));
    802 
    803   /* Which format string to use (different radix for numbers).  */
    804   const char *number_fmtstr;
    805   if (radix == radix_hex)
    806     number_fmtstr = "%0*" PRIx64;
    807   else if (radix == radix_decimal)
    808     number_fmtstr = "%0*" PRId64;
    809   else
    810     number_fmtstr = "%0*" PRIo64;
    811 
    812 #ifdef USE_DEMANGLE
    813   size_t demangle_buffer_len = 0;
    814   char *demangle_buffer = NULL;
    815 #endif
    816 
    817   /* Iterate over all symbols.  */
    818   for (cnt = 1; cnt < nsyms; ++cnt)
    819     {
    820       /* In this format SECTION entries are not printed.  */
    821       if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
    822 	continue;
    823 
    824       char symstrbuf[50];
    825       const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
    826 				     symstrbuf, sizeof symstrbuf);
    827 
    828 #ifdef USE_DEMANGLE
    829       /* Demangle if necessary.  */
    830       if (demangle)
    831 	{
    832 	  int status = -1;
    833 	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
    834 					   &demangle_buffer_len, &status);
    835 
    836 	  if (status == 0)
    837 	    symstr = dmsymstr;
    838 	}
    839 #endif
    840 
    841       char symbindbuf[50];
    842       char symtypebuf[50];
    843       char secnamebuf[1024];
    844       char addressbuf[(64 + 2) / 3 + 1];
    845       char sizebuf[(64 + 2) / 3 + 1];
    846 
    847       /* If we have to precede the line with the file name.  */
    848       if (print_file_name)
    849 	{
    850 	  fputs_unlocked (fullname, stdout);
    851 	  putchar_unlocked (':');
    852 	}
    853 
    854       /* Covert the address.  */
    855       if (syms[cnt].sym.st_shndx == SHN_UNDEF)
    856 	addressbuf[0] = sizebuf[0] = '\0';
    857       else
    858 	{
    859 	  snprintf (addressbuf, sizeof (addressbuf), number_fmtstr,
    860 		    digits, syms[cnt].sym.st_value);
    861 	  snprintf (sizebuf, sizeof (sizebuf), number_fmtstr,
    862 		    digits, syms[cnt].sym.st_size);
    863 	}
    864 
    865       /* Print the actual string.  */
    866       printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
    867 	      longest_name, symstr, addressbuf,
    868 	      ebl_symbol_binding_name (ebl,
    869 				       GELF_ST_BIND (syms[cnt].sym.st_info),
    870 				       symbindbuf, sizeof (symbindbuf)),
    871 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
    872 				    symtypebuf, sizeof (symtypebuf)),
    873 	      sizebuf, longest_where, syms[cnt].where,
    874 	      ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
    875 				secnamebuf, sizeof (secnamebuf), scnnames,
    876 				shnum));
    877     }
    878 
    879 #ifdef USE_DEMANGLE
    880   free (demangle_buffer);
    881 #endif
    882 
    883   if (scnnames_malloced)
    884     free (scnnames);
    885 }
    886 
    887 
    888 static char
    889 class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
    890 {
    891   int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
    892 
    893   /* XXX Add support for architecture specific types and classes.  */
    894   if (sym->st_shndx == SHN_ABS)
    895     return local_p ? 'a' : 'A';
    896 
    897   if (sym->st_shndx == SHN_UNDEF)
    898     /* Undefined symbols must be global.  */
    899     return 'U';
    900 
    901   char result = "NDTSFBD         "[GELF_ST_TYPE (sym->st_info)];
    902 
    903   if (result == 'D')
    904     {
    905       /* Special handling: unique data symbols.  */
    906       if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
    907 	  && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
    908 	result = 'u';
    909       else
    910 	{
    911 	  GElf_Shdr shdr_mem;
    912 	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
    913 					  &shdr_mem);
    914 	  if (shdr != NULL)
    915 	    {
    916 	      if ((shdr->sh_flags & SHF_WRITE) == 0)
    917 		result = 'R';
    918 	      else if (shdr->sh_type == SHT_NOBITS)
    919 		result = 'B';
    920 	    }
    921 	}
    922     }
    923 
    924   return local_p ? tolower (result) : result;
    925 }
    926 
    927 
    928 static void
    929 show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
    930 		  const char *prefix, const char *fname, const char *fullname,
    931 		  GElf_SymX *syms, size_t nsyms)
    932 {
    933   int digits = length_map[gelf_getclass (elf) - 1][radix];
    934 
    935   if (prefix != NULL && ! print_file_name)
    936     printf ("\n%s:\n", fname);
    937 
    938   static const char *const fmtstrs[] =
    939     {
    940       [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %9$s%3$c%4$s %5$s",
    941       [radix_decimal] = "%8$s%*" PRId64 "%10$s %9$s%3$c%4$s %5$s",
    942       [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %9$s%3$c%4$s %5$s"
    943     };
    944   static const char *const sfmtstrs[] =
    945     {
    946       [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %7$0*6$" PRIx64 " %9$s%3$c%4$s %5$s",
    947       [radix_decimal] = "%8$s%2$*1$" PRId64 "%10$s %7$*6$" PRId64 " %9$s%3$c%4$s %5$s",
    948       [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %7$0*6$" PRIo64 " %9$s%3$c%4$s %5$s"
    949     };
    950 
    951 #ifdef USE_DEMANGLE
    952   size_t demangle_buffer_len = 0;
    953   char *demangle_buffer = NULL;
    954 #endif
    955 
    956   /* Iterate over all symbols.  */
    957   for (size_t cnt = 0; cnt < nsyms; ++cnt)
    958     {
    959       char symstrbuf[50];
    960       const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
    961 				     symstrbuf, sizeof symstrbuf);
    962 
    963       /* Printing entries with a zero-length name makes the output
    964 	 not very well parseable.  Since these entries don't carry
    965 	 much information we leave them out.  */
    966       if (symstr[0] == '\0')
    967 	continue;
    968 
    969       /* We do not print the entries for files.  */
    970       if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
    971 	continue;
    972 
    973 #ifdef USE_DEMANGLE
    974       /* Demangle if necessary.  */
    975       if (demangle)
    976 	{
    977 	  int status = -1;
    978 	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
    979 					   &demangle_buffer_len, &status);
    980 
    981 	  if (status == 0)
    982 	    symstr = dmsymstr;
    983 	}
    984 #endif
    985 
    986       /* If we have to precede the line with the file name.  */
    987       if (print_file_name)
    988 	{
    989 	  fputs_unlocked (fullname, stdout);
    990 	  putchar_unlocked (':');
    991 	}
    992 
    993       bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
    994       bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
    995       const char *marker = (mark_special
    996 			    ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
    997 
    998       if (syms[cnt].sym.st_shndx == SHN_UNDEF)
    999 	{
   1000 	  const char *color = "";
   1001 	  if (color_mode)
   1002 	    {
   1003 	      if (is_tls)
   1004 		color = color_undef_tls;
   1005 	      else if (is_weak)
   1006 		color = color_undef_weak;
   1007 	      else
   1008 		color = color_undef;
   1009 	    }
   1010 
   1011 	  printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
   1012 	}
   1013       else
   1014 	{
   1015 	  const char *color = "";
   1016 	  if (color_mode)
   1017 	    {
   1018 	      if (is_tls)
   1019 		color = color_tls;
   1020 	      else if (is_weak)
   1021 		color = color_weak;
   1022 	      else
   1023 		color = color_symbol;
   1024 	    }
   1025 
   1026 	  printf (print_size && syms[cnt].sym.st_size != 0
   1027 		  ? sfmtstrs[radix] : fmtstrs[radix],
   1028 		  digits, syms[cnt].sym.st_value,
   1029 		  class_type_char (elf, ehdr, &syms[cnt].sym), marker,
   1030 		  symstr,
   1031 		  digits, (uint64_t) syms[cnt].sym.st_size,
   1032 		  color_mode ? color_address : "",
   1033 		  color,
   1034 		  color_mode ? color_off : "");
   1035 	}
   1036 
   1037       if (color_mode)
   1038 	fputs_unlocked (color_off, stdout);
   1039       putchar_unlocked ('\n');
   1040     }
   1041 
   1042 #ifdef USE_DEMANGLE
   1043   free (demangle_buffer);
   1044 #endif
   1045 }
   1046 
   1047 
   1048 static void
   1049 show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
   1050 		    const char *prefix, const char *fullname, GElf_SymX *syms,
   1051 		    size_t nsyms)
   1052 {
   1053   if (prefix != NULL && ! print_file_name)
   1054     printf ("%s:\n", fullname);
   1055 
   1056   const char *fmtstr;
   1057   if (radix == radix_hex)
   1058     fmtstr = "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n";
   1059   else if (radix == radix_decimal)
   1060     fmtstr = "%s %c%s %*" PRId64 " %*" PRId64 "\n";
   1061   else
   1062     fmtstr = "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n";
   1063 
   1064   int digits = length_map[gelf_getclass (elf) - 1][radix];
   1065 
   1066 #ifdef USE_DEMANGLE
   1067   size_t demangle_buffer_len = 0;
   1068   char *demangle_buffer = NULL;
   1069 #endif
   1070 
   1071   /* Iterate over all symbols.  */
   1072   for (size_t cnt = 0; cnt < nsyms; ++cnt)
   1073     {
   1074       char symstrbuf[50];
   1075       const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
   1076 				     symstrbuf, sizeof symstrbuf);
   1077 
   1078       /* Printing entries with a zero-length name makes the output
   1079 	 not very well parseable.  Since these entries don't carry
   1080 	 much information we leave them out.  */
   1081       if (symstr[0] == '\0')
   1082 	continue;
   1083 
   1084 #ifdef USE_DEMANGLE
   1085       /* Demangle if necessary.  */
   1086       if (demangle)
   1087 	{
   1088 	  int status = -1;
   1089 	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
   1090 					   &demangle_buffer_len, &status);
   1091 
   1092 	  if (status == 0)
   1093 	    symstr = dmsymstr;
   1094 	}
   1095 #endif
   1096 
   1097       /* If we have to precede the line with the file name.  */
   1098       if (print_file_name)
   1099 	{
   1100 	  fputs_unlocked (fullname, stdout);
   1101 	  putchar_unlocked (':');
   1102 	  putchar_unlocked (' ');
   1103 	}
   1104 
   1105       printf (fmtstr,
   1106 	      symstr,
   1107 	      class_type_char (elf, ehdr, &syms[cnt].sym),
   1108 	      mark_special
   1109 	      ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
   1110 		 ? "@"
   1111 		 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
   1112 		    ? "*" : " "))
   1113 	      : "",
   1114 	      digits, syms[cnt].sym.st_value,
   1115 	      digits, syms[cnt].sym.st_size);
   1116     }
   1117 
   1118 #ifdef USE_DEMANGLE
   1119   free (demangle_buffer);
   1120 #endif
   1121 }
   1122 
   1123 
   1124 /* Maximum size of memory we allocate on the stack.  */
   1125 #define MAX_STACK_ALLOC	65536
   1126 
   1127 static int
   1128 sort_by_address (const void *p1, const void *p2)
   1129 {
   1130   GElf_SymX *s1 = (GElf_SymX *) p1;
   1131   GElf_SymX *s2 = (GElf_SymX *) p2;
   1132 
   1133   int result = (s1->sym.st_value < s2->sym.st_value
   1134 		? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
   1135 
   1136   return reverse_sort ? -result : result;
   1137 }
   1138 
   1139 static Elf_Data *sort_by_name_strtab;
   1140 
   1141 static int
   1142 sort_by_name (const void *p1, const void *p2)
   1143 {
   1144   GElf_SymX *s1 = (GElf_SymX *) p1;
   1145   GElf_SymX *s2 = (GElf_SymX *) p2;
   1146 
   1147   const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
   1148   const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
   1149 
   1150   int result = strcmp (n1, n2);
   1151 
   1152   return reverse_sort ? -result : result;
   1153 }
   1154 
   1155 static void
   1156 show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
   1157 	      GElf_Shdr *shdr, const char *prefix, const char *fname,
   1158 	      const char *fullname)
   1159 {
   1160   /* Get the section header string table index.  */
   1161   size_t shstrndx;
   1162   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
   1163     error (EXIT_FAILURE, 0,
   1164 	   gettext ("cannot get section header string table index"));
   1165 
   1166   /* The section is that large.  */
   1167   size_t size = shdr->sh_size;
   1168   /* One entry is this large.  */
   1169   size_t entsize = shdr->sh_entsize;
   1170 
   1171   /* Consistency checks.  */
   1172   if (entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, ehdr->e_version))
   1173     error (0, 0,
   1174 	   gettext ("%s: entry size in section `%s' is not what we expect"),
   1175 	   fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
   1176   else if (size % entsize != 0)
   1177     error (0, 0,
   1178 	   gettext ("%s: size of section `%s' is not multiple of entry size"),
   1179 	   fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
   1180 
   1181   /* Compute number of entries.  Handle buggy entsize values.  */
   1182   size_t nentries = size / (entsize ?: 1);
   1183 
   1184 
   1185 #define obstack_chunk_alloc xmalloc
   1186 #define obstack_chunk_free free
   1187   struct obstack whereob;
   1188   obstack_init (&whereob);
   1189 
   1190   /* Get a DWARF debugging descriptor.  It's no problem if this isn't
   1191      possible.  We just won't print any line number information.  */
   1192   Dwarf *dbg = NULL;
   1193   if (format == format_sysv)
   1194     {
   1195       dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
   1196       if (dbg != NULL)
   1197 	{
   1198 	  (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
   1199 
   1200 	  get_local_names (dbg);
   1201 	}
   1202     }
   1203 
   1204   /* Allocate the memory.
   1205 
   1206      XXX We can use a dirty trick here.  Since GElf_Sym == Elf64_Sym we
   1207      can use the data memory instead of copying again if what we read
   1208      is a 64 bit file.  */
   1209   GElf_SymX *sym_mem;
   1210   if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
   1211     sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
   1212   else
   1213     sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
   1214 
   1215   /* Get the data of the section.  */
   1216   Elf_Data *data = elf_getdata (scn, NULL);
   1217   Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
   1218   if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
   1219     INTERNAL_ERROR (fullname);
   1220 
   1221   /* Iterate over all symbols.  */
   1222 #ifdef USE_DEMANGLE
   1223   size_t demangle_buffer_len = 0;
   1224   char *demangle_buffer = NULL;
   1225 #endif
   1226   int longest_name = 4;
   1227   int longest_where = 4;
   1228   size_t nentries_used = 0;
   1229   for (size_t cnt = 0; cnt < nentries; ++cnt)
   1230     {
   1231       GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
   1232 					&sym_mem[nentries_used].sym,
   1233 					&sym_mem[nentries_used].xndx);
   1234       if (sym == NULL)
   1235 	INTERNAL_ERROR (fullname);
   1236 
   1237       /* Filter out administrative symbols without a name and those
   1238 	 deselected by the user with command line options.  */
   1239       if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
   1240 	  || (hide_defined && sym->st_shndx != SHN_UNDEF)
   1241 	  || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
   1242 	continue;
   1243 
   1244       sym_mem[nentries_used].where = "";
   1245       if (format == format_sysv)
   1246 	{
   1247 	  const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
   1248 					   sym->st_name);
   1249 	  if (symstr == NULL)
   1250 	    continue;
   1251 
   1252 #ifdef USE_DEMANGLE
   1253 	  /* Demangle if necessary.  */
   1254 	  if (demangle)
   1255 	    {
   1256 	      int status = -1;
   1257 	      char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
   1258 					       &demangle_buffer_len, &status);
   1259 
   1260 	      if (status == 0)
   1261 		symstr = dmsymstr;
   1262 	    }
   1263 #endif
   1264 
   1265 	  longest_name = MAX ((size_t) longest_name, strlen (symstr));
   1266 
   1267 	  if (sym->st_shndx != SHN_UNDEF
   1268 	      && GELF_ST_BIND (sym->st_info) != STB_LOCAL
   1269 	      && global_root != NULL)
   1270 	    {
   1271 	      Dwarf_Global fake = { .name = symstr };
   1272 	      Dwarf_Global **found = tfind (&fake, &global_root,
   1273 					    global_compare);
   1274 	      if (found != NULL)
   1275 		{
   1276 		  Dwarf_Die die_mem;
   1277 		  Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
   1278 						 &die_mem);
   1279 
   1280 		  Dwarf_Die cudie_mem;
   1281 		  Dwarf_Die *cudie = NULL;
   1282 
   1283 		  Dwarf_Addr lowpc;
   1284 		  Dwarf_Addr highpc;
   1285 		  if (die != NULL
   1286 		      && dwarf_lowpc (die, &lowpc) == 0
   1287 		      && lowpc <= sym->st_value
   1288 		      && dwarf_highpc (die, &highpc) == 0
   1289 		      && highpc > sym->st_value)
   1290 		    cudie = dwarf_offdie (dbg, (*found)->cu_offset,
   1291 					  &cudie_mem);
   1292 		  if (cudie != NULL)
   1293 		    {
   1294 		      Dwarf_Line *line = dwarf_getsrc_die (cudie,
   1295 							   sym->st_value);
   1296 		      if (line != NULL)
   1297 			{
   1298 			  /* We found the line.  */
   1299 			  int lineno;
   1300 			  (void) dwarf_lineno (line, &lineno);
   1301 			  int n;
   1302 			  n = obstack_printf (&whereob, "%s:%d%c",
   1303 					      basename (dwarf_linesrc (line,
   1304 								       NULL,
   1305 								       NULL)),
   1306 					      lineno, '\0');
   1307 			  sym_mem[nentries_used].where
   1308 			    = obstack_finish (&whereob);
   1309 
   1310 			  /* The return value of obstack_print included the
   1311 			     NUL byte, so subtract one.  */
   1312 			  if (--n > (int) longest_where)
   1313 			    longest_where = (size_t) n;
   1314 			}
   1315 		    }
   1316 		}
   1317 	    }
   1318 
   1319 	  /* Try to find the symbol among the local symbols.  */
   1320 	  if (sym_mem[nentries_used].where[0] == '\0')
   1321 	    {
   1322 	      struct local_name fake =
   1323 		{
   1324 		  .name = symstr,
   1325 		  .lowpc = sym->st_value,
   1326 		  .highpc = sym->st_value,
   1327 		};
   1328 	      struct local_name **found = tfind (&fake, &local_root,
   1329 						 local_compare);
   1330 	      if (found != NULL)
   1331 		{
   1332 		  /* We found the line.  */
   1333 		  int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
   1334 					  basename ((*found)->file),
   1335 					  (*found)->lineno,
   1336 					  '\0');
   1337 		  sym_mem[nentries_used].where = obstack_finish (&whereob);
   1338 
   1339 		  /* The return value of obstack_print included the
   1340 		     NUL byte, so subtract one.  */
   1341 		  if (--n > (int) longest_where)
   1342 		    longest_where = (size_t) n;
   1343 		}
   1344 	    }
   1345 	}
   1346 
   1347       /* We use this entry.  */
   1348       ++nentries_used;
   1349     }
   1350 #ifdef USE_DEMANGLE
   1351   free (demangle_buffer);
   1352 #endif
   1353   /* Now we know the exact number.  */
   1354   nentries = nentries_used;
   1355 
   1356   /* Sort the entries according to the users wishes.  */
   1357   if (sort == sort_name)
   1358     {
   1359       sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
   1360 					 NULL);
   1361       qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
   1362     }
   1363   else if (sort == sort_numeric)
   1364     qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
   1365 
   1366   /* Finally print according to the users selection.  */
   1367   switch (format)
   1368     {
   1369     case format_sysv:
   1370       show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
   1371 			 longest_name, longest_where);
   1372       break;
   1373 
   1374     case format_bsd:
   1375       show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
   1376 			sym_mem, nentries);
   1377       break;
   1378 
   1379     case format_posix:
   1380     default:
   1381       assert (format == format_posix);
   1382       show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
   1383 			  sym_mem, nentries);
   1384       break;
   1385     }
   1386 
   1387   /* Free all memory.  */
   1388   if (nentries * sizeof (GElf_Sym) >= MAX_STACK_ALLOC)
   1389     free (sym_mem);
   1390 
   1391   obstack_free (&whereob, NULL);
   1392 
   1393   if (dbg != NULL)
   1394     {
   1395       tdestroy (global_root, free);
   1396       global_root = NULL;
   1397 
   1398       tdestroy (local_root, free);
   1399       local_root = NULL;
   1400 
   1401       (void) dwarf_end (dbg);
   1402     }
   1403 }
   1404 
   1405 
   1406 static int
   1407 handle_elf (Elf *elf, const char *prefix, const char *fname,
   1408 	    const char *suffix)
   1409 {
   1410   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
   1411   size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
   1412   size_t fname_len = strlen (fname) + 1;
   1413   char fullname[prefix_len + 1 + fname_len + suffix_len];
   1414   char *cp = fullname;
   1415   Elf_Scn *scn = NULL;
   1416   int any = 0;
   1417   int result = 0;
   1418   GElf_Ehdr ehdr_mem;
   1419   GElf_Ehdr *ehdr;
   1420   Ebl *ebl;
   1421 
   1422   /* Get the backend for this object file type.  */
   1423   ebl = ebl_openbackend (elf);
   1424 
   1425   /* We need the ELF header in a few places.  */
   1426   ehdr = gelf_getehdr (elf, &ehdr_mem);
   1427   if (ehdr == NULL)
   1428     INTERNAL_ERROR (fullname);
   1429 
   1430   /* If we are asked to print the dynamic symbol table and this is
   1431      executable or dynamic executable, fail.  */
   1432   if (symsec_type == SHT_DYNSYM
   1433       && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
   1434     {
   1435       /* XXX Add machine specific object file types.  */
   1436       error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
   1437 	     prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
   1438       result = 1;
   1439       goto out;
   1440     }
   1441 
   1442   /* Create the full name of the file.  */
   1443   if (prefix != NULL)
   1444     cp = mempcpy (cp, prefix, prefix_len);
   1445   cp = mempcpy (cp, fname, fname_len);
   1446   if (suffix != NULL)
   1447     memcpy (cp - 1, suffix, suffix_len + 1);
   1448 
   1449   /* Find the symbol table.
   1450 
   1451      XXX Can there be more than one?  Do we print all?  Currently we do.  */
   1452   while ((scn = elf_nextscn (elf, scn)) != NULL)
   1453     {
   1454       GElf_Shdr shdr_mem;
   1455       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1456 
   1457       if (shdr == NULL)
   1458 	INTERNAL_ERROR (fullname);
   1459 
   1460       if (shdr->sh_type == symsec_type)
   1461 	{
   1462 	  Elf_Scn *xndxscn = NULL;
   1463 
   1464 	  /* We have a symbol table.  First make sure we remember this.  */
   1465 	  any = 1;
   1466 
   1467 	  /* Look for an extended section index table for this section.  */
   1468 	  if (symsec_type == SHT_SYMTAB)
   1469 	    {
   1470 	      size_t scnndx = elf_ndxscn (scn);
   1471 
   1472 	      while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
   1473 		{
   1474 		  GElf_Shdr xndxshdr_mem;
   1475 		  GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
   1476 
   1477 		  if (xndxshdr == NULL)
   1478 		    INTERNAL_ERROR (fullname);
   1479 
   1480 		  if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
   1481 		      && xndxshdr->sh_link == scnndx)
   1482 		    break;
   1483 		}
   1484 	    }
   1485 
   1486 	  show_symbols (ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
   1487 			fullname);
   1488 	}
   1489     }
   1490 
   1491   if (! any)
   1492     {
   1493       error (0, 0, gettext ("%s%s%s: no symbols"),
   1494 	     prefix ?: "", prefix ? ":" : "", fname);
   1495       result = 1;
   1496     }
   1497 
   1498  out:
   1499   /* Close the ELF backend library descriptor.  */
   1500   ebl_closebackend (ebl);
   1501 
   1502   return result;
   1503 }
   1504 
   1505 
   1506 #include "debugpred.h"
   1507