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