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