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