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