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