• 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 
755       assert (elf_ndxscn (scn) == cnt);
756       cnt++;
757 
758       char *name = elf_strptr (ebl->elf, shstrndx,
759 			       gelf_getshdr (scn, &shdr_mem)->sh_name);
760       if (unlikely (name == NULL))
761 	{
762 	  const size_t bufsz = sizeof "[invalid sh_name 0x12345678]";
763 	  name = alloca (bufsz);
764 	  snprintf (name, bufsz, "[invalid sh_name %#" PRIx32 "]",
765 		    gelf_getshdr (scn, &shdr_mem)->sh_name);
766 	}
767       scnnames[elf_ndxscn (scn)] = name;
768     }
769 
770   int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
771 
772   /* We always print this prolog.  */
773   printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
774 
775   /* The header line.  */
776   printf (gettext ("%*s%-*s %-*s Class  Type     %-*s %*s Section\n\n"),
777 	  print_file_name ? (int) strlen (fullname) + 1: 0, "",
778 	  longest_name, sgettext ("sysv|Name"),
779 	  /* TRANS: the "sysv|" parts makes the string unique.  */
780 	  digits, sgettext ("sysv|Value"),
781 	  /* TRANS: the "sysv|" parts makes the string unique.  */
782 	  digits, sgettext ("sysv|Size"),
783 	  /* TRANS: the "sysv|" parts makes the string unique.  */
784 	  longest_where, sgettext ("sysv|Line"));
785 
786 #ifdef USE_DEMANGLE
787   size_t demangle_buffer_len = 0;
788   char *demangle_buffer = NULL;
789 #endif
790 
791   /* Iterate over all symbols.  */
792   for (cnt = 1; cnt < nsyms; ++cnt)
793     {
794       /* In this format SECTION entries are not printed.  */
795       if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
796 	continue;
797 
798       char symstrbuf[50];
799       const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
800 				     symstrbuf, sizeof symstrbuf);
801 
802 #ifdef USE_DEMANGLE
803       /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
804       if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
805 	{
806 	  int status = -1;
807 	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
808 					   &demangle_buffer_len, &status);
809 
810 	  if (status == 0)
811 	    symstr = dmsymstr;
812 	}
813 #endif
814 
815       char symbindbuf[50];
816       char symtypebuf[50];
817       char secnamebuf[1024];
818       char addressbuf[(64 + 2) / 3 + 1];
819       char sizebuf[(64 + 2) / 3 + 1];
820 
821       /* If we have to precede the line with the file name.  */
822       if (print_file_name)
823 	{
824 	  fputs_unlocked (fullname, stdout);
825 	  putchar_unlocked (':');
826 	}
827 
828       /* Covert the address.  */
829       if (syms[cnt].sym.st_shndx == SHN_UNDEF)
830 	addressbuf[0] = sizebuf[0] = '\0';
831       else
832 	{
833 	  snprintf (addressbuf, sizeof (addressbuf),
834 		    (radix == radix_hex ? "%0*" PRIx64
835 		     : (radix == radix_decimal ? "%0*" PRId64
836 			: "%0*" PRIo64)),
837 		    digits, syms[cnt].sym.st_value);
838 	  snprintf (sizebuf, sizeof (sizebuf),
839 		    (radix == radix_hex ? "%0*" PRIx64
840 		     : (radix == radix_decimal ? "%0*" PRId64
841 			: "%0*" PRIo64)),
842 		    digits, syms[cnt].sym.st_size);
843 	}
844 
845       /* Print the actual string.  */
846       printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
847 	      longest_name, symstr, addressbuf,
848 	      ebl_symbol_binding_name (ebl,
849 				       GELF_ST_BIND (syms[cnt].sym.st_info),
850 				       symbindbuf, sizeof (symbindbuf)),
851 	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
852 				    symtypebuf, sizeof (symtypebuf)),
853 	      sizebuf, longest_where, syms[cnt].where,
854 	      ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
855 				secnamebuf, sizeof (secnamebuf), scnnames,
856 				shnum));
857     }
858 
859 #ifdef USE_DEMANGLE
860   free (demangle_buffer);
861 #endif
862 
863   if (scnnames_malloced)
864     free (scnnames);
865 }
866 
867 
868 static char
class_type_char(Elf * elf,const GElf_Ehdr * ehdr,GElf_Sym * sym)869 class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
870 {
871   int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
872 
873   /* XXX Add support for architecture specific types and classes.  */
874   if (sym->st_shndx == SHN_ABS)
875     return local_p ? 'a' : 'A';
876 
877   if (sym->st_shndx == SHN_UNDEF)
878     /* Undefined symbols must be global.  */
879     return 'U';
880 
881   char result = "NDTSFBD         "[GELF_ST_TYPE (sym->st_info)];
882 
883   if (result == 'D')
884     {
885       /* Special handling: unique data symbols.  */
886       if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
887 	  && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
888 	result = 'u';
889       else
890 	{
891 	  GElf_Shdr shdr_mem;
892 	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
893 					  &shdr_mem);
894 	  if (shdr != NULL)
895 	    {
896 	      if ((shdr->sh_flags & SHF_WRITE) == 0)
897 		result = 'R';
898 	      else if (shdr->sh_type == SHT_NOBITS)
899 		result = 'B';
900 	    }
901 	}
902     }
903 
904   return local_p ? tolower (result) : result;
905 }
906 
907 
908 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)909 show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
910 		  const char *prefix, const char *fname, const char *fullname,
911 		  GElf_SymX *syms, size_t nsyms)
912 {
913   int digits = length_map[gelf_getclass (elf) - 1][radix];
914 
915   if (prefix != NULL && ! print_file_name)
916     printf ("\n%s:\n", fname);
917 
918 #ifdef USE_DEMANGLE
919   size_t demangle_buffer_len = 0;
920   char *demangle_buffer = NULL;
921 #endif
922 
923   /* Iterate over all symbols.  */
924   for (size_t cnt = 0; cnt < nsyms; ++cnt)
925     {
926       char symstrbuf[50];
927       const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
928 				     symstrbuf, sizeof symstrbuf);
929 
930       /* Printing entries with a zero-length name makes the output
931 	 not very well parseable.  Since these entries don't carry
932 	 much information we leave them out.  */
933       if (symstr[0] == '\0')
934 	continue;
935 
936       /* We do not print the entries for files.  */
937       if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
938 	continue;
939 
940 #ifdef USE_DEMANGLE
941       /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
942       if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
943 	{
944 	  int status = -1;
945 	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
946 					   &demangle_buffer_len, &status);
947 
948 	  if (status == 0)
949 	    symstr = dmsymstr;
950 	}
951 #endif
952 
953       /* If we have to precede the line with the file name.  */
954       if (print_file_name)
955 	{
956 	  fputs_unlocked (fullname, stdout);
957 	  putchar_unlocked (':');
958 	}
959 
960       bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
961       bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
962       const char *marker = (mark_special
963 			    ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
964 
965       if (syms[cnt].sym.st_shndx == SHN_UNDEF)
966 	{
967 	  const char *color = "";
968 	  if (color_mode)
969 	    {
970 	      if (is_tls)
971 		color = color_undef_tls;
972 	      else if (is_weak)
973 		color = color_undef_weak;
974 	      else
975 		color = color_undef;
976 	    }
977 
978 	  printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
979 	}
980       else
981 	{
982 	  const char *color = "";
983 	  if (color_mode)
984 	    {
985 	      if (is_tls)
986 		color = color_tls;
987 	      else if (is_weak)
988 		color = color_weak;
989 	      else
990 		color = color_symbol;
991 	    }
992 	  if (print_size && syms[cnt].sym.st_size != 0)
993 	    {
994 #define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %10$0*9$" PRIx64 " %7$s%3$c%4$s %5$s"
995 #define DECFMT "%6$s%2$*1$" PRId64 "%8$s %10$*9$" PRId64 " %7$s%3$c%4$s %5$s"
996 #define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %10$0*9$" PRIo64 " %7$s%3$c%4$s %5$s"
997 	      printf ((radix == radix_hex ? HEXFMT
998 		       : (radix == radix_decimal ? DECFMT : OCTFMT)),
999 		      digits, syms[cnt].sym.st_value,
1000 		      class_type_char (elf, ehdr, &syms[cnt].sym), marker,
1001 		      symstr,
1002 		      color_mode ? color_address : "",
1003 		      color,
1004 		      color_mode ? color_off : "",
1005 		      digits, (uint64_t) syms[cnt].sym.st_size);
1006 #undef HEXFMT
1007 #undef DECFMT
1008 #undef OCTFMT
1009 	    }
1010 	  else
1011 	    {
1012 #define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %7$s%3$c%4$s %5$s"
1013 #define DECFMT "%6$s%2$*1$" PRId64 "%8$s %7$s%3$c%4$s %5$s"
1014 #define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %7$s%3$c%4$s %5$s"
1015 	      printf ((radix == radix_hex ? HEXFMT
1016 		       : (radix == radix_decimal ? DECFMT : OCTFMT)),
1017 		      digits, syms[cnt].sym.st_value,
1018 		      class_type_char (elf, ehdr, &syms[cnt].sym), marker,
1019 		      symstr,
1020 		      color_mode ? color_address : "",
1021 		      color,
1022 		      color_mode ? color_off : "");
1023 #undef HEXFMT
1024 #undef DECFMT
1025 #undef OCTFMT
1026 	    }
1027 	}
1028 
1029       if (color_mode)
1030 	fputs_unlocked (color_off, stdout);
1031       putchar_unlocked ('\n');
1032     }
1033 
1034 #ifdef USE_DEMANGLE
1035   free (demangle_buffer);
1036 #endif
1037 }
1038 
1039 
1040 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)1041 show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
1042 		    const char *prefix, const char *fullname, GElf_SymX *syms,
1043 		    size_t nsyms)
1044 {
1045   if (prefix != NULL && ! print_file_name)
1046     printf ("%s:\n", fullname);
1047 
1048   int digits = length_map[gelf_getclass (elf) - 1][radix];
1049 
1050 #ifdef USE_DEMANGLE
1051   size_t demangle_buffer_len = 0;
1052   char *demangle_buffer = NULL;
1053 #endif
1054 
1055   /* Iterate over all symbols.  */
1056   for (size_t cnt = 0; cnt < nsyms; ++cnt)
1057     {
1058       char symstrbuf[50];
1059       const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
1060 				     symstrbuf, sizeof symstrbuf);
1061 
1062       /* Printing entries with a zero-length name makes the output
1063 	 not very well parseable.  Since these entries don't carry
1064 	 much information we leave them out.  */
1065       if (symstr[0] == '\0')
1066 	continue;
1067 
1068 #ifdef USE_DEMANGLE
1069       /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
1070       if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
1071 	{
1072 	  int status = -1;
1073 	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1074 					   &demangle_buffer_len, &status);
1075 
1076 	  if (status == 0)
1077 	    symstr = dmsymstr;
1078 	}
1079 #endif
1080 
1081       /* If we have to precede the line with the file name.  */
1082       if (print_file_name)
1083 	{
1084 	  fputs_unlocked (fullname, stdout);
1085 	  putchar_unlocked (':');
1086 	  putchar_unlocked (' ');
1087 	}
1088 
1089       printf ((radix == radix_hex
1090 	       ? "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n"
1091 	       : (radix == radix_decimal
1092 		  ? "%s %c%s %*" PRId64 " %*" PRId64 "\n"
1093 		  : "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n")),
1094 	      symstr,
1095 	      class_type_char (elf, ehdr, &syms[cnt].sym),
1096 	      mark_special
1097 	      ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
1098 		 ? "@"
1099 		 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
1100 		    ? "*" : " "))
1101 	      : "",
1102 	      digits, syms[cnt].sym.st_value,
1103 	      digits, syms[cnt].sym.st_size);
1104     }
1105 
1106 #ifdef USE_DEMANGLE
1107   free (demangle_buffer);
1108 #endif
1109 }
1110 
1111 
1112 /* Maximum size of memory we allocate on the stack.  */
1113 #define MAX_STACK_ALLOC	65536
1114 
1115 static int
sort_by_address(const void * p1,const void * p2)1116 sort_by_address (const void *p1, const void *p2)
1117 {
1118   GElf_SymX *s1 = (GElf_SymX *) p1;
1119   GElf_SymX *s2 = (GElf_SymX *) p2;
1120 
1121   int result = (s1->sym.st_value < s2->sym.st_value
1122 		? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
1123 
1124   return reverse_sort ? -result : result;
1125 }
1126 
1127 static Elf_Data *sort_by_name_strtab;
1128 
1129 static int
sort_by_name(const void * p1,const void * p2)1130 sort_by_name (const void *p1, const void *p2)
1131 {
1132   GElf_SymX *s1 = (GElf_SymX *) p1;
1133   GElf_SymX *s2 = (GElf_SymX *) p2;
1134 
1135   const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
1136   const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
1137 
1138   int result = strcmp (n1, n2);
1139 
1140   return reverse_sort ? -result : result;
1141 }
1142 
1143 /* Stub libdwfl callback, only the ELF handle already open is ever
1144    used.  Only used for finding the alternate debug file if the Dwarf
1145    comes from the main file.  We are not interested in separate
1146    debuginfo.  */
1147 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)1148 find_no_debuginfo (Dwfl_Module *mod,
1149 		   void **userdata,
1150 		   const char *modname,
1151 		   Dwarf_Addr base,
1152 		   const char *file_name,
1153 		   const char *debuglink_file,
1154 		   GElf_Word debuglink_crc,
1155 		   char **debuginfo_file_name)
1156 {
1157   Dwarf_Addr dwbias;
1158   dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
1159 
1160   /* We are only interested if the Dwarf has been setup on the main
1161      elf file but is only missing the alternate debug link.  If dwbias
1162      hasn't even been setup, this is searching for separate debuginfo
1163      for the main elf.  We don't care in that case.  */
1164   if (dwbias == (Dwarf_Addr) -1)
1165     return -1;
1166 
1167   return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
1168 				       file_name, debuglink_file,
1169 				       debuglink_crc, debuginfo_file_name);
1170 }
1171 
1172 /* Get the Dwarf for the module/file we want.  */
1173 struct getdbg
1174 {
1175   const char *name;
1176   Dwarf **dbg;
1177 };
1178 
1179 static int
getdbg_dwflmod(Dwfl_Module * dwflmod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)1180 getdbg_dwflmod (Dwfl_Module *dwflmod,
1181 		void **userdata __attribute__ ((unused)),
1182 		const char *name,
1183 		Dwarf_Addr base __attribute__ ((unused)),
1184 		void *arg)
1185 {
1186   struct getdbg *get = (struct getdbg *) arg;
1187   if (get != NULL && get->name != NULL && strcmp (get->name, name) == 0)
1188     {
1189       Dwarf_Addr bias;
1190       *get->dbg = dwfl_module_getdwarf (dwflmod, &bias);
1191       return DWARF_CB_ABORT;
1192     }
1193 
1194   return DWARF_CB_OK;
1195 }
1196 
1197 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)1198 show_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr,
1199 	      Elf_Scn *scn, Elf_Scn *xndxscn,
1200 	      GElf_Shdr *shdr, const char *prefix, const char *fname,
1201 	      const char *fullname)
1202 {
1203   /* Get the section header string table index.  */
1204   size_t shstrndx;
1205   if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1206     error (EXIT_FAILURE, 0,
1207 	   gettext ("cannot get section header string table index"));
1208 
1209   /* The section is that large.  */
1210   size_t size = shdr->sh_size;
1211   /* One entry is this large.  */
1212   size_t entsize = shdr->sh_entsize;
1213 
1214   /* Consistency checks.  */
1215   if (entsize == 0
1216       || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
1217     error (0, 0,
1218 	   gettext ("%s: entry size in section %zd `%s' is not what we expect"),
1219 	   fullname, elf_ndxscn (scn),
1220 	   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1221   else if (size % entsize != 0)
1222     error (0, 0,
1223 	   gettext ("%s: size of section %zd `%s' is not multiple of entry size"),
1224 	   fullname, elf_ndxscn (scn),
1225 	   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1226 
1227   /* Compute number of entries.  Handle buggy entsize values.  */
1228   size_t nentries = size / (entsize ?: 1);
1229 
1230 
1231 #define obstack_chunk_alloc xmalloc
1232 #define obstack_chunk_free free
1233   struct obstack whereob;
1234   obstack_init (&whereob);
1235 
1236   /* Get a DWARF debugging descriptor.  It's no problem if this isn't
1237      possible.  We just won't print any line number information.  */
1238   Dwarf *dbg = NULL;
1239   Dwfl *dwfl = NULL;
1240   if (format == format_sysv)
1241     {
1242       if (ehdr->e_type != ET_REL)
1243 	dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
1244       else
1245 	{
1246 	  /* Abuse libdwfl to do the relocations for us.  This is just
1247 	     for the ET_REL file containing Dwarf, so no need for
1248 	     fancy lookups.  */
1249 
1250 	  /* Duplicate an fd for dwfl_report_offline to swallow.  */
1251 	  int dwfl_fd = dup (fd);
1252 	  if (likely (dwfl_fd >= 0))
1253 	    {
1254 	      static const Dwfl_Callbacks callbacks =
1255 		{
1256 		  .section_address = dwfl_offline_section_address,
1257 		  .find_debuginfo = find_no_debuginfo
1258 		};
1259 	      dwfl = dwfl_begin (&callbacks);
1260 	      if (likely (dwfl != NULL))
1261 		{
1262 		  /* Let 0 be the logical address of the file (or
1263 		     first in archive).  */
1264 		  dwfl->offline_next_address = 0;
1265 		  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd)
1266 		      == NULL)
1267 		    {
1268 		      /* Consumed on success, not on failure.  */
1269 		      close (dwfl_fd);
1270 		    }
1271 		  else
1272 		    {
1273 		      dwfl_report_end (dwfl, NULL, NULL);
1274 
1275 		      struct getdbg get = { .name = fname, .dbg = &dbg };
1276 		      dwfl_getmodules (dwfl, &getdbg_dwflmod, &get, 0);
1277 		    }
1278 		}
1279 	    }
1280 	}
1281       if (dbg != NULL)
1282 	{
1283 	  (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
1284 
1285 	  get_local_names (dbg);
1286 	}
1287     }
1288 
1289   /* Get the data of the section.  */
1290   Elf_Data *data = elf_getdata (scn, NULL);
1291   Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
1292   if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
1293     INTERNAL_ERROR (fullname);
1294 
1295   /* Allocate the memory.
1296 
1297      XXX We can use a dirty trick here.  Since GElf_Sym == Elf64_Sym we
1298      can use the data memory instead of copying again if what we read
1299      is a 64 bit file.  */
1300   if (nentries > SIZE_MAX / sizeof (GElf_SymX))
1301     error (EXIT_FAILURE, 0,
1302           gettext ("%s: entries (%zd) in section %zd `%s' is too large"),
1303           fullname, nentries, elf_ndxscn (scn),
1304           elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1305   GElf_SymX *sym_mem;
1306   if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
1307     sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
1308   else
1309     sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
1310 
1311   /* Iterate over all symbols.  */
1312 #ifdef USE_DEMANGLE
1313   size_t demangle_buffer_len = 0;
1314   char *demangle_buffer = NULL;
1315 #endif
1316   int longest_name = 4;
1317   int longest_where = 4;
1318   size_t nentries_used = 0;
1319   for (size_t cnt = 0; cnt < nentries; ++cnt)
1320     {
1321       GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
1322 					&sym_mem[nentries_used].sym,
1323 					&sym_mem[nentries_used].xndx);
1324       if (sym == NULL)
1325 	INTERNAL_ERROR (fullname);
1326 
1327       /* Filter out administrative symbols without a name and those
1328 	 deselected by the user with command line options.  */
1329       if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
1330 	  || (hide_defined && sym->st_shndx != SHN_UNDEF)
1331 	  || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
1332 	continue;
1333 
1334       sym_mem[nentries_used].where = "";
1335       if (format == format_sysv)
1336 	{
1337 	  const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
1338 					   sym->st_name);
1339 	  if (symstr == NULL)
1340 	    continue;
1341 
1342 #ifdef USE_DEMANGLE
1343 	  /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
1344 	  if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
1345 	    {
1346 	      int status = -1;
1347 	      char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1348 					       &demangle_buffer_len, &status);
1349 
1350 	      if (status == 0)
1351 		symstr = dmsymstr;
1352 	    }
1353 #endif
1354 
1355 	  longest_name = MAX ((size_t) longest_name, strlen (symstr));
1356 
1357 	  if (sym->st_shndx != SHN_UNDEF
1358 	      && GELF_ST_BIND (sym->st_info) != STB_LOCAL
1359 	      && global_root != NULL)
1360 	    {
1361 	      Dwarf_Global fake = { .name = symstr };
1362 	      Dwarf_Global **found = tfind (&fake, &global_root,
1363 					    global_compare);
1364 	      if (found != NULL)
1365 		{
1366 		  Dwarf_Die die_mem;
1367 		  Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
1368 						 &die_mem);
1369 
1370 		  Dwarf_Die cudie_mem;
1371 		  Dwarf_Die *cudie = NULL;
1372 
1373 		  Dwarf_Addr lowpc;
1374 		  Dwarf_Addr highpc;
1375 		  if (die != NULL
1376 		      && dwarf_lowpc (die, &lowpc) == 0
1377 		      && lowpc <= sym->st_value
1378 		      && dwarf_highpc (die, &highpc) == 0
1379 		      && highpc > sym->st_value)
1380 		    cudie = dwarf_offdie (dbg, (*found)->cu_offset,
1381 					  &cudie_mem);
1382 		  if (cudie != NULL)
1383 		    {
1384 		      Dwarf_Line *line = dwarf_getsrc_die (cudie,
1385 							   sym->st_value);
1386 		      if (line != NULL)
1387 			{
1388 			  /* We found the line.  */
1389 			  int lineno;
1390 			  (void) dwarf_lineno (line, &lineno);
1391 			  const char *file = dwarf_linesrc (line, NULL, NULL);
1392 			  file = (file != NULL) ? basename (file) : "???";
1393 			  int n;
1394 			  n = obstack_printf (&whereob, "%s:%d%c", file,
1395 					      lineno, '\0');
1396 			  sym_mem[nentries_used].where
1397 			    = obstack_finish (&whereob);
1398 
1399 			  /* The return value of obstack_print included the
1400 			     NUL byte, so subtract one.  */
1401 			  if (--n > (int) longest_where)
1402 			    longest_where = (size_t) n;
1403 			}
1404 		    }
1405 		}
1406 	    }
1407 
1408 	  /* Try to find the symbol among the local symbols.  */
1409 	  if (sym_mem[nentries_used].where[0] == '\0')
1410 	    {
1411 	      struct local_name fake =
1412 		{
1413 		  .name = symstr,
1414 		  .lowpc = sym->st_value,
1415 		  .highpc = sym->st_value,
1416 		};
1417 	      struct local_name **found = tfind (&fake, &local_root,
1418 						 local_compare);
1419 	      if (found != NULL)
1420 		{
1421 		  /* We found the line.  */
1422 		  int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
1423 					  basename ((*found)->file),
1424 					  (*found)->lineno,
1425 					  '\0');
1426 		  sym_mem[nentries_used].where = obstack_finish (&whereob);
1427 
1428 		  /* The return value of obstack_print included the
1429 		     NUL byte, so subtract one.  */
1430 		  if (--n > (int) longest_where)
1431 		    longest_where = (size_t) n;
1432 		}
1433 	    }
1434 	}
1435 
1436       /* We use this entry.  */
1437       ++nentries_used;
1438     }
1439 #ifdef USE_DEMANGLE
1440   free (demangle_buffer);
1441 #endif
1442   /* Now we know the exact number.  */
1443   nentries = nentries_used;
1444 
1445   /* Sort the entries according to the users wishes.  */
1446   if (sort == sort_name)
1447     {
1448       sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
1449 					 NULL);
1450       qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
1451     }
1452   else if (sort == sort_numeric)
1453     qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
1454 
1455   /* Finally print according to the users selection.  */
1456   switch (format)
1457     {
1458     case format_sysv:
1459       show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
1460 			 longest_name, longest_where);
1461       break;
1462 
1463     case format_bsd:
1464       show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
1465 			sym_mem, nentries);
1466       break;
1467 
1468     case format_posix:
1469     default:
1470       assert (format == format_posix);
1471       show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
1472 			  sym_mem, nentries);
1473       break;
1474     }
1475 
1476   /* Free all memory.  */
1477   if (nentries * sizeof (sym_mem[0]) >= MAX_STACK_ALLOC)
1478     free (sym_mem);
1479 
1480   obstack_free (&whereob, NULL);
1481 
1482   if (dbg != NULL)
1483     {
1484       tdestroy (global_root, free);
1485       global_root = NULL;
1486 
1487       tdestroy (local_root, free);
1488       local_root = NULL;
1489 
1490       if (dwfl == NULL)
1491 	(void) dwarf_end (dbg);
1492     }
1493   if (dwfl != NULL)
1494     dwfl_end (dwfl);
1495 }
1496 
1497 
1498 static int
handle_elf(int fd,Elf * elf,const char * prefix,const char * fname,const char * suffix)1499 handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
1500 	    const char *suffix)
1501 {
1502   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1503   size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
1504   size_t fname_len = strlen (fname) + 1;
1505   char fullname[prefix_len + 1 + fname_len + suffix_len];
1506   char *cp = fullname;
1507   Elf_Scn *scn = NULL;
1508   int any = 0;
1509   int result = 0;
1510   GElf_Ehdr ehdr_mem;
1511   GElf_Ehdr *ehdr;
1512   Ebl *ebl;
1513 
1514   /* Get the backend for this object file type.  */
1515   ebl = ebl_openbackend (elf);
1516 
1517   /* We need the ELF header in a few places.  */
1518   ehdr = gelf_getehdr (elf, &ehdr_mem);
1519   if (ehdr == NULL)
1520     INTERNAL_ERROR (fullname);
1521 
1522   /* If we are asked to print the dynamic symbol table and this is
1523      executable or dynamic executable, fail.  */
1524   if (symsec_type == SHT_DYNSYM
1525       && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1526     {
1527       /* XXX Add machine specific object file types.  */
1528       error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
1529 	     prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
1530       result = 1;
1531       goto out;
1532     }
1533 
1534   /* Create the full name of the file.  */
1535   if (prefix != NULL)
1536     cp = mempcpy (cp, prefix, prefix_len);
1537   cp = mempcpy (cp, fname, fname_len);
1538   if (suffix != NULL)
1539     memcpy (cp - 1, suffix, suffix_len + 1);
1540 
1541   /* Find the symbol table.
1542 
1543      XXX Can there be more than one?  Do we print all?  Currently we do.  */
1544   while ((scn = elf_nextscn (elf, scn)) != NULL)
1545     {
1546       GElf_Shdr shdr_mem;
1547       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1548 
1549       if (shdr == NULL)
1550 	INTERNAL_ERROR (fullname);
1551 
1552       if (shdr->sh_type == symsec_type)
1553 	{
1554 	  Elf_Scn *xndxscn = NULL;
1555 
1556 	  /* We have a symbol table.  First make sure we remember this.  */
1557 	  any = 1;
1558 
1559 	  /* Look for an extended section index table for this section.  */
1560 	  if (symsec_type == SHT_SYMTAB)
1561 	    {
1562 	      size_t scnndx = elf_ndxscn (scn);
1563 
1564 	      while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
1565 		{
1566 		  GElf_Shdr xndxshdr_mem;
1567 		  GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1568 
1569 		  if (xndxshdr == NULL)
1570 		    INTERNAL_ERROR (fullname);
1571 
1572 		  if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1573 		      && xndxshdr->sh_link == scnndx)
1574 		    break;
1575 		}
1576 	    }
1577 
1578 	  show_symbols (fd, ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
1579 			fullname);
1580 	}
1581     }
1582 
1583   if (! any)
1584     {
1585       error (0, 0, gettext ("%s%s%s: no symbols"),
1586 	     prefix ?: "", prefix ? ":" : "", fname);
1587       result = 1;
1588     }
1589 
1590  out:
1591   /* Close the ELF backend library descriptor.  */
1592   ebl_closebackend (ebl);
1593 
1594   return result;
1595 }
1596 
1597 
1598 #include "debugpred.h"
1599