blob: 2911afa87e50676ad44bbe61044d6d173a6b85e5 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Print symbol information from ELF file in human-readable form.
Mark Wielaard587c4b32015-04-14 11:59:36 +02002 Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 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.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000010
Mark Wielaardde2ed972012-06-05 17:15:16 +020011 elfutils is distributed in the hope that it will be useful, but
Ulrich Drepper361df7d2006-04-04 21:38:57 +000012 WITHOUT ANY WARRANTY; without even the implied warranty of
Mark Wielaardde2ed972012-06-05 17:15:16 +020013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000015
Mark Wielaardde2ed972012-06-05 17:15:16 +020016 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000018
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>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000036#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"
Mark Wielaard70cd9072015-12-02 16:57:44 +010048#include "../libdwfl/libdwflP.h"
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000049
50
51/* Name and version of program. */
52static void print_version (FILE *stream, struct argp_state *state);
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080053ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000054
55/* Bug report address. */
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080056ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000057
58
59/* Values for the parameters which have no short form. */
Ulrich Drepper2356ba02011-10-03 07:23:07 -040060#define OPT_DEFINED 0x100
61#define OPT_MARK_SPECIAL 0x101
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000062
63/* Definitions of arguments for argp functions. */
64static 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 },
Ulrich Drepper2356ba02011-10-03 07:23:07 -040087 { "mark-special", OPT_MARK_SPECIAL, NULL, 0, N_("Mark special symbols"), 0 },
88 { "mark-weak", OPT_MARK_SPECIAL, NULL, OPTION_HIDDEN, "", 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000089 { "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 },
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -040096#ifdef USE_DEMANGLE
97 { "demangle", 'C', NULL, 0,
98 N_("Decode low-level symbol names into source code names"), 0 },
99#endif
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000100 { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
101 { NULL, 0, NULL, 0, NULL, 0 }
102};
103
104/* Short description of program. */
105static const char doc[] = N_("List symbols from FILEs (a.out by default).");
106
107/* Strings for arguments in help texts. */
108static const char args_doc[] = N_("[FILE...]");
109
110/* Prototype for option handler. */
111static error_t parse_opt (int key, char *arg, struct argp_state *state);
112
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500113/* Parser children. */
114static struct argp_child argp_children[] =
115 {
116 { &color_argp, 0, N_("Output formatting"), 2 },
117 { NULL, 0, NULL, 0}
118 };
119
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000120/* Data structure to communicate with argp functions. */
121static struct argp argp =
122{
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500123 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000124};
125
126
127/* Print symbols in file named FNAME. */
128static int process_file (const char *fname, bool more_than_one);
129
130/* Handle content of archive. */
131static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
132 const char *suffix);
133
134/* Handle ELF file. */
Mark Wielaard70cd9072015-12-02 16:57:44 +0100135static int handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000136 const char *suffix);
137
138
139#define INTERNAL_ERROR(fname) \
Mark Wielaard587c4b32015-04-14 11:59:36 +0200140 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"), \
141 fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000142
143
144/* Internal representation of symbols. */
145typedef 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. */
156static enum
157{
158 format_sysv = 0,
159 format_bsd,
160 format_posix
161} format;
162
163/* Print defined, undefined, or both? */
164static bool hide_undefined;
165static bool hide_defined;
166
167/* Print local symbols also? */
168static bool hide_local;
169
170/* Nonzero if full filename should precede every symbol. */
171static bool print_file_name;
172
173/* If true print size of defined symbols in BSD format. */
174static bool print_size;
175
176/* If true print archive index. */
177static bool print_armap;
178
179/* If true reverse sorting. */
180static bool reverse_sort;
181
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400182#ifdef USE_DEMANGLE
183/* If true demangle symbols. */
184static bool demangle;
185#endif
186
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000187/* Type of the section we are printing. */
188static GElf_Word symsec_type = SHT_SYMTAB;
189
190/* Sorting selection. */
191static enum
192{
193 sort_name = 0,
194 sort_numeric,
195 sort_nosort
196} sort;
197
198/* Radix for printed numbers. */
199static enum
200{
201 radix_hex = 0,
202 radix_decimal,
203 radix_octal
204} radix;
205
Ulrich Drepper2356ba02011-10-03 07:23:07 -0400206/* 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. */
211static bool mark_special;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000212
213
214int
215main (int argc, char *argv[])
216{
217 int remaining;
218 int result = 0;
219
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000220 /* 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. */
Ulrich Drepperb0243862007-06-06 00:09:36 +0000229 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000230
231 /* Initialize the message catalog. */
Ulrich Drepperb0243862007-06-06 00:09:36 +0000232 (void) textdomain (PACKAGE_TARNAME);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000233
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. */
258static void
259print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
260{
Ulrich Drepperb0243862007-06-06 00:09:36 +0000261 fprintf (stream, "nm (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000262 fprintf (stream, gettext ("\
263Copyright (C) %s Red Hat, Inc.\n\
264This is free software; see the source for copying conditions. There is NO\n\
265warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Ulrich Drepper3a64a302012-01-21 18:19:24 -0500266"), "2012");
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000267 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
268}
269
270
271/* Handle program arguments. */
272static error_t
273parse_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
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400282#ifdef USE_DEMANGLE
283 case 'C':
284 demangle = true;
285 break;
286#endif
287
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000288 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
Ulrich Drepper2356ba02011-10-03 07:23:07 -0400347 case OPT_MARK_SPECIAL:
348 mark_special = true;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000349 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. */
371static int
372process_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 {
Mark Wielaard70cd9072015-12-02 16:57:44 +0100388 int result = handle_elf (fd, elf, more_than_one ? "" : NULL,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000389 fname, NULL);
390
391 if (elf_end (elf) != 0)
392 INTERNAL_ERROR (fname);
393
394 if (close (fd) != 0)
Ulrich Drepperd112ef82005-09-03 21:31:27 +0000395 error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000396
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)
Ulrich Drepperd112ef82005-09-03 21:31:27 +0000407 error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000408
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
423static int
424handle_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
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500457 fputs_unlocked (gettext("\nArchive index:\n"), stdout);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000458
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);
Mark Wielaard0b799ad2014-12-26 16:12:52 +0100468 break;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000469 }
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
Mark Wielaard8fb260f2014-12-26 16:20:39 +0100493 && strcmp (arhdr->ar_name, "//") != 0
494 && strcmp (arhdr->ar_name, "/SYM64/") != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000495 {
496 if (elf_kind (subelf) == ELF_K_ELF)
Mark Wielaard70cd9072015-12-02 16:57:44 +0100497 result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000498 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. */
521static 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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000538static int
539global_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
548static void *global_root;
549
550
551static int
552get_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
563struct 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
573static int
574local_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
605static int
606get_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
Roland McGrath6724c902005-10-28 07:07:19 +0000613 Dwarf_Op *loc;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000614 size_t nloc;
Roland McGrath6724c902005-10-28 07:07:19 +0000615 if (dwarf_getlocation (locattr, &loc, &nloc) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000616 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
631static void *local_root;
632
633
634static void
635get_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
Mark Wielaard3fbd8572015-12-02 16:44:42 +0100712 /* 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);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000722 }
723 while (dwarf_siblingof (die, die) == 0);
724 }
725}
726
Roland McGrath468fe4d2008-12-11 21:00:12 -0800727/* Do elf_strptr, but return a backup string and never NULL. */
728static const char *
729sym_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}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000739
740/* Show symbols in SysV format. */
741static void
Marek Polacekc8920de2011-05-12 12:08:21 +0200742show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000743 GElf_SymX *syms, size_t nsyms, int longest_name,
744 int longest_where)
745{
746 size_t shnum;
Ulrich Drepperf1894932009-06-13 15:55:42 -0700747 if (elf_getshdrnum (ebl->elf, &shnum) < 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000748 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;
Ulrich Drepperf1894932009-06-13 15:55:42 -0700758 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000759 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
Mark Wielaard03d76f42013-11-09 16:45:22 +0100769 assert (elf_ndxscn (scn) == cnt);
770 cnt++;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000771
Roland McGrath468fe4d2008-12-11 21:00:12 -0800772 char *name = elf_strptr (ebl->elf, shstrndx,
773 gelf_getshdr (scn, &shdr_mem)->sh_name);
774 if (unlikely (name == NULL))
775 {
Mark Wielaard7df3d2c2012-12-11 22:27:05 +0100776 const size_t bufsz = sizeof "[invalid sh_name 0x12345678]";
Roland McGrath57bd66c2012-12-11 09:42:07 -0800777 name = alloca (bufsz);
778 snprintf (name, bufsz, "[invalid sh_name %#" PRIx32 "]",
Roland McGrath468fe4d2008-12-11 21:00:12 -0800779 gelf_getshdr (scn, &shdr_mem)->sh_name);
780 }
781 scnnames[elf_ndxscn (scn)] = name;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000782 }
783
784 int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
785
786 /* We always print this prolog. */
Marek Polacekc8920de2011-05-12 12:08:21 +0200787 printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000788
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
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400800#ifdef USE_DEMANGLE
801 size_t demangle_buffer_len = 0;
802 char *demangle_buffer = NULL;
803#endif
804
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000805 /* Iterate over all symbols. */
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400806 for (cnt = 1; cnt < nsyms; ++cnt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000807 {
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400808 /* In this format SECTION entries are not printed. */
809 if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
810 continue;
811
Roland McGrath468fe4d2008-12-11 21:00:12 -0800812 char symstrbuf[50];
813 const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
814 symstrbuf, sizeof symstrbuf);
815
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400816#ifdef USE_DEMANGLE
Jan Kratochvil7c6e7852014-01-15 21:16:57 +0100817 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
818 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400819 {
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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000829 char symbindbuf[50];
830 char symtypebuf[50];
831 char secnamebuf[1024];
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400832 char addressbuf[(64 + 2) / 3 + 1];
833 char sizebuf[(64 + 2) / 3 + 1];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000834
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
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400842 /* Covert the address. */
843 if (syms[cnt].sym.st_shndx == SHN_UNDEF)
844 addressbuf[0] = sizebuf[0] = '\0';
845 else
846 {
Mark Wielaardf48eb6b2014-01-23 00:56:41 +0100847 snprintf (addressbuf, sizeof (addressbuf),
848 (radix == radix_hex ? "%0*" PRIx64
849 : (radix == radix_decimal ? "%0*" PRId64
850 : "%0*" PRIo64)),
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400851 digits, syms[cnt].sym.st_value);
Mark Wielaardf48eb6b2014-01-23 00:56:41 +0100852 snprintf (sizebuf, sizeof (sizebuf),
853 (radix == radix_hex ? "%0*" PRIx64
854 : (radix == radix_decimal ? "%0*" PRId64
855 : "%0*" PRIo64)),
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400856 digits, syms[cnt].sym.st_size);
857 }
858
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000859 /* Print the actual string. */
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400860 printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
861 longest_name, symstr, addressbuf,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000862 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)),
Ulrich Drepper66f4c372011-10-03 15:53:12 -0400867 sizebuf, longest_where, syms[cnt].where,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000868 ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
869 secnamebuf, sizeof (secnamebuf), scnnames,
870 shnum));
871 }
872
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400873#ifdef USE_DEMANGLE
874 free (demangle_buffer);
875#endif
876
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000877 if (scnnames_malloced)
878 free (scnnames);
879}
880
881
882static char
Ulrich Drepper2356ba02011-10-03 07:23:07 -0400883class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000884{
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
Ulrich Drepper2356ba02011-10-03 07:23:07 -0400895 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 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000917
918 return local_p ? tolower (result) : result;
919}
920
921
922static void
Ulrich Drepper2356ba02011-10-03 07:23:07 -0400923show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000924 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
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400932#ifdef USE_DEMANGLE
933 size_t demangle_buffer_len = 0;
934 char *demangle_buffer = NULL;
935#endif
936
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000937 /* Iterate over all symbols. */
938 for (size_t cnt = 0; cnt < nsyms; ++cnt)
939 {
Roland McGrath468fe4d2008-12-11 21:00:12 -0800940 char symstrbuf[50];
941 const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
942 symstrbuf, sizeof symstrbuf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000943
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
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500950 /* We do not print the entries for files. */
951 if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
952 continue;
953
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400954#ifdef USE_DEMANGLE
Jan Kratochvil7c6e7852014-01-15 21:16:57 +0100955 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
956 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -0400957 {
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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000967 /* 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
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500974 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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000979 if (syms[cnt].sym.st_shndx == SHN_UNDEF)
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500980 {
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 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000994 else
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -0500995 {
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 }
Mark Wielaardf48eb6b2014-01-23 00:56:41 +01001006 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 }
Ulrich Drepperc6b3d0c2012-01-21 18:14:39 -05001041 }
1042
1043 if (color_mode)
1044 fputs_unlocked (color_off, stdout);
1045 putchar_unlocked ('\n');
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001046 }
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001047
1048#ifdef USE_DEMANGLE
1049 free (demangle_buffer);
1050#endif
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001051}
1052
1053
1054static void
Ulrich Drepper2356ba02011-10-03 07:23:07 -04001055show_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)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001058{
1059 if (prefix != NULL && ! print_file_name)
1060 printf ("%s:\n", fullname);
1061
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001062 int digits = length_map[gelf_getclass (elf) - 1][radix];
1063
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001064#ifdef USE_DEMANGLE
1065 size_t demangle_buffer_len = 0;
1066 char *demangle_buffer = NULL;
1067#endif
1068
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001069 /* Iterate over all symbols. */
1070 for (size_t cnt = 0; cnt < nsyms; ++cnt)
1071 {
Roland McGrath468fe4d2008-12-11 21:00:12 -08001072 char symstrbuf[50];
1073 const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
1074 symstrbuf, sizeof symstrbuf);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001075
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
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001082#ifdef USE_DEMANGLE
Jan Kratochvil7c6e7852014-01-15 21:16:57 +01001083 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
1084 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001085 {
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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001095 /* 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
Mark Wielaardf48eb6b2014-01-23 00:56:41 +01001103 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")),
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001108 symstr,
Ulrich Drepper2356ba02011-10-03 07:23:07 -04001109 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 ? "*" : " "))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001115 : "",
1116 digits, syms[cnt].sym.st_value,
1117 digits, syms[cnt].sym.st_size);
1118 }
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001119
1120#ifdef USE_DEMANGLE
1121 free (demangle_buffer);
1122#endif
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001123}
1124
1125
1126/* Maximum size of memory we allocate on the stack. */
1127#define MAX_STACK_ALLOC 65536
1128
Roland McGrathcb6d8652007-08-23 08:10:54 +00001129static int
1130sort_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
1141static Elf_Data *sort_by_name_strtab;
1142
1143static int
1144sort_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
Mark Wielaard70cd9072015-12-02 16:57:44 +01001157/* 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. */
1161static int
1162find_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. */
1187struct getdbg
1188{
1189 const char *name;
1190 Dwarf **dbg;
1191};
1192
1193static int
1194getdbg_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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001211static void
Mark Wielaard70cd9072015-12-02 16:57:44 +01001212show_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr,
1213 Elf_Scn *scn, Elf_Scn *xndxscn,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001214 GElf_Shdr *shdr, const char *prefix, const char *fname,
1215 const char *fullname)
1216{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001217 /* Get the section header string table index. */
1218 size_t shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001219 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001220 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. */
Mark Wielaard309e7122014-12-26 19:36:31 +01001229 if (entsize == 0
Mark Wielaarda2b964c2015-05-08 17:56:32 +02001230 || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001231 error (0, 0,
Mark Wielaard309e7122014-12-26 19:36:31 +01001232 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));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001235 else if (size % entsize != 0)
1236 error (0, 0,
Mark Wielaard309e7122014-12-26 19:36:31 +01001237 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));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001240
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;
Mark Wielaard70cd9072015-12-02 16:57:44 +01001253 Dwfl *dwfl = NULL;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001254 if (format == format_sysv)
1255 {
Mark Wielaard70cd9072015-12-02 16:57:44 +01001256 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 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001295 if (dbg != NULL)
1296 {
1297 (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
1298
1299 get_local_names (dbg);
1300 }
1301 }
1302
Mark Wielaardc08079a2015-06-27 22:07:01 +02001303 /* 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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001309 /* 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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001320 /* Iterate over all symbols. */
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001321#ifdef USE_DEMANGLE
1322 size_t demangle_buffer_len = 0;
1323 char *demangle_buffer = NULL;
1324#endif
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001325 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
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001337 deselected by the user with command line options. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001338 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);
Roland McGrath468fe4d2008-12-11 21:00:12 -08001348 if (symstr == NULL)
1349 continue;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001350
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001351#ifdef USE_DEMANGLE
Jan Kratochvil7c6e7852014-01-15 21:16:57 +01001352 /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
1353 if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001354 {
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
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001364 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);
Mark Wielaarda3344c72015-05-06 12:45:49 +02001400 const char *file = dwarf_linesrc (line, NULL, NULL);
1401 file = (file != NULL) ? basename (file) : "???";
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001402 int n;
Mark Wielaarda3344c72015-05-06 12:45:49 +02001403 n = obstack_printf (&whereob, "%s:%d%c", file,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001404 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
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001417 /* Try to find the symbol among the local symbols. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001418 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 }
Ulrich Drepperb4a16cf2011-10-02 08:33:19 -04001448#ifdef USE_DEMANGLE
1449 free (demangle_buffer);
1450#endif
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001451 /* 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)
Roland McGrathcb6d8652007-08-23 08:10:54 +00001456 {
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 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001461 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:
Marek Polacekc8920de2011-05-12 12:08:21 +02001468 show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
1469 longest_name, longest_where);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001470 break;
1471
1472 case format_bsd:
Ulrich Drepper2356ba02011-10-03 07:23:07 -04001473 show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001474 sym_mem, nentries);
1475 break;
1476
1477 case format_posix:
1478 default:
1479 assert (format == format_posix);
Ulrich Drepper2356ba02011-10-03 07:23:07 -04001480 show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
1481 sym_mem, nentries);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001482 break;
1483 }
1484
1485 /* Free all memory. */
Mark Wielaard9beaa942015-06-18 11:07:41 +02001486 if (nentries * sizeof (sym_mem[0]) >= MAX_STACK_ALLOC)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001487 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
Mark Wielaard70cd9072015-12-02 16:57:44 +01001499 if (dwfl == NULL)
1500 (void) dwarf_end (dbg);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001501 }
Mark Wielaard70cd9072015-12-02 16:57:44 +01001502 if (dwfl != NULL)
1503 dwfl_end (dwfl);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001504}
1505
1506
1507static int
Mark Wielaard70cd9072015-12-02 16:57:44 +01001508handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001509 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
Mark Wielaard70cd9072015-12-02 16:57:44 +01001587 show_symbols (fd, ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001588 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}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00001605
1606
1607#include "debugpred.h"