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