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