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