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