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