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@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.  */
52static void print_version (FILE *stream, struct argp_state *state);
53ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
54
55/* Bug report address.  */
56ARGP_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.  */
64static 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.  */
105static const char doc[] = N_("List symbols from FILEs (a.out by default).");
106
107/* Strings for arguments in help texts.  */
108static const char args_doc[] = N_("[FILE...]");
109
110/* Prototype for option handler.  */
111static error_t parse_opt (int key, char *arg, struct argp_state *state);
112
113/* Parser children.  */
114static 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.  */
121static 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.  */
128static int process_file (const char *fname, bool more_than_one);
129
130/* Handle content of archive.  */
131static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
132		      const char *suffix);
133
134/* Handle ELF file.  */
135static 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.  */
145typedef 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.  */
156static enum
157{
158  format_sysv = 0,
159  format_bsd,
160  format_posix
161} format;
162
163/* Print defined, undefined, or both?  */
164static bool hide_undefined;
165static bool hide_defined;
166
167/* Print local symbols also?  */
168static bool hide_local;
169
170/* Nonzero if full filename should precede every symbol.  */
171static bool print_file_name;
172
173/* If true print size of defined symbols in BSD format.  */
174static bool print_size;
175
176/* If true print archive index.  */
177static bool print_armap;
178
179/* If true reverse sorting.  */
180static bool reverse_sort;
181
182#ifdef USE_DEMANGLE
183/* If true demangle symbols.  */
184static bool demangle;
185#endif
186
187/* Type of the section we are printing.  */
188static GElf_Word symsec_type = SHT_SYMTAB;
189
190/* Sorting selection.  */
191static enum
192{
193  sort_name = 0,
194  sort_numeric,
195  sort_nosort
196} sort;
197
198/* Radix for printed numbers.  */
199static 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.  */
211static bool mark_special;
212
213
214int
215main (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.  */
258static void
259print_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 ("\
263Copyright (C) %s Red Hat, Inc.\n\
264This is free software; see the source for copying conditions.  There is NO\n\
265warranty; 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.  */
272static error_t
273parse_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.  */
371static int
372process_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
423static int
424handle_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.  */
521static 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
538static int
539global_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
548static void *global_root;
549
550
551static int
552get_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
563struct 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
573static int
574local_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
605static int
606get_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
631static void *local_root;
632
633
634static void
635get_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.  */
728static const char *
729sym_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.  */
741static void
742show_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
882static char
883class_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
922static void
923show_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
1054static void
1055show_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
1129static int
1130sort_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
1141static Elf_Data *sort_by_name_strtab;
1142
1143static int
1144sort_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.  */
1161static int
1162find_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.  */
1187struct getdbg
1188{
1189  const char *name;
1190  Dwarf **dbg;
1191};
1192
1193static int
1194getdbg_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
1211static void
1212show_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
1507static int
1508handle_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