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