1 /* Print symbol information from ELF file in human-readable form.
2 Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 elfutils is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <ar.h>
24 #include <argp.h>
25 #include <assert.h>
26 #include <ctype.h>
27 #include <dwarf.h>
28 #include <errno.h>
29 #include <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, gettext ("%s: INTERNAL ERROR %d (%s): %s"), \
141 fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
142
143
144 /* Internal representation of symbols. */
145 typedef struct GElf_SymX
146 {
147 GElf_Sym sym;
148 Elf32_Word xndx;
149 char *where;
150 } GElf_SymX;
151
152
153 /* User-selectable options. */
154
155 /* The selected output format. */
156 static enum
157 {
158 format_sysv = 0,
159 format_bsd,
160 format_posix
161 } format;
162
163 /* Print defined, undefined, or both? */
164 static bool hide_undefined;
165 static bool hide_defined;
166
167 /* Print local symbols also? */
168 static bool hide_local;
169
170 /* Nonzero if full filename should precede every symbol. */
171 static bool print_file_name;
172
173 /* If true print size of defined symbols in BSD format. */
174 static bool print_size;
175
176 /* If true print archive index. */
177 static bool print_armap;
178
179 /* If true reverse sorting. */
180 static bool reverse_sort;
181
182 #ifdef USE_DEMANGLE
183 /* If true demangle symbols. */
184 static bool demangle;
185 #endif
186
187 /* Type of the section we are printing. */
188 static GElf_Word symsec_type = SHT_SYMTAB;
189
190 /* Sorting selection. */
191 static enum
192 {
193 sort_name = 0,
194 sort_numeric,
195 sort_nosort
196 } sort;
197
198 /* Radix for printed numbers. */
199 static enum
200 {
201 radix_hex = 0,
202 radix_decimal,
203 radix_octal
204 } radix;
205
206 /* If nonzero mark special symbols:
207 - weak symbols are distinguished from global symbols by adding
208 a `*' after the identifying letter for the symbol class and type.
209 - TLS symbols are distinguished from normal symbols by adding
210 a '@' after the identifying letter for the symbol class and type. */
211 static bool mark_special;
212
213
214 int
main(int argc,char * argv[])215 main (int argc, char *argv[])
216 {
217 int remaining;
218 int result = 0;
219
220 /* We use no threads here which can interfere with handling a stream. */
221 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
222 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
223 (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
224
225 /* Set locale. */
226 (void) setlocale (LC_ALL, "");
227
228 /* Make sure the message catalog can be found. */
229 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
230
231 /* Initialize the message catalog. */
232 (void) textdomain (PACKAGE_TARNAME);
233
234 /* Parse and process arguments. */
235 (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
236
237 /* Tell the library which version we are expecting. */
238 (void) elf_version (EV_CURRENT);
239
240 if (remaining == argc)
241 /* The user didn't specify a name so we use a.out. */
242 result = process_file ("a.out", false);
243 else
244 {
245 /* Process all the remaining files. */
246 const bool more_than_one = remaining + 1 < argc;
247
248 do
249 result |= process_file (argv[remaining], more_than_one);
250 while (++remaining < argc);
251 }
252
253 return result;
254 }
255
256
257 /* 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, gettext ("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, gettext ("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, gettext ("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, gettext ("%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 (gettext("\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, gettext ("invalid offset %zu for symbol %s"),
453 arsym->as_off, arsym->as_name);
454 break;
455 }
456
457 printf (gettext ("%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 gettext ("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, gettext ("%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 gettext ("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 gettext ("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 (gettext ("\n\nSymbols from %s:\n\n"), fullname);
772
773 /* The header line. */
774 printf (gettext ("%*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 = 1; 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 #ifdef USE_DEMANGLE
801 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
802 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
803 {
804 int status = -1;
805 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
806 &demangle_buffer_len, &status);
807
808 if (status == 0)
809 symstr = dmsymstr;
810 }
811 #endif
812
813 char symbindbuf[50];
814 char symtypebuf[50];
815 char secnamebuf[1024];
816 char addressbuf[(64 + 2) / 3 + 1];
817 char sizebuf[(64 + 2) / 3 + 1];
818
819 /* If we have to precede the line with the file name. */
820 if (print_file_name)
821 {
822 fputs_unlocked (fullname, stdout);
823 putchar_unlocked (':');
824 }
825
826 /* Covert the address. */
827 if (syms[cnt].sym.st_shndx == SHN_UNDEF)
828 addressbuf[0] = sizebuf[0] = '\0';
829 else
830 {
831 snprintf (addressbuf, sizeof (addressbuf),
832 (radix == radix_hex ? "%0*" PRIx64
833 : (radix == radix_decimal ? "%0*" PRId64
834 : "%0*" PRIo64)),
835 digits, syms[cnt].sym.st_value);
836 snprintf (sizebuf, sizeof (sizebuf),
837 (radix == radix_hex ? "%0*" PRIx64
838 : (radix == radix_decimal ? "%0*" PRId64
839 : "%0*" PRIo64)),
840 digits, syms[cnt].sym.st_size);
841 }
842
843 /* Print the actual string. */
844 printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
845 longest_name, symstr, addressbuf,
846 ebl_symbol_binding_name (ebl,
847 GELF_ST_BIND (syms[cnt].sym.st_info),
848 symbindbuf, sizeof (symbindbuf)),
849 ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
850 symtypebuf, sizeof (symtypebuf)),
851 sizebuf, longest_where, syms[cnt].where,
852 ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
853 secnamebuf, sizeof (secnamebuf), scnnames,
854 shnum));
855 }
856
857 #ifdef USE_DEMANGLE
858 free (demangle_buffer);
859 #endif
860
861 if (scnnames_malloced)
862 free (scnnames);
863 }
864
865
866 static char
class_type_char(Elf * elf,const GElf_Ehdr * ehdr,GElf_Sym * sym)867 class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
868 {
869 int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
870
871 /* XXX Add support for architecture specific types and classes. */
872 if (sym->st_shndx == SHN_ABS)
873 return local_p ? 'a' : 'A';
874
875 if (sym->st_shndx == SHN_UNDEF)
876 /* Undefined symbols must be global. */
877 return 'U';
878
879 char result = "NDTSFBD "[GELF_ST_TYPE (sym->st_info)];
880
881 if (result == 'D')
882 {
883 /* Special handling: unique data symbols. */
884 if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
885 && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
886 result = 'u';
887 else
888 {
889 GElf_Shdr shdr_mem;
890 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
891 &shdr_mem);
892 if (shdr != NULL)
893 {
894 if ((shdr->sh_flags & SHF_WRITE) == 0)
895 result = 'R';
896 else if (shdr->sh_type == SHT_NOBITS)
897 result = 'B';
898 }
899 }
900 }
901
902 return local_p ? tolower (result) : result;
903 }
904
905
906 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)907 show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
908 const char *prefix, const char *fname, const char *fullname,
909 GElf_SymX *syms, size_t nsyms)
910 {
911 int digits = length_map[gelf_getclass (elf) - 1][radix];
912
913 if (prefix != NULL && ! print_file_name)
914 printf ("\n%s:\n", fname);
915
916 #ifdef USE_DEMANGLE
917 size_t demangle_buffer_len = 0;
918 char *demangle_buffer = NULL;
919 #endif
920
921 /* Iterate over all symbols. */
922 for (size_t cnt = 0; cnt < nsyms; ++cnt)
923 {
924 char symstrbuf[50];
925 const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
926 symstrbuf, sizeof symstrbuf);
927
928 /* Printing entries with a zero-length name makes the output
929 not very well parseable. Since these entries don't carry
930 much information we leave them out. */
931 if (symstr[0] == '\0')
932 continue;
933
934 /* We do not print the entries for files. */
935 if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
936 continue;
937
938 #ifdef USE_DEMANGLE
939 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
940 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
941 {
942 int status = -1;
943 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
944 &demangle_buffer_len, &status);
945
946 if (status == 0)
947 symstr = dmsymstr;
948 }
949 #endif
950
951 /* If we have to precede the line with the file name. */
952 if (print_file_name)
953 {
954 fputs_unlocked (fullname, stdout);
955 putchar_unlocked (':');
956 }
957
958 bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
959 bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
960 const char *marker = (mark_special
961 ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
962
963 if (syms[cnt].sym.st_shndx == SHN_UNDEF)
964 {
965 const char *color = "";
966 if (color_mode)
967 {
968 if (is_tls)
969 color = color_undef_tls;
970 else if (is_weak)
971 color = color_undef_weak;
972 else
973 color = color_undef;
974 }
975
976 printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
977 }
978 else
979 {
980 const char *color = "";
981 if (color_mode)
982 {
983 if (is_tls)
984 color = color_tls;
985 else if (is_weak)
986 color = color_weak;
987 else
988 color = color_symbol;
989 }
990 if (print_size && syms[cnt].sym.st_size != 0)
991 {
992 #define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %10$0*9$" PRIx64 " %7$s%3$c%4$s %5$s"
993 #define DECFMT "%6$s%2$*1$" PRId64 "%8$s %10$*9$" PRId64 " %7$s%3$c%4$s %5$s"
994 #define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %10$0*9$" PRIo64 " %7$s%3$c%4$s %5$s"
995 printf ((radix == radix_hex ? HEXFMT
996 : (radix == radix_decimal ? DECFMT : OCTFMT)),
997 digits, syms[cnt].sym.st_value,
998 class_type_char (elf, ehdr, &syms[cnt].sym), marker,
999 symstr,
1000 color_mode ? color_address : "",
1001 color,
1002 color_mode ? color_off : "",
1003 digits, (uint64_t) syms[cnt].sym.st_size);
1004 #undef HEXFMT
1005 #undef DECFMT
1006 #undef OCTFMT
1007 }
1008 else
1009 {
1010 #define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %7$s%3$c%4$s %5$s"
1011 #define DECFMT "%6$s%2$*1$" PRId64 "%8$s %7$s%3$c%4$s %5$s"
1012 #define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %7$s%3$c%4$s %5$s"
1013 printf ((radix == radix_hex ? HEXFMT
1014 : (radix == radix_decimal ? DECFMT : OCTFMT)),
1015 digits, syms[cnt].sym.st_value,
1016 class_type_char (elf, ehdr, &syms[cnt].sym), marker,
1017 symstr,
1018 color_mode ? color_address : "",
1019 color,
1020 color_mode ? color_off : "");
1021 #undef HEXFMT
1022 #undef DECFMT
1023 #undef OCTFMT
1024 }
1025 }
1026
1027 if (color_mode)
1028 fputs_unlocked (color_off, stdout);
1029 putchar_unlocked ('\n');
1030 }
1031
1032 #ifdef USE_DEMANGLE
1033 free (demangle_buffer);
1034 #endif
1035 }
1036
1037
1038 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)1039 show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
1040 const char *prefix, const char *fullname, GElf_SymX *syms,
1041 size_t nsyms)
1042 {
1043 if (prefix != NULL && ! print_file_name)
1044 printf ("%s:\n", fullname);
1045
1046 int digits = length_map[gelf_getclass (elf) - 1][radix];
1047
1048 #ifdef USE_DEMANGLE
1049 size_t demangle_buffer_len = 0;
1050 char *demangle_buffer = NULL;
1051 #endif
1052
1053 /* Iterate over all symbols. */
1054 for (size_t cnt = 0; cnt < nsyms; ++cnt)
1055 {
1056 char symstrbuf[50];
1057 const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
1058 symstrbuf, sizeof symstrbuf);
1059
1060 /* Printing entries with a zero-length name makes the output
1061 not very well parseable. Since these entries don't carry
1062 much information we leave them out. */
1063 if (symstr[0] == '\0')
1064 continue;
1065
1066 #ifdef USE_DEMANGLE
1067 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
1068 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
1069 {
1070 int status = -1;
1071 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1072 &demangle_buffer_len, &status);
1073
1074 if (status == 0)
1075 symstr = dmsymstr;
1076 }
1077 #endif
1078
1079 /* If we have to precede the line with the file name. */
1080 if (print_file_name)
1081 {
1082 fputs_unlocked (fullname, stdout);
1083 putchar_unlocked (':');
1084 putchar_unlocked (' ');
1085 }
1086
1087 printf ((radix == radix_hex
1088 ? "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n"
1089 : (radix == radix_decimal
1090 ? "%s %c%s %*" PRId64 " %*" PRId64 "\n"
1091 : "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n")),
1092 symstr,
1093 class_type_char (elf, ehdr, &syms[cnt].sym),
1094 mark_special
1095 ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
1096 ? "@"
1097 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
1098 ? "*" : " "))
1099 : "",
1100 digits, syms[cnt].sym.st_value,
1101 digits, syms[cnt].sym.st_size);
1102 }
1103
1104 #ifdef USE_DEMANGLE
1105 free (demangle_buffer);
1106 #endif
1107 }
1108
1109
1110 /* Maximum size of memory we allocate on the stack. */
1111 #define MAX_STACK_ALLOC 65536
1112
1113 static int
sort_by_address(const void * p1,const void * p2)1114 sort_by_address (const void *p1, const void *p2)
1115 {
1116 GElf_SymX *s1 = (GElf_SymX *) p1;
1117 GElf_SymX *s2 = (GElf_SymX *) p2;
1118
1119 int result = (s1->sym.st_value < s2->sym.st_value
1120 ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
1121
1122 return reverse_sort ? -result : result;
1123 }
1124
1125 static Elf_Data *sort_by_name_strtab;
1126
1127 static int
sort_by_name(const void * p1,const void * p2)1128 sort_by_name (const void *p1, const void *p2)
1129 {
1130 GElf_SymX *s1 = (GElf_SymX *) p1;
1131 GElf_SymX *s2 = (GElf_SymX *) p2;
1132
1133 const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
1134 const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
1135
1136 int result = strcmp (n1, n2);
1137
1138 return reverse_sort ? -result : result;
1139 }
1140
1141 /* Stub libdwfl callback, only the ELF handle already open is ever
1142 used. Only used for finding the alternate debug file if the Dwarf
1143 comes from the main file. We are not interested in separate
1144 debuginfo. */
1145 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)1146 find_no_debuginfo (Dwfl_Module *mod,
1147 void **userdata,
1148 const char *modname,
1149 Dwarf_Addr base,
1150 const char *file_name,
1151 const char *debuglink_file,
1152 GElf_Word debuglink_crc,
1153 char **debuginfo_file_name)
1154 {
1155 Dwarf_Addr dwbias;
1156 dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
1157
1158 /* We are only interested if the Dwarf has been setup on the main
1159 elf file but is only missing the alternate debug link. If dwbias
1160 hasn't even been setup, this is searching for separate debuginfo
1161 for the main elf. We don't care in that case. */
1162 if (dwbias == (Dwarf_Addr) -1)
1163 return -1;
1164
1165 return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
1166 file_name, debuglink_file,
1167 debuglink_crc, debuginfo_file_name);
1168 }
1169
1170 /* Get the Dwarf for the module/file we want. */
1171 struct getdbg
1172 {
1173 const char *name;
1174 Dwarf **dbg;
1175 };
1176
1177 static int
getdbg_dwflmod(Dwfl_Module * dwflmod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)1178 getdbg_dwflmod (Dwfl_Module *dwflmod,
1179 void **userdata __attribute__ ((unused)),
1180 const char *name,
1181 Dwarf_Addr base __attribute__ ((unused)),
1182 void *arg)
1183 {
1184 struct getdbg *get = (struct getdbg *) arg;
1185 if (get != NULL && get->name != NULL && strcmp (get->name, name) == 0)
1186 {
1187 Dwarf_Addr bias;
1188 *get->dbg = dwfl_module_getdwarf (dwflmod, &bias);
1189 return DWARF_CB_ABORT;
1190 }
1191
1192 return DWARF_CB_OK;
1193 }
1194
1195 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)1196 show_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr,
1197 Elf_Scn *scn, Elf_Scn *xndxscn,
1198 GElf_Shdr *shdr, const char *prefix, const char *fname,
1199 const char *fullname)
1200 {
1201 /* Get the section header string table index. */
1202 size_t shstrndx;
1203 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
1204 error (EXIT_FAILURE, 0,
1205 gettext ("cannot get section header string table index"));
1206
1207 /* The section is that large. */
1208 size_t size = shdr->sh_size;
1209 /* One entry is this large. */
1210 size_t entsize = shdr->sh_entsize;
1211
1212 /* Consistency checks. */
1213 if (entsize == 0
1214 || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
1215 error (0, 0,
1216 gettext ("%s: entry size in section %zd `%s' is not what we expect"),
1217 fullname, elf_ndxscn (scn),
1218 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1219 else if (size % entsize != 0)
1220 error (0, 0,
1221 gettext ("%s: size of section %zd `%s' is not multiple of entry size"),
1222 fullname, elf_ndxscn (scn),
1223 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1224
1225 /* Compute number of entries. Handle buggy entsize values. */
1226 size_t nentries = size / (entsize ?: 1);
1227
1228
1229 #define obstack_chunk_alloc xmalloc
1230 #define obstack_chunk_free free
1231 struct obstack whereob;
1232 obstack_init (&whereob);
1233
1234 /* Get a DWARF debugging descriptor. It's no problem if this isn't
1235 possible. We just won't print any line number information. */
1236 Dwarf *dbg = NULL;
1237 Dwfl *dwfl = NULL;
1238 if (format == format_sysv)
1239 {
1240 if (ehdr->e_type != ET_REL)
1241 dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
1242 else
1243 {
1244 /* Abuse libdwfl to do the relocations for us. This is just
1245 for the ET_REL file containing Dwarf, so no need for
1246 fancy lookups. */
1247
1248 /* Duplicate an fd for dwfl_report_offline to swallow. */
1249 int dwfl_fd = dup (fd);
1250 if (likely (dwfl_fd >= 0))
1251 {
1252 static const Dwfl_Callbacks callbacks =
1253 {
1254 .section_address = dwfl_offline_section_address,
1255 .find_debuginfo = find_no_debuginfo
1256 };
1257 dwfl = dwfl_begin (&callbacks);
1258 if (likely (dwfl != NULL))
1259 {
1260 /* Let 0 be the logical address of the file (or
1261 first in archive). */
1262 dwfl->offline_next_address = 0;
1263 if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd)
1264 == NULL)
1265 {
1266 /* Consumed on success, not on failure. */
1267 close (dwfl_fd);
1268 }
1269 else
1270 {
1271 dwfl_report_end (dwfl, NULL, NULL);
1272
1273 struct getdbg get = { .name = fname, .dbg = &dbg };
1274 dwfl_getmodules (dwfl, &getdbg_dwflmod, &get, 0);
1275 }
1276 }
1277 }
1278 }
1279 if (dbg != NULL)
1280 {
1281 (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
1282
1283 get_local_names (dbg);
1284 }
1285 }
1286
1287 /* Get the data of the section. */
1288 Elf_Data *data = elf_getdata (scn, NULL);
1289 Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
1290 if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
1291 INTERNAL_ERROR (fullname);
1292
1293 /* Allocate the memory.
1294
1295 XXX We can use a dirty trick here. Since GElf_Sym == Elf64_Sym we
1296 can use the data memory instead of copying again if what we read
1297 is a 64 bit file. */
1298 if (nentries > SIZE_MAX / sizeof (GElf_SymX))
1299 error (EXIT_FAILURE, 0,
1300 gettext ("%s: entries (%zd) in section %zd `%s' is too large"),
1301 fullname, nentries, elf_ndxscn (scn),
1302 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
1303 GElf_SymX *sym_mem;
1304 if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
1305 sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
1306 else
1307 sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
1308
1309 /* Iterate over all symbols. */
1310 #ifdef USE_DEMANGLE
1311 size_t demangle_buffer_len = 0;
1312 char *demangle_buffer = NULL;
1313 #endif
1314 int longest_name = 4;
1315 int longest_where = 4;
1316 size_t nentries_used = 0;
1317 for (size_t cnt = 0; cnt < nentries; ++cnt)
1318 {
1319 GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
1320 &sym_mem[nentries_used].sym,
1321 &sym_mem[nentries_used].xndx);
1322 if (sym == NULL)
1323 INTERNAL_ERROR (fullname);
1324
1325 /* Filter out administrative symbols without a name and those
1326 deselected by the user with command line options. */
1327 if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
1328 || (hide_defined && sym->st_shndx != SHN_UNDEF)
1329 || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
1330 continue;
1331
1332 sym_mem[nentries_used].where = "";
1333 if (format == format_sysv)
1334 {
1335 const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
1336 sym->st_name);
1337 if (symstr == NULL)
1338 continue;
1339
1340 #ifdef USE_DEMANGLE
1341 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
1342 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
1343 {
1344 int status = -1;
1345 char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
1346 &demangle_buffer_len, &status);
1347
1348 if (status == 0)
1349 symstr = dmsymstr;
1350 }
1351 #endif
1352
1353 longest_name = MAX ((size_t) longest_name, strlen (symstr));
1354
1355 if (sym->st_shndx != SHN_UNDEF
1356 && GELF_ST_BIND (sym->st_info) != STB_LOCAL
1357 && global_root != NULL)
1358 {
1359 Dwarf_Global fake = { .name = symstr };
1360 Dwarf_Global **found = tfind (&fake, &global_root,
1361 global_compare);
1362 if (found != NULL)
1363 {
1364 Dwarf_Die die_mem;
1365 Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
1366 &die_mem);
1367
1368 Dwarf_Die cudie_mem;
1369 Dwarf_Die *cudie = NULL;
1370
1371 Dwarf_Addr lowpc;
1372 Dwarf_Addr highpc;
1373 if (die != NULL
1374 && dwarf_lowpc (die, &lowpc) == 0
1375 && lowpc <= sym->st_value
1376 && dwarf_highpc (die, &highpc) == 0
1377 && highpc > sym->st_value)
1378 cudie = dwarf_offdie (dbg, (*found)->cu_offset,
1379 &cudie_mem);
1380 if (cudie != NULL)
1381 {
1382 Dwarf_Line *line = dwarf_getsrc_die (cudie,
1383 sym->st_value);
1384 if (line != NULL)
1385 {
1386 /* We found the line. */
1387 int lineno;
1388 (void) dwarf_lineno (line, &lineno);
1389 const char *file = dwarf_linesrc (line, NULL, NULL);
1390 file = (file != NULL) ? basename (file) : "???";
1391 int n;
1392 n = obstack_printf (&whereob, "%s:%d%c", file,
1393 lineno, '\0');
1394 sym_mem[nentries_used].where
1395 = obstack_finish (&whereob);
1396
1397 /* The return value of obstack_print included the
1398 NUL byte, so subtract one. */
1399 if (--n > (int) longest_where)
1400 longest_where = (size_t) n;
1401 }
1402 }
1403 }
1404 }
1405
1406 /* Try to find the symbol among the local symbols. */
1407 if (sym_mem[nentries_used].where[0] == '\0')
1408 {
1409 struct local_name fake =
1410 {
1411 .name = symstr,
1412 .lowpc = sym->st_value,
1413 .highpc = sym->st_value,
1414 };
1415 struct local_name **found = tfind (&fake, &local_root,
1416 local_compare);
1417 if (found != NULL)
1418 {
1419 /* We found the line. */
1420 int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
1421 basename ((*found)->file),
1422 (*found)->lineno,
1423 '\0');
1424 sym_mem[nentries_used].where = obstack_finish (&whereob);
1425
1426 /* The return value of obstack_print included the
1427 NUL byte, so subtract one. */
1428 if (--n > (int) longest_where)
1429 longest_where = (size_t) n;
1430 }
1431 }
1432 }
1433
1434 /* We use this entry. */
1435 ++nentries_used;
1436 }
1437 #ifdef USE_DEMANGLE
1438 free (demangle_buffer);
1439 #endif
1440 /* Now we know the exact number. */
1441 size_t nentries_orig = nentries;
1442 nentries = nentries_used;
1443
1444 /* Sort the entries according to the users wishes. */
1445 if (sort == sort_name)
1446 {
1447 sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
1448 NULL);
1449 qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
1450 }
1451 else if (sort == sort_numeric)
1452 qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
1453
1454 /* Finally print according to the users selection. */
1455 switch (format)
1456 {
1457 case format_sysv:
1458 show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
1459 longest_name, longest_where);
1460 break;
1461
1462 case format_bsd:
1463 show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
1464 sym_mem, nentries);
1465 break;
1466
1467 case format_posix:
1468 default:
1469 assert (format == format_posix);
1470 show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
1471 sym_mem, nentries);
1472 break;
1473 }
1474
1475 /* Free all memory. */
1476 if (nentries_orig * sizeof (sym_mem[0]) >= MAX_STACK_ALLOC)
1477 free (sym_mem);
1478
1479 obstack_free (&whereob, NULL);
1480
1481 if (dbg != NULL)
1482 {
1483 tdestroy (global_root, free);
1484 global_root = NULL;
1485
1486 tdestroy (local_root, free);
1487 local_root = NULL;
1488
1489 if (dwfl == NULL)
1490 (void) dwarf_end (dbg);
1491 }
1492 if (dwfl != NULL)
1493 dwfl_end (dwfl);
1494 }
1495
1496
1497 static int
handle_elf(int fd,Elf * elf,const char * prefix,const char * fname,const char * suffix)1498 handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
1499 const char *suffix)
1500 {
1501 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1502 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
1503 size_t fname_len = strlen (fname) + 1;
1504 char fullname[prefix_len + 1 + fname_len + suffix_len];
1505 char *cp = fullname;
1506 Elf_Scn *scn = NULL;
1507 int any = 0;
1508 int result = 0;
1509 GElf_Ehdr ehdr_mem;
1510 GElf_Ehdr *ehdr;
1511 Ebl *ebl;
1512
1513 /* Get the backend for this object file type. */
1514 ebl = ebl_openbackend (elf);
1515
1516 /* We need the ELF header in a few places. */
1517 ehdr = gelf_getehdr (elf, &ehdr_mem);
1518 if (ehdr == NULL)
1519 INTERNAL_ERROR (fullname);
1520
1521 /* If we are asked to print the dynamic symbol table and this is
1522 executable or dynamic executable, fail. */
1523 if (symsec_type == SHT_DYNSYM
1524 && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
1525 {
1526 /* XXX Add machine specific object file types. */
1527 error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
1528 prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
1529 result = 1;
1530 goto out;
1531 }
1532
1533 /* Create the full name of the file. */
1534 if (prefix != NULL)
1535 cp = mempcpy (cp, prefix, prefix_len);
1536 cp = mempcpy (cp, fname, fname_len);
1537 if (suffix != NULL)
1538 memcpy (cp - 1, suffix, suffix_len + 1);
1539
1540 /* Find the symbol table.
1541
1542 XXX Can there be more than one? Do we print all? Currently we do. */
1543 while ((scn = elf_nextscn (elf, scn)) != NULL)
1544 {
1545 GElf_Shdr shdr_mem;
1546 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1547
1548 if (shdr == NULL)
1549 INTERNAL_ERROR (fullname);
1550
1551 if (shdr->sh_type == symsec_type)
1552 {
1553 Elf_Scn *xndxscn = NULL;
1554
1555 /* We have a symbol table. First make sure we remember this. */
1556 any = 1;
1557
1558 /* Look for an extended section index table for this section. */
1559 if (symsec_type == SHT_SYMTAB)
1560 {
1561 size_t scnndx = elf_ndxscn (scn);
1562
1563 while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
1564 {
1565 GElf_Shdr xndxshdr_mem;
1566 GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
1567
1568 if (xndxshdr == NULL)
1569 INTERNAL_ERROR (fullname);
1570
1571 if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
1572 && xndxshdr->sh_link == scnndx)
1573 break;
1574 }
1575 }
1576
1577 show_symbols (fd, ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
1578 fullname);
1579 }
1580 }
1581
1582 if (! any)
1583 {
1584 error (0, 0, gettext ("%s%s%s: no symbols"),
1585 prefix ?: "", prefix ? ":" : "", fname);
1586 result = 1;
1587 }
1588
1589 out:
1590 /* Close the ELF backend library descriptor. */
1591 ebl_closebackend (ebl);
1592
1593 return result;
1594 }
1595
1596
1597 #include "debugpred.h"
1598