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