1/* Print information from ELF file in human-readable form. 2 Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 Written by Ulrich Drepper <drepper@redhat.com>, 1999. 5 6 Red Hat elfutils is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by the 8 Free Software Foundation; version 2 of the License. 9 10 Red Hat elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with Red Hat elfutils; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18 19 Red Hat elfutils is an included package of the Open Invention Network. 20 An included package of the Open Invention Network is a package for which 21 Open Invention Network licensees cross-license their patents. No patent 22 license is granted, either expressly or impliedly, by designation as an 23 included package. Should you wish to participate in the Open Invention 24 Network licensing program, please visit www.openinventionnetwork.com 25 <http://www.openinventionnetwork.com>. */ 26 27#ifdef HAVE_CONFIG_H 28# include <config.h> 29#endif 30 31#include <argp.h> 32#include <assert.h> 33#include <ctype.h> 34#include <dwarf.h> 35#include <errno.h> 36#include <error.h> 37#include <fcntl.h> 38#include <gelf.h> 39#include <inttypes.h> 40#include <langinfo.h> 41#include <libdw.h> 42#include <libdwfl.h> 43#include <libintl.h> 44#include <locale.h> 45#include <stdarg.h> 46#include <stdbool.h> 47#include <stdlib.h> 48#include <string.h> 49#include <time.h> 50#include <unistd.h> 51#include <sys/param.h> 52 53#include <system.h> 54#include "../libelf/libelfP.h" 55#include "../libelf/common.h" 56#include "../libebl/libeblP.h" 57#include "../libdw/libdwP.h" 58#include "../libdwfl/libdwflP.h" 59#include "../libdw/memory-access.h" 60 61 62/* Name and version of program. */ 63static void print_version (FILE *stream, struct argp_state *state); 64void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; 65 66/* Bug report address. */ 67const char *argp_program_bug_address = PACKAGE_BUGREPORT; 68 69/* Definitions of arguments for argp functions. */ 70static const struct argp_option options[] = 71{ 72 { NULL, 0, NULL, 0, N_("Output selection:"), 0 }, 73 { "all", 'a', NULL, 0, N_("Equivalent to: -h -l"), 0 }, 74 { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 }, 75 { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 }, 76 { "histogram", 'I', NULL, 0, 77 N_("Display histogram of bucket list lengths"), 0 }, 78 { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 }, 79 { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 }, 80 { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 }, 81 { "section-headers", 'S', NULL, 0, N_("Display the sections' header"), 0 }, 82 { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 }, 83 { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 }, 84 { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 }, 85 { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, 86 N_("Display DWARF section content. SECTION can be one of abbrev, " 87 "aranges, frame, info, loc, line, ranges, pubnames, str, or macinfo."), 88 0 }, 89 { "notes", 'n', NULL, 0, N_("Display the core notes"), 0 }, 90 { "arch-specific", 'A', NULL, 0, 91 N_("Display architecture specific information (if any)"), 0 }, 92 { "hex-dump", 'x', "SECTION", 0, 93 N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, 94 { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, 95 N_("Print string contents of sections"), 0 }, 96 { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 }, 97 { "archive-index", 'c', NULL, 0, 98 N_("Display the symbol index of an archive"), 0 }, 99 100 { NULL, 0, NULL, 0, N_("Output control:"), 0 }, 101 102 { NULL, 0, NULL, 0, NULL, 0 } 103}; 104 105/* Short description of program. */ 106static const char doc[] = N_("\ 107Print information from ELF file in human-readable form."); 108 109/* Strings for arguments in help texts. */ 110static const char args_doc[] = N_("FILE..."); 111 112/* Prototype for option handler. */ 113static error_t parse_opt (int key, char *arg, struct argp_state *state); 114 115/* Data structure to communicate with argp functions. */ 116static struct argp argp = 117{ 118 options, parse_opt, args_doc, doc, NULL, NULL, NULL 119}; 120 121 122/* Flags set by the option controlling the output. */ 123 124/* True if dynamic segment should be printed. */ 125static bool print_dynamic_table; 126 127/* True if the file header should be printed. */ 128static bool print_file_header; 129 130/* True if the program headers should be printed. */ 131static bool print_program_header; 132 133/* True if relocations should be printed. */ 134static bool print_relocations; 135 136/* True if the section headers should be printed. */ 137static bool print_section_header; 138 139/* True if the symbol table should be printed. */ 140static bool print_symbol_table; 141 142/* True if the version information should be printed. */ 143static bool print_version_info; 144 145/* True if section groups should be printed. */ 146static bool print_section_groups; 147 148/* True if bucket list length histogram should be printed. */ 149static bool print_histogram; 150 151/* True if the architecture specific data should be printed. */ 152static bool print_arch; 153 154/* True if note section content should be printed. */ 155static bool print_notes; 156 157/* True if SHF_STRINGS section content should be printed. */ 158static bool print_string_sections; 159 160/* True if archive index should be printed. */ 161static bool print_archive_index; 162 163/* True if any of the control options except print_archive_index is set. */ 164static bool any_control_option; 165 166/* Select printing of debugging sections. */ 167static enum section_e 168{ 169 section_abbrev = 1, /* .debug_abbrev */ 170 section_aranges = 2, /* .debug_aranges */ 171 section_frame = 4, /* .debug_frame or .eh_frame */ 172 section_info = 8, /* .debug_info */ 173 section_line = 16, /* .debug_line */ 174 section_loc = 32, /* .debug_loc */ 175 section_pubnames = 64,/* .debug_pubnames */ 176 section_str = 128, /* .debug_str */ 177 section_macinfo = 256,/* .debug_macinfo */ 178 section_ranges = 512, /* .debug_ranges */ 179 section_all = (section_abbrev | section_aranges | section_frame 180 | section_info | section_line | section_loc 181 | section_pubnames | section_str | section_macinfo 182 | section_ranges) 183} print_debug_sections; 184 185/* Select hex dumping of sections. */ 186static struct section_argument *dump_data_sections; 187static struct section_argument **dump_data_sections_tail = &dump_data_sections; 188 189/* Select string dumping of sections. */ 190static struct section_argument *string_sections; 191static struct section_argument **string_sections_tail = &string_sections; 192 193struct section_argument 194{ 195 struct section_argument *next; 196 const char *arg; 197}; 198 199/* Number of sections in the file. */ 200static size_t shnum; 201 202 203/* Declarations of local functions. */ 204static void process_file (int fd, const char *fname, bool only_one); 205static void process_elf_file (Dwfl_Module *dwflmod, int fd); 206static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr); 207static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); 208static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); 209static void print_scngrp (Ebl *ebl); 210static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr); 211static void print_relocs (Ebl *ebl); 212static void handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); 213static void handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); 214static void print_symtab (Ebl *ebl, int type); 215static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); 216static void print_verinfo (Ebl *ebl); 217static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); 218static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); 219static void handle_versym (Ebl *ebl, Elf_Scn *scn, 220 GElf_Shdr *shdr); 221static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr); 222static void handle_hash (Ebl *ebl); 223static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr); 224static void print_liblist (Ebl *ebl); 225static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr); 226static void dump_data (Ebl *ebl); 227static void dump_strings (Ebl *ebl); 228static void print_strings (Ebl *ebl); 229static void dump_archive_index (Elf *, const char *); 230 231 232int 233main (int argc, char *argv[]) 234{ 235 /* Set locale. */ 236 setlocale (LC_ALL, ""); 237 238 /* Initialize the message catalog. */ 239 textdomain (PACKAGE_TARNAME); 240 241 /* Parse and process arguments. */ 242 int remaining; 243 argp_parse (&argp, argc, argv, 0, &remaining, NULL); 244 245 /* Before we start tell the ELF library which version we are using. */ 246 elf_version (EV_CURRENT); 247 248 /* Now process all the files given at the command line. */ 249 bool only_one = remaining + 1 == argc; 250 do 251 { 252 /* Open the file. */ 253 int fd = open (argv[remaining], O_RDONLY); 254 if (fd == -1) 255 { 256 error (0, errno, gettext ("cannot open input file")); 257 continue; 258 } 259 260 process_file (fd, argv[remaining], only_one); 261 262 close (fd); 263 } 264 while (++remaining < argc); 265 266 return error_message_count != 0; 267} 268 269 270/* Handle program arguments. */ 271static error_t 272parse_opt (int key, char *arg, 273 struct argp_state *state __attribute__ ((unused))) 274{ 275 switch (key) 276 { 277 case 'a': 278 print_file_header = true; 279 print_program_header = true; 280 print_relocations = true; 281 print_section_header = true; 282 print_symbol_table = true; 283 print_version_info = true; 284 print_dynamic_table = true; 285 print_section_groups = true; 286 print_histogram = true; 287 print_arch = true; 288 print_notes = true; 289 any_control_option = true; 290 break; 291 case 'A': 292 print_arch = true; 293 any_control_option = true; 294 break; 295 case 'd': 296 print_dynamic_table = true; 297 any_control_option = true; 298 break; 299 case 'g': 300 print_section_groups = true; 301 any_control_option = true; 302 break; 303 case 'h': 304 print_file_header = true; 305 any_control_option = true; 306 break; 307 case 'I': 308 print_histogram = true; 309 any_control_option = true; 310 break; 311 case 'l': 312 print_program_header = true; 313 any_control_option = true; 314 break; 315 case 'n': 316 print_notes = true; 317 any_control_option = true; 318 break; 319 case 'r': 320 print_relocations = true; 321 any_control_option = true; 322 break; 323 case 'S': 324 print_section_header = true; 325 any_control_option = true; 326 break; 327 case 's': 328 print_symbol_table = true; 329 any_control_option = true; 330 break; 331 case 'V': 332 print_version_info = true; 333 any_control_option = true; 334 break; 335 case 'c': 336 print_archive_index = true; 337 break; 338 case 'w': 339 if (arg == NULL) 340 print_debug_sections = section_all; 341 else if (strcmp (arg, "abbrev") == 0) 342 print_debug_sections |= section_abbrev; 343 else if (strcmp (arg, "aranges") == 0) 344 print_debug_sections |= section_aranges; 345 else if (strcmp (arg, "ranges") == 0) 346 print_debug_sections |= section_ranges; 347 else if (strcmp (arg, "frame") == 0) 348 print_debug_sections |= section_frame; 349 else if (strcmp (arg, "info") == 0) 350 print_debug_sections |= section_info; 351 else if (strcmp (arg, "loc") == 0) 352 print_debug_sections |= section_loc; 353 else if (strcmp (arg, "line") == 0) 354 print_debug_sections |= section_line; 355 else if (strcmp (arg, "pubnames") == 0) 356 print_debug_sections |= section_pubnames; 357 else if (strcmp (arg, "str") == 0) 358 print_debug_sections |= section_str; 359 else if (strcmp (arg, "macinfo") == 0) 360 print_debug_sections |= section_macinfo; 361 else 362 { 363 fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"), 364 arg); 365 argp_help (&argp, stderr, ARGP_HELP_SEE, 366 program_invocation_short_name); 367 exit (1); 368 } 369 any_control_option = true; 370 break; 371 case 'p': 372 any_control_option = true; 373 if (arg == NULL) 374 { 375 print_string_sections = true; 376 break; 377 } 378 /* Fall through. */ 379 case 'x': 380 { 381 struct section_argument *a = xmalloc (sizeof *a); 382 a->arg = arg; 383 a->next = NULL; 384 struct section_argument ***tailp 385 = key == 'x' ? &dump_data_sections_tail : &string_sections_tail; 386 **tailp = a; 387 *tailp = &a->next; 388 } 389 any_control_option = true; 390 break; 391 case ARGP_KEY_NO_ARGS: 392 fputs (gettext ("Missing file name.\n"), stderr); 393 goto do_argp_help; 394 case ARGP_KEY_FINI: 395 if (! any_control_option && ! print_archive_index) 396 { 397 fputs (gettext ("No operation specified.\n"), stderr); 398 do_argp_help: 399 argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, 400 program_invocation_short_name); 401 exit (1); 402 } 403 break; 404 default: 405 return ARGP_ERR_UNKNOWN; 406 } 407 return 0; 408} 409 410 411/* Print the version information. */ 412static void 413print_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 414{ 415 fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 416 fprintf (stream, gettext ("\ 417Copyright (C) %s Red Hat, Inc.\n\ 418This is free software; see the source for copying conditions. There is NO\n\ 419warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 420"), "2008"); 421 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 422} 423 424 425/* Check if the file is an archive, and if so dump its index. */ 426static void 427check_archive_index (int fd, const char *fname, bool only_one) 428{ 429 /* Create an `Elf' descriptor. */ 430 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 431 if (elf == NULL) 432 error (0, 0, gettext ("cannot generate Elf descriptor: %s"), 433 elf_errmsg (-1)); 434 else 435 { 436 if (elf_kind (elf) == ELF_K_AR) 437 { 438 if (!only_one) 439 printf ("\n%s:\n\n", fname); 440 dump_archive_index (elf, fname); 441 } 442 else 443 error (0, 0, 444 gettext ("'%s' is not an archive, cannot print archive index"), 445 fname); 446 447 /* Now we can close the descriptor. */ 448 if (elf_end (elf) != 0) 449 error (0, 0, gettext ("error while closing Elf descriptor: %s"), 450 elf_errmsg (-1)); 451 } 452} 453 454/* Trivial callback used for checking if we opened an archive. */ 455static int 456count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)), 457 void **userdata __attribute__ ((unused)), 458 const char *name __attribute__ ((unused)), 459 Dwarf_Addr base __attribute__ ((unused)), 460 void *arg) 461{ 462 if (*(bool *) arg) 463 return DWARF_CB_ABORT; 464 *(bool *) arg = true; 465 return DWARF_CB_OK; 466} 467 468struct process_dwflmod_args 469{ 470 int fd; 471 bool only_one; 472}; 473 474static int 475process_dwflmod (Dwfl_Module *dwflmod, 476 void **userdata __attribute__ ((unused)), 477 const char *name __attribute__ ((unused)), 478 Dwarf_Addr base __attribute__ ((unused)), 479 void *arg) 480{ 481 const struct process_dwflmod_args *a = arg; 482 483 /* Print the file name. */ 484 if (!a->only_one) 485 { 486 const char *fname; 487 dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL); 488 489 printf ("\n%s:\n\n", fname); 490 } 491 492 process_elf_file (dwflmod, a->fd); 493 494 return DWARF_CB_OK; 495} 496 497/* Stub libdwfl callback, only the ELF handle already open is ever used. */ 498static int 499find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)), 500 void **userdata __attribute__ ((unused)), 501 const char *modname __attribute__ ((unused)), 502 Dwarf_Addr base __attribute__ ((unused)), 503 const char *file_name __attribute__ ((unused)), 504 const char *debuglink_file __attribute__ ((unused)), 505 GElf_Word debuglink_crc __attribute__ ((unused)), 506 char **debuginfo_file_name __attribute__ ((unused))) 507{ 508 return -1; 509} 510 511/* Process one input file. */ 512static void 513process_file (int fd, const char *fname, bool only_one) 514{ 515 if (print_archive_index) 516 check_archive_index (fd, fname, only_one); 517 518 if (!any_control_option) 519 return; 520 521 /* Duplicate an fd for dwfl_report_offline to swallow. */ 522 int dwfl_fd = dup (fd); 523 if (unlikely (dwfl_fd < 0)) 524 error (EXIT_FAILURE, errno, "dup"); 525 526 /* Use libdwfl in a trivial way to open the libdw handle for us. 527 This takes care of applying relocations to DWARF data in ET_REL files. */ 528 static const Dwfl_Callbacks callbacks = 529 { 530 .section_address = dwfl_offline_section_address, 531 .find_debuginfo = find_no_debuginfo 532 }; 533 Dwfl *dwfl = dwfl_begin (&callbacks); 534 if (likely (dwfl != NULL)) 535 /* Let 0 be the logical address of the file (or first in archive). */ 536 dwfl->offline_next_address = 0; 537 if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL) 538 { 539 struct stat64 st; 540 if (fstat64 (fd, &st) != 0) 541 error (0, errno, gettext ("cannot stat input file")); 542 else if (unlikely (st.st_size == 0)) 543 error (0, 0, gettext ("input file is empty")); 544 else 545 error (0, 0, gettext ("failed reading '%s': %s"), 546 fname, dwfl_errmsg (-1)); 547 } 548 else 549 { 550 dwfl_report_end (dwfl, NULL, NULL); 551 552 if (only_one) 553 { 554 /* Clear ONLY_ONE if we have multiple modules, from an archive. */ 555 bool seen = false; 556 only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0; 557 } 558 559 /* Process the one or more modules gleaned from this file. */ 560 struct process_dwflmod_args a = { .fd = fd, .only_one = only_one }; 561 dwfl_getmodules (dwfl, &process_dwflmod, &a, 0); 562 } 563 dwfl_end (dwfl); 564} 565 566 567/* Process one ELF file. */ 568static void 569process_elf_file (Dwfl_Module *dwflmod, int fd) 570{ 571 GElf_Addr dwflbias; 572 Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias); 573 574 GElf_Ehdr ehdr_mem; 575 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 576 577 if (ehdr == NULL) 578 { 579 elf_error: 580 error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1)); 581 return; 582 } 583 584 Ebl *ebl = ebl_openbackend (elf); 585 if (unlikely (ebl == NULL)) 586 { 587 ebl_error: 588 error (0, errno, gettext ("cannot create EBL handle")); 589 return; 590 } 591 592 /* Determine the number of sections. */ 593 if (unlikely (elf_getshnum (ebl->elf, &shnum) < 0)) 594 error (EXIT_FAILURE, 0, 595 gettext ("cannot determine number of sections: %s"), 596 elf_errmsg (-1)); 597 598 /* For an ET_REL file, libdwfl has adjusted the in-core shdrs 599 and may have applied relocation to some sections. 600 So we need to get a fresh Elf handle on the file to display those. */ 601 bool print_unrelocated = (print_section_header 602 || print_relocations 603 || dump_data_sections != NULL 604 || print_notes); 605 606 Elf *pure_elf = NULL; 607 Ebl *pure_ebl = ebl; 608 if (ehdr->e_type == ET_REL && print_unrelocated) 609 { 610 /* Read the file afresh. */ 611 off64_t aroff = elf_getaroff (elf); 612 pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 613 if (aroff > 0) 614 { 615 /* Archive member. */ 616 (void) elf_rand (pure_elf, aroff); 617 Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf); 618 elf_end (pure_elf); 619 pure_elf = armem; 620 } 621 if (pure_elf == NULL) 622 goto elf_error; 623 pure_ebl = ebl_openbackend (pure_elf); 624 if (pure_ebl == NULL) 625 goto ebl_error; 626 } 627 628 if (print_file_header) 629 print_ehdr (ebl, ehdr); 630 if (print_section_header) 631 print_shdr (pure_ebl, ehdr); 632 if (print_program_header) 633 print_phdr (ebl, ehdr); 634 if (print_section_groups) 635 print_scngrp (ebl); 636 if (print_dynamic_table) 637 print_dynamic (ebl, ehdr); 638 if (print_relocations) 639 print_relocs (pure_ebl); 640 if (print_histogram) 641 handle_hash (ebl); 642 if (print_symbol_table) 643 print_symtab (ebl, SHT_DYNSYM); 644 if (print_version_info) 645 print_verinfo (ebl); 646 if (print_symbol_table) 647 print_symtab (ebl, SHT_SYMTAB); 648 if (print_arch) 649 print_liblist (ebl); 650 if (print_arch) 651 print_attributes (ebl, ehdr); 652 if (dump_data_sections != NULL) 653 dump_data (pure_ebl); 654 if (string_sections != NULL) 655 dump_strings (ebl); 656 if (print_debug_sections != 0) 657 print_debug (dwflmod, ebl, ehdr); 658 if (print_notes) 659 handle_notes (pure_ebl, ehdr); 660 if (print_string_sections) 661 print_strings (ebl); 662 663 ebl_closebackend (ebl); 664 665 if (pure_ebl != ebl) 666 { 667 ebl_closebackend (pure_ebl); 668 elf_end (pure_elf); 669 } 670} 671 672 673/* Print file type. */ 674static void 675print_file_type (unsigned short int e_type) 676{ 677 if (likely (e_type <= ET_CORE)) 678 { 679 static const char *const knowntypes[] = 680 { 681 N_("NONE (None)"), 682 N_("REL (Relocatable file)"), 683 N_("EXEC (Executable file)"), 684 N_("DYN (Shared object file)"), 685 N_("CORE (Core file)") 686 }; 687 puts (gettext (knowntypes[e_type])); 688 } 689 else if (e_type >= ET_LOOS && e_type <= ET_HIOS) 690 printf (gettext ("OS Specific: (%x)\n"), e_type); 691 else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */) 692 printf (gettext ("Processor Specific: (%x)\n"), e_type); 693 else 694 puts ("???"); 695} 696 697 698/* Print ELF header. */ 699static void 700print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) 701{ 702 fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout); 703 for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt) 704 printf (" %02hhx", ehdr->e_ident[cnt]); 705 706 printf (gettext ("\n Class: %s\n"), 707 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32" 708 : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64" 709 : "\?\?\?"); 710 711 printf (gettext (" Data: %s\n"), 712 ehdr->e_ident[EI_DATA] == ELFDATA2LSB 713 ? "2's complement, little endian" 714 : ehdr->e_ident[EI_DATA] == ELFDATA2MSB 715 ? "2's complement, big endian" : "\?\?\?"); 716 717 printf (gettext (" Ident Version: %hhd %s\n"), 718 ehdr->e_ident[EI_VERSION], 719 ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)") 720 : "(\?\?\?)"); 721 722 char buf[512]; 723 printf (gettext (" OS/ABI: %s\n"), 724 ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf))); 725 726 printf (gettext (" ABI Version: %hhd\n"), 727 ehdr->e_ident[EI_ABIVERSION]); 728 729 fputs_unlocked (gettext (" Type: "), stdout); 730 print_file_type (ehdr->e_type); 731 732 printf (gettext (" Machine: %s\n"), ebl->name); 733 734 printf (gettext (" Version: %d %s\n"), 735 ehdr->e_version, 736 ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)"); 737 738 printf (gettext (" Entry point address: %#" PRIx64 "\n"), 739 ehdr->e_entry); 740 741 printf (gettext (" Start of program headers: %" PRId64 " %s\n"), 742 ehdr->e_phoff, gettext ("(bytes into file)")); 743 744 printf (gettext (" Start of section headers: %" PRId64 " %s\n"), 745 ehdr->e_shoff, gettext ("(bytes into file)")); 746 747 printf (gettext (" Flags: %s\n"), 748 ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf))); 749 750 printf (gettext (" Size of this header: %" PRId16 " %s\n"), 751 ehdr->e_ehsize, gettext ("(bytes)")); 752 753 printf (gettext (" Size of program header entries: %" PRId16 " %s\n"), 754 ehdr->e_phentsize, gettext ("(bytes)")); 755 756 printf (gettext (" Number of program headers entries: %" PRId16 "\n"), 757 ehdr->e_phnum); 758 759 printf (gettext (" Size of section header entries: %" PRId16 " %s\n"), 760 ehdr->e_shentsize, gettext ("(bytes)")); 761 762 printf (gettext (" Number of section headers entries: %" PRId16), 763 ehdr->e_shnum); 764 if (ehdr->e_shnum == 0) 765 { 766 GElf_Shdr shdr_mem; 767 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 768 if (shdr != NULL) 769 printf (gettext (" (%" PRIu32 " in [0].sh_size)"), 770 (uint32_t) shdr->sh_size); 771 else 772 fputs_unlocked (gettext (" ([0] not available)"), stdout); 773 } 774 fputc_unlocked ('\n', stdout); 775 776 if (unlikely (ehdr->e_shstrndx == SHN_XINDEX)) 777 { 778 GElf_Shdr shdr_mem; 779 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 780 if (shdr != NULL) 781 /* We managed to get the zeroth section. */ 782 snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"), 783 (uint32_t) shdr->sh_link); 784 else 785 { 786 strncpy (buf, gettext (" ([0] not available)"), sizeof (buf)); 787 buf[sizeof (buf) - 1] = '\0'; 788 } 789 790 printf (gettext (" Section header string table index: XINDEX%s\n\n"), 791 buf); 792 } 793 else 794 printf (gettext (" Section header string table index: %" PRId16 "\n\n"), 795 ehdr->e_shstrndx); 796} 797 798 799static const char * 800get_visibility_type (int value) 801{ 802 switch (value) 803 { 804 case STV_DEFAULT: 805 return "DEFAULT"; 806 case STV_INTERNAL: 807 return "INTERNAL"; 808 case STV_HIDDEN: 809 return "HIDDEN"; 810 case STV_PROTECTED: 811 return "PROTECTED"; 812 default: 813 return "???"; 814 } 815} 816 817 818/* Print the section headers. */ 819static void 820print_shdr (Ebl *ebl, GElf_Ehdr *ehdr) 821{ 822 size_t cnt; 823 size_t shstrndx; 824 825 if (! print_file_header) 826 printf (gettext ("\ 827There are %d section headers, starting at offset %#" PRIx64 ":\n\ 828\n"), 829 ehdr->e_shnum, ehdr->e_shoff); 830 831 /* Get the section header string table index. */ 832 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 833 error (EXIT_FAILURE, 0, 834 gettext ("cannot get section header string table index")); 835 836 puts (gettext ("Section Headers:")); 837 838 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 839 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al")); 840 else 841 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al")); 842 843 for (cnt = 0; cnt < shnum; ++cnt) 844 { 845 Elf_Scn *scn = elf_getscn (ebl->elf, cnt); 846 847 if (unlikely (scn == NULL)) 848 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"), 849 elf_errmsg (-1)); 850 851 /* Get the section header. */ 852 GElf_Shdr shdr_mem; 853 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 854 if (unlikely (shdr == NULL)) 855 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"), 856 elf_errmsg (-1)); 857 858 char flagbuf[20]; 859 char *cp = flagbuf; 860 if (shdr->sh_flags & SHF_WRITE) 861 *cp++ = 'W'; 862 if (shdr->sh_flags & SHF_ALLOC) 863 *cp++ = 'A'; 864 if (shdr->sh_flags & SHF_EXECINSTR) 865 *cp++ = 'X'; 866 if (shdr->sh_flags & SHF_MERGE) 867 *cp++ = 'M'; 868 if (shdr->sh_flags & SHF_STRINGS) 869 *cp++ = 'S'; 870 if (shdr->sh_flags & SHF_INFO_LINK) 871 *cp++ = 'I'; 872 if (shdr->sh_flags & SHF_LINK_ORDER) 873 *cp++ = 'L'; 874 if (shdr->sh_flags & SHF_OS_NONCONFORMING) 875 *cp++ = 'N'; 876 if (shdr->sh_flags & SHF_GROUP) 877 *cp++ = 'G'; 878 if (shdr->sh_flags & SHF_TLS) 879 *cp++ = 'T'; 880 if (shdr->sh_flags & SHF_ORDERED) 881 *cp++ = 'O'; 882 if (shdr->sh_flags & SHF_EXCLUDE) 883 *cp++ = 'E'; 884 *cp = '\0'; 885 886 char buf[128]; 887 printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64 888 " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32 889 " %2" PRId64 "\n", 890 cnt, 891 elf_strptr (ebl->elf, shstrndx, shdr->sh_name) 892 ?: "<corrupt>", 893 ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)), 894 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr, 895 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset, 896 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size, 897 shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info, 898 shdr->sh_addralign); 899 } 900 901 fputc_unlocked ('\n', stdout); 902} 903 904 905/* Print the program header. */ 906static void 907print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) 908{ 909 if (ehdr->e_phnum == 0) 910 /* No program header, this is OK in relocatable objects. */ 911 return; 912 913 puts (gettext ("Program Headers:")); 914 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 915 puts (gettext ("\ 916 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align")); 917 else 918 puts (gettext ("\ 919 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align")); 920 921 /* Process all program headers. */ 922 bool has_relro = false; 923 GElf_Addr relro_from = 0; 924 GElf_Addr relro_to = 0; 925 for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt) 926 { 927 char buf[128]; 928 GElf_Phdr mem; 929 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem); 930 931 /* If for some reason the header cannot be returned show this. */ 932 if (unlikely (phdr == NULL)) 933 { 934 puts (" ???"); 935 continue; 936 } 937 938 printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64 939 " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n", 940 ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)), 941 phdr->p_offset, 942 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr, 943 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr, 944 phdr->p_filesz, 945 phdr->p_memsz, 946 phdr->p_flags & PF_R ? 'R' : ' ', 947 phdr->p_flags & PF_W ? 'W' : ' ', 948 phdr->p_flags & PF_X ? 'E' : ' ', 949 phdr->p_align); 950 951 if (phdr->p_type == PT_INTERP) 952 { 953 /* We can show the user the name of the interpreter. */ 954 size_t maxsize; 955 char *filedata = elf_rawfile (ebl->elf, &maxsize); 956 957 if (filedata != NULL && phdr->p_offset < maxsize) 958 printf (gettext ("\t[Requesting program interpreter: %s]\n"), 959 filedata + phdr->p_offset); 960 } 961 else if (phdr->p_type == PT_GNU_RELRO) 962 { 963 has_relro = true; 964 relro_from = phdr->p_vaddr; 965 relro_to = relro_from + phdr->p_memsz; 966 } 967 } 968 969 /* Get the section header string table index. */ 970 size_t shstrndx; 971 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 972 error (EXIT_FAILURE, 0, 973 gettext ("cannot get section header string table index")); 974 975 puts (gettext ("\n Section to Segment mapping:\n Segment Sections...")); 976 977 for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt) 978 { 979 /* Print the segment number. */ 980 printf (" %2.2zu ", cnt); 981 982 GElf_Phdr phdr_mem; 983 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem); 984 /* This must not happen. */ 985 if (unlikely (phdr == NULL)) 986 error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"), 987 elf_errmsg (-1)); 988 989 /* Iterate over the sections. */ 990 bool in_relro = false; 991 bool in_ro = false; 992 for (size_t inner = 1; inner < shnum; ++inner) 993 { 994 Elf_Scn *scn = elf_getscn (ebl->elf, inner); 995 /* This should not happen. */ 996 if (unlikely (scn == NULL)) 997 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"), 998 elf_errmsg (-1)); 999 1000 /* Get the section header. */ 1001 GElf_Shdr shdr_mem; 1002 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1003 if (unlikely (shdr == NULL)) 1004 error (EXIT_FAILURE, 0, 1005 gettext ("cannot get section header: %s"), 1006 elf_errmsg (-1)); 1007 1008 if (shdr->sh_size > 0 1009 /* Compare allocated sections by VMA, unallocated 1010 sections by file offset. */ 1011 && (shdr->sh_flags & SHF_ALLOC 1012 ? (shdr->sh_addr >= phdr->p_vaddr 1013 && (shdr->sh_addr + shdr->sh_size 1014 <= phdr->p_vaddr + phdr->p_memsz)) 1015 : (shdr->sh_offset >= phdr->p_offset 1016 && (shdr->sh_offset + shdr->sh_size 1017 <= phdr->p_offset + phdr->p_filesz)))) 1018 { 1019 if (has_relro && !in_relro 1020 && shdr->sh_addr >= relro_from 1021 && shdr->sh_addr + shdr->sh_size <= relro_to) 1022 { 1023 fputs_unlocked (" [RELRO:", stdout); 1024 in_relro = true; 1025 } 1026 else if (has_relro && in_relro && shdr->sh_addr >= relro_to) 1027 { 1028 fputs_unlocked ("]", stdout); 1029 in_relro = false; 1030 } 1031 else if (has_relro && in_relro 1032 && shdr->sh_addr + shdr->sh_size > relro_to) 1033 fputs_unlocked ("] <RELRO:", stdout); 1034 else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0) 1035 { 1036 if (!in_ro) 1037 { 1038 fputs_unlocked (" [RO:", stdout); 1039 in_ro = true; 1040 } 1041 } 1042 else 1043 { 1044 /* Determine the segment this section is part of. */ 1045 size_t cnt2; 1046 GElf_Phdr *phdr2 = NULL; 1047 for (cnt2 = 0; cnt2 < ehdr->e_phnum; ++cnt2) 1048 { 1049 GElf_Phdr phdr2_mem; 1050 phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem); 1051 1052 if (phdr2 != NULL && phdr2->p_type == PT_LOAD 1053 && shdr->sh_addr >= phdr2->p_vaddr 1054 && (shdr->sh_addr + shdr->sh_size 1055 <= phdr2->p_vaddr + phdr2->p_memsz)) 1056 break; 1057 } 1058 1059 if (cnt2 < ehdr->e_phnum) 1060 { 1061 if ((phdr2->p_flags & PF_W) == 0 && !in_ro) 1062 { 1063 fputs_unlocked (" [RO:", stdout); 1064 in_ro = true; 1065 } 1066 else if ((phdr2->p_flags & PF_W) != 0 && in_ro) 1067 { 1068 fputs_unlocked ("]", stdout); 1069 in_ro = false; 1070 } 1071 } 1072 } 1073 1074 printf (" %s", 1075 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 1076 1077 /* Signal that this sectin is only partially covered. */ 1078 if (has_relro && in_relro 1079 && shdr->sh_addr + shdr->sh_size > relro_to) 1080 { 1081 fputs_unlocked (">", stdout); 1082 in_relro = false; 1083 } 1084 } 1085 } 1086 if (in_relro || in_ro) 1087 fputs_unlocked ("]", stdout); 1088 1089 /* Finish the line. */ 1090 fputc_unlocked ('\n', stdout); 1091 } 1092} 1093 1094 1095static void 1096handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 1097{ 1098 /* Get the data of the section. */ 1099 Elf_Data *data = elf_getdata (scn, NULL); 1100 1101 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1102 GElf_Shdr symshdr_mem; 1103 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1104 Elf_Data *symdata = elf_getdata (symscn, NULL); 1105 1106 if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL 1107 || symdata == NULL) 1108 return; 1109 1110 /* Get the section header string table index. */ 1111 size_t shstrndx; 1112 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 1113 error (EXIT_FAILURE, 0, 1114 gettext ("cannot get section header string table index")); 1115 1116 Elf32_Word *grpref = (Elf32_Word *) data->d_buf; 1117 1118 GElf_Sym sym_mem; 1119 printf ((grpref[0] & GRP_COMDAT) 1120 ? ngettext ("\ 1121\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n", 1122 "\ 1123\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n", 1124 data->d_size / sizeof (Elf32_Word) - 1) 1125 : ngettext ("\ 1126\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\ 1127\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n", 1128 data->d_size / sizeof (Elf32_Word) - 1), 1129 elf_ndxscn (scn), 1130 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1131 elf_strptr (ebl->elf, symshdr->sh_link, 1132 gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name) 1133 ?: gettext ("<INVALID SYMBOL>"), 1134 data->d_size / sizeof (Elf32_Word) - 1); 1135 1136 for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt) 1137 { 1138 GElf_Shdr grpshdr_mem; 1139 GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]), 1140 &grpshdr_mem); 1141 1142 const char *str; 1143 printf (" [%2u] %s\n", 1144 grpref[cnt], 1145 grpshdr != NULL 1146 && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name)) 1147 ? str : gettext ("<INVALID SECTION>")); 1148 } 1149} 1150 1151 1152static void 1153print_scngrp (Ebl *ebl) 1154{ 1155 /* Find all relocation sections and handle them. */ 1156 Elf_Scn *scn = NULL; 1157 1158 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1159 { 1160 /* Handle the section if it is a symbol table. */ 1161 GElf_Shdr shdr_mem; 1162 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1163 1164 if (shdr != NULL && shdr->sh_type == SHT_GROUP) 1165 handle_scngrp (ebl, scn, shdr); 1166 } 1167} 1168 1169 1170static const struct flags 1171{ 1172 int mask; 1173 const char *str; 1174} dt_flags[] = 1175 { 1176 { DF_ORIGIN, "ORIGIN" }, 1177 { DF_SYMBOLIC, "SYMBOLIC" }, 1178 { DF_TEXTREL, "TEXTREL" }, 1179 { DF_BIND_NOW, "BIND_NOW" }, 1180 { DF_STATIC_TLS, "STATIC_TLS" } 1181 }; 1182static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]); 1183 1184static const struct flags dt_flags_1[] = 1185 { 1186 { DF_1_NOW, "NOW" }, 1187 { DF_1_GLOBAL, "GLOBAL" }, 1188 { DF_1_GROUP, "GROUP" }, 1189 { DF_1_NODELETE, "NODELETE" }, 1190 { DF_1_LOADFLTR, "LOADFLTR" }, 1191 { DF_1_INITFIRST, "INITFIRST" }, 1192 { DF_1_NOOPEN, "NOOPEN" }, 1193 { DF_1_ORIGIN, "ORIGIN" }, 1194 { DF_1_DIRECT, "DIRECT" }, 1195 { DF_1_TRANS, "TRANS" }, 1196 { DF_1_INTERPOSE, "INTERPOSE" }, 1197 { DF_1_NODEFLIB, "NODEFLIB" }, 1198 { DF_1_NODUMP, "NODUMP" }, 1199 { DF_1_CONFALT, "CONFALT" }, 1200 { DF_1_ENDFILTEE, "ENDFILTEE" }, 1201 { DF_1_DISPRELDNE, "DISPRELDNE" }, 1202 { DF_1_DISPRELPND, "DISPRELPND" }, 1203 }; 1204static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]); 1205 1206static const struct flags dt_feature_1[] = 1207 { 1208 { DTF_1_PARINIT, "PARINIT" }, 1209 { DTF_1_CONFEXP, "CONFEXP" } 1210 }; 1211static const int ndt_feature_1 = (sizeof (dt_feature_1) 1212 / sizeof (dt_feature_1[0])); 1213 1214static const struct flags dt_posflag_1[] = 1215 { 1216 { DF_P1_LAZYLOAD, "LAZYLOAD" }, 1217 { DF_P1_GROUPPERM, "GROUPPERM" } 1218 }; 1219static const int ndt_posflag_1 = (sizeof (dt_posflag_1) 1220 / sizeof (dt_posflag_1[0])); 1221 1222 1223static void 1224print_flags (int class, GElf_Xword d_val, const struct flags *flags, 1225 int nflags) 1226{ 1227 bool first = true; 1228 int cnt; 1229 1230 for (cnt = 0; cnt < nflags; ++cnt) 1231 if (d_val & flags[cnt].mask) 1232 { 1233 if (!first) 1234 putchar_unlocked (' '); 1235 fputs_unlocked (flags[cnt].str, stdout); 1236 d_val &= ~flags[cnt].mask; 1237 first = false; 1238 } 1239 1240 if (d_val != 0) 1241 { 1242 if (!first) 1243 putchar_unlocked (' '); 1244 printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val); 1245 } 1246 1247 putchar_unlocked ('\n'); 1248} 1249 1250 1251static void 1252print_dt_flags (int class, GElf_Xword d_val) 1253{ 1254 print_flags (class, d_val, dt_flags, ndt_flags); 1255} 1256 1257 1258static void 1259print_dt_flags_1 (int class, GElf_Xword d_val) 1260{ 1261 print_flags (class, d_val, dt_flags_1, ndt_flags_1); 1262} 1263 1264 1265static void 1266print_dt_feature_1 (int class, GElf_Xword d_val) 1267{ 1268 print_flags (class, d_val, dt_feature_1, ndt_feature_1); 1269} 1270 1271 1272static void 1273print_dt_posflag_1 (int class, GElf_Xword d_val) 1274{ 1275 print_flags (class, d_val, dt_posflag_1, ndt_posflag_1); 1276} 1277 1278 1279static void 1280handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 1281{ 1282 int class = gelf_getclass (ebl->elf); 1283 GElf_Shdr glink; 1284 Elf_Data *data; 1285 size_t cnt; 1286 size_t shstrndx; 1287 1288 /* Get the data of the section. */ 1289 data = elf_getdata (scn, NULL); 1290 if (data == NULL) 1291 return; 1292 1293 /* Get the section header string table index. */ 1294 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 1295 error (EXIT_FAILURE, 0, 1296 gettext ("cannot get section header string table index")); 1297 1298 printf (ngettext ("\ 1299\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 1300 "\ 1301\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 1302 shdr->sh_size / shdr->sh_entsize), 1303 (unsigned long int) (shdr->sh_size / shdr->sh_entsize), 1304 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 1305 shdr->sh_offset, 1306 (int) shdr->sh_link, 1307 elf_strptr (ebl->elf, shstrndx, 1308 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 1309 &glink)->sh_name)); 1310 fputs_unlocked (gettext (" Type Value\n"), stdout); 1311 1312 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 1313 { 1314 GElf_Dyn dynmem; 1315 GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem); 1316 if (dyn == NULL) 1317 break; 1318 1319 char buf[64]; 1320 printf (" %-17s ", 1321 ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf))); 1322 1323 switch (dyn->d_tag) 1324 { 1325 case DT_NULL: 1326 case DT_DEBUG: 1327 case DT_BIND_NOW: 1328 case DT_TEXTREL: 1329 /* No further output. */ 1330 fputc_unlocked ('\n', stdout); 1331 break; 1332 1333 case DT_NEEDED: 1334 printf (gettext ("Shared library: [%s]\n"), 1335 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1336 break; 1337 1338 case DT_SONAME: 1339 printf (gettext ("Library soname: [%s]\n"), 1340 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1341 break; 1342 1343 case DT_RPATH: 1344 printf (gettext ("Library rpath: [%s]\n"), 1345 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1346 break; 1347 1348 case DT_RUNPATH: 1349 printf (gettext ("Library runpath: [%s]\n"), 1350 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1351 break; 1352 1353 case DT_PLTRELSZ: 1354 case DT_RELASZ: 1355 case DT_STRSZ: 1356 case DT_RELSZ: 1357 case DT_RELAENT: 1358 case DT_SYMENT: 1359 case DT_RELENT: 1360 case DT_PLTPADSZ: 1361 case DT_MOVEENT: 1362 case DT_MOVESZ: 1363 case DT_INIT_ARRAYSZ: 1364 case DT_FINI_ARRAYSZ: 1365 case DT_SYMINSZ: 1366 case DT_SYMINENT: 1367 case DT_GNU_CONFLICTSZ: 1368 case DT_GNU_LIBLISTSZ: 1369 printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val); 1370 break; 1371 1372 case DT_VERDEFNUM: 1373 case DT_VERNEEDNUM: 1374 case DT_RELACOUNT: 1375 case DT_RELCOUNT: 1376 printf ("%" PRId64 "\n", dyn->d_un.d_val); 1377 break; 1378 1379 case DT_PLTREL: 1380 puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0)); 1381 break; 1382 1383 case DT_FLAGS: 1384 print_dt_flags (class, dyn->d_un.d_val); 1385 break; 1386 1387 case DT_FLAGS_1: 1388 print_dt_flags_1 (class, dyn->d_un.d_val); 1389 break; 1390 1391 case DT_FEATURE_1: 1392 print_dt_feature_1 (class, dyn->d_un.d_val); 1393 break; 1394 1395 case DT_POSFLAG_1: 1396 print_dt_posflag_1 (class, dyn->d_un.d_val); 1397 break; 1398 1399 default: 1400 printf ("%#0*" PRIx64 "\n", 1401 class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val); 1402 break; 1403 } 1404 } 1405} 1406 1407 1408/* Print the dynamic segment. */ 1409static void 1410print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr) 1411{ 1412 for (int i = 0; i < ehdr->e_phnum; ++i) 1413 { 1414 GElf_Phdr phdr_mem; 1415 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem); 1416 1417 if (phdr != NULL && phdr->p_type == PT_DYNAMIC) 1418 { 1419 Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset); 1420 GElf_Shdr shdr_mem; 1421 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1422 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC) 1423 handle_dynamic (ebl, scn, shdr); 1424 break; 1425 } 1426 } 1427} 1428 1429 1430/* Print relocations. */ 1431static void 1432print_relocs (Ebl *ebl) 1433{ 1434 /* Find all relocation sections and handle them. */ 1435 Elf_Scn *scn = NULL; 1436 1437 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1438 { 1439 /* Handle the section if it is a symbol table. */ 1440 GElf_Shdr shdr_mem; 1441 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1442 1443 if (likely (shdr != NULL)) 1444 { 1445 if (shdr->sh_type == SHT_REL) 1446 handle_relocs_rel (ebl, scn, shdr); 1447 else if (shdr->sh_type == SHT_RELA) 1448 handle_relocs_rela (ebl, scn, shdr); 1449 } 1450 } 1451} 1452 1453 1454/* Handle a relocation section. */ 1455static void 1456handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 1457{ 1458 int class = gelf_getclass (ebl->elf); 1459 int nentries = shdr->sh_size / shdr->sh_entsize; 1460 1461 /* Get the data of the section. */ 1462 Elf_Data *data = elf_getdata (scn, NULL); 1463 if (data == NULL) 1464 return; 1465 1466 /* Get the symbol table information. */ 1467 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1468 GElf_Shdr symshdr_mem; 1469 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1470 Elf_Data *symdata = elf_getdata (symscn, NULL); 1471 1472 /* Get the section header of the section the relocations are for. */ 1473 GElf_Shdr destshdr_mem; 1474 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), 1475 &destshdr_mem); 1476 1477 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL)) 1478 { 1479 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"), 1480 shdr->sh_offset); 1481 return; 1482 } 1483 1484 /* Search for the optional extended section index table. */ 1485 Elf_Data *xndxdata = NULL; 1486 int xndxscnidx = elf_scnshndx (scn); 1487 if (unlikely (xndxscnidx > 0)) 1488 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL); 1489 1490 /* Get the section header string table index. */ 1491 size_t shstrndx; 1492 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 1493 error (EXIT_FAILURE, 0, 1494 gettext ("cannot get section header string table index")); 1495 1496 if (shdr->sh_info != 0) 1497 printf (ngettext ("\ 1498\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 1499 "\ 1500\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 1501 nentries), 1502 (unsigned int) elf_ndxscn (scn), 1503 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1504 (unsigned int) shdr->sh_info, 1505 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 1506 shdr->sh_offset, 1507 nentries); 1508 else 1509 /* The .rel.dyn section does not refer to a specific section but 1510 instead of section index zero. Do not try to print a section 1511 name. */ 1512 printf (ngettext ("\ 1513\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 1514 "\ 1515\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 1516 nentries), 1517 (unsigned int) elf_ndxscn (scn), 1518 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1519 shdr->sh_offset, 1520 nentries); 1521 fputs_unlocked (class == ELFCLASS32 1522 ? gettext ("\ 1523 Offset Type Value Name\n") 1524 : gettext ("\ 1525 Offset Type Value Name\n"), 1526 stdout); 1527 1528 for (int cnt = 0; cnt < nentries; ++cnt) 1529 { 1530 GElf_Rel relmem; 1531 GElf_Rel *rel = gelf_getrel (data, cnt, &relmem); 1532 if (likely (rel != NULL)) 1533 { 1534 char buf[128]; 1535 GElf_Sym symmem; 1536 Elf32_Word xndx; 1537 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, 1538 GELF_R_SYM (rel->r_info), 1539 &symmem, &xndx); 1540 if (unlikely (sym == NULL)) 1541 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", 1542 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1543 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1544 /* Avoid the leading R_ which isn't carrying any 1545 information. */ 1546 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1547 buf, sizeof (buf)) + 2 1548 : gettext ("<INVALID RELOC>"), 1549 gettext ("INVALID SYMBOL"), 1550 (long int) GELF_R_SYM (rel->r_info)); 1551 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 1552 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", 1553 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1554 likely (ebl_reloc_type_check (ebl, 1555 GELF_R_TYPE (rel->r_info))) 1556 /* Avoid the leading R_ which isn't carrying any 1557 information. */ 1558 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1559 buf, sizeof (buf)) + 2 1560 : gettext ("<INVALID RELOC>"), 1561 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1562 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); 1563 else 1564 { 1565 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 1566 sym->st_shndx == SHN_XINDEX 1567 ? xndx : sym->st_shndx), 1568 &destshdr_mem); 1569 1570 if (unlikely (destshdr == NULL)) 1571 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", 1572 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1573 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1574 /* Avoid the leading R_ which isn't carrying any 1575 information. */ 1576 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1577 buf, sizeof (buf)) + 2 1578 : gettext ("<INVALID RELOC>"), 1579 gettext ("INVALID SECTION"), 1580 (long int) (sym->st_shndx == SHN_XINDEX 1581 ? xndx : sym->st_shndx)); 1582 else 1583 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", 1584 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1585 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1586 /* Avoid the leading R_ which isn't carrying any 1587 information. */ 1588 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1589 buf, sizeof (buf)) + 2 1590 : gettext ("<INVALID RELOC>"), 1591 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1592 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 1593 } 1594 } 1595 } 1596} 1597 1598 1599/* Handle a relocation section. */ 1600static void 1601handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 1602{ 1603 int class = gelf_getclass (ebl->elf); 1604 int nentries = shdr->sh_size / shdr->sh_entsize; 1605 1606 /* Get the data of the section. */ 1607 Elf_Data *data = elf_getdata (scn, NULL); 1608 if (data == NULL) 1609 return; 1610 1611 /* Get the symbol table information. */ 1612 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1613 GElf_Shdr symshdr_mem; 1614 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1615 Elf_Data *symdata = elf_getdata (symscn, NULL); 1616 1617 /* Get the section header of the section the relocations are for. */ 1618 GElf_Shdr destshdr_mem; 1619 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), 1620 &destshdr_mem); 1621 1622 if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL)) 1623 { 1624 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"), 1625 shdr->sh_offset); 1626 return; 1627 } 1628 1629 /* Search for the optional extended section index table. */ 1630 Elf_Data *xndxdata = NULL; 1631 int xndxscnidx = elf_scnshndx (scn); 1632 if (unlikely (xndxscnidx > 0)) 1633 xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL); 1634 1635 /* Get the section header string table index. */ 1636 size_t shstrndx; 1637 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 1638 error (EXIT_FAILURE, 0, 1639 gettext ("cannot get section header string table index")); 1640 1641 printf (ngettext ("\ 1642\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 1643 "\ 1644\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 1645 nentries), 1646 elf_ndxscn (scn), 1647 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1648 (unsigned int) shdr->sh_info, 1649 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 1650 shdr->sh_offset, 1651 nentries); 1652 fputs_unlocked (class == ELFCLASS32 1653 ? gettext ("\ 1654 Offset Type Value Addend Name\n") 1655 : gettext ("\ 1656 Offset Type Value Addend Name\n"), 1657 stdout); 1658 1659 for (int cnt = 0; cnt < nentries; ++cnt) 1660 { 1661 GElf_Rela relmem; 1662 GElf_Rela *rel = gelf_getrela (data, cnt, &relmem); 1663 if (likely (rel != NULL)) 1664 { 1665 char buf[64]; 1666 GElf_Sym symmem; 1667 Elf32_Word xndx; 1668 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, 1669 GELF_R_SYM (rel->r_info), 1670 &symmem, &xndx); 1671 1672 if (unlikely (sym == NULL)) 1673 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", 1674 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1675 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1676 /* Avoid the leading R_ which isn't carrying any 1677 information. */ 1678 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1679 buf, sizeof (buf)) + 2 1680 : gettext ("<INVALID RELOC>"), 1681 gettext ("INVALID SYMBOL"), 1682 (long int) GELF_R_SYM (rel->r_info)); 1683 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 1684 printf ("\ 1685 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", 1686 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1687 likely (ebl_reloc_type_check (ebl, 1688 GELF_R_TYPE (rel->r_info))) 1689 /* Avoid the leading R_ which isn't carrying any 1690 information. */ 1691 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1692 buf, sizeof (buf)) + 2 1693 : gettext ("<INVALID RELOC>"), 1694 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1695 rel->r_addend, 1696 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); 1697 else 1698 { 1699 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 1700 sym->st_shndx == SHN_XINDEX 1701 ? xndx : sym->st_shndx), 1702 &destshdr_mem); 1703 1704 if (unlikely (shdr == NULL)) 1705 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", 1706 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1707 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1708 /* Avoid the leading R_ which isn't carrying any 1709 information. */ 1710 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1711 buf, sizeof (buf)) + 2 1712 : gettext ("<INVALID RELOC>"), 1713 gettext ("INVALID SECTION"), 1714 (long int) (sym->st_shndx == SHN_XINDEX 1715 ? xndx : sym->st_shndx)); 1716 else 1717 printf ("\ 1718 %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", 1719 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1720 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1721 /* Avoid the leading R_ which isn't carrying any 1722 information. */ 1723 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1724 buf, sizeof (buf)) + 2 1725 : gettext ("<INVALID RELOC>"), 1726 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1727 rel->r_addend, 1728 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 1729 } 1730 } 1731 } 1732} 1733 1734 1735/* Print the program header. */ 1736static void 1737print_symtab (Ebl *ebl, int type) 1738{ 1739 /* Find the symbol table(s). For this we have to search through the 1740 section table. */ 1741 Elf_Scn *scn = NULL; 1742 1743 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1744 { 1745 /* Handle the section if it is a symbol table. */ 1746 GElf_Shdr shdr_mem; 1747 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1748 1749 if (shdr != NULL && shdr->sh_type == (GElf_Word) type) 1750 handle_symtab (ebl, scn, shdr); 1751 } 1752} 1753 1754 1755static void 1756handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 1757{ 1758 Elf_Data *versym_data = NULL; 1759 Elf_Data *verneed_data = NULL; 1760 Elf_Data *verdef_data = NULL; 1761 Elf_Data *xndx_data = NULL; 1762 int class = gelf_getclass (ebl->elf); 1763 Elf32_Word verneed_stridx = 0; 1764 Elf32_Word verdef_stridx = 0; 1765 1766 /* Get the data of the section. */ 1767 Elf_Data *data = elf_getdata (scn, NULL); 1768 if (data == NULL) 1769 return; 1770 1771 /* Find out whether we have other sections we might need. */ 1772 Elf_Scn *runscn = NULL; 1773 while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL) 1774 { 1775 GElf_Shdr runshdr_mem; 1776 GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem); 1777 1778 if (likely (runshdr != NULL)) 1779 { 1780 if (runshdr->sh_type == SHT_GNU_versym 1781 && runshdr->sh_link == elf_ndxscn (scn)) 1782 /* Bingo, found the version information. Now get the data. */ 1783 versym_data = elf_getdata (runscn, NULL); 1784 else if (runshdr->sh_type == SHT_GNU_verneed) 1785 { 1786 /* This is the information about the needed versions. */ 1787 verneed_data = elf_getdata (runscn, NULL); 1788 verneed_stridx = runshdr->sh_link; 1789 } 1790 else if (runshdr->sh_type == SHT_GNU_verdef) 1791 { 1792 /* This is the information about the defined versions. */ 1793 verdef_data = elf_getdata (runscn, NULL); 1794 verdef_stridx = runshdr->sh_link; 1795 } 1796 else if (runshdr->sh_type == SHT_SYMTAB_SHNDX 1797 && runshdr->sh_link == elf_ndxscn (scn)) 1798 /* Extended section index. */ 1799 xndx_data = elf_getdata (runscn, NULL); 1800 } 1801 } 1802 1803 /* Get the section header string table index. */ 1804 size_t shstrndx; 1805 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 1806 error (EXIT_FAILURE, 0, 1807 gettext ("cannot get section header string table index")); 1808 1809 /* Now we can compute the number of entries in the section. */ 1810 unsigned int nsyms = data->d_size / (class == ELFCLASS32 1811 ? sizeof (Elf32_Sym) 1812 : sizeof (Elf64_Sym)); 1813 1814 printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n", 1815 "\nSymbol table [%2u] '%s' contains %u entries:\n", 1816 nsyms), 1817 (unsigned int) elf_ndxscn (scn), 1818 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms); 1819 GElf_Shdr glink; 1820 printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n", 1821 " %lu local symbols String table: [%2u] '%s'\n", 1822 shdr->sh_info), 1823 (unsigned long int) shdr->sh_info, 1824 (unsigned int) shdr->sh_link, 1825 elf_strptr (ebl->elf, shstrndx, 1826 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 1827 &glink)->sh_name)); 1828 1829 fputs_unlocked (class == ELFCLASS32 1830 ? gettext ("\ 1831 Num: Value Size Type Bind Vis Ndx Name\n") 1832 : gettext ("\ 1833 Num: Value Size Type Bind Vis Ndx Name\n"), 1834 stdout); 1835 1836 for (unsigned int cnt = 0; cnt < nsyms; ++cnt) 1837 { 1838 char typebuf[64]; 1839 char bindbuf[64]; 1840 char scnbuf[64]; 1841 Elf32_Word xndx; 1842 GElf_Sym sym_mem; 1843 GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx); 1844 1845 if (unlikely (sym == NULL)) 1846 continue; 1847 1848 /* Determine the real section index. */ 1849 if (likely (sym->st_shndx != SHN_XINDEX)) 1850 xndx = sym->st_shndx; 1851 1852 printf (gettext ("\ 1853%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"), 1854 cnt, 1855 class == ELFCLASS32 ? 8 : 16, 1856 sym->st_value, 1857 sym->st_size, 1858 ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), 1859 typebuf, sizeof (typebuf)), 1860 ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), 1861 bindbuf, sizeof (bindbuf)), 1862 get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)), 1863 ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf, 1864 sizeof (scnbuf), NULL, shnum), 1865 elf_strptr (ebl->elf, shdr->sh_link, sym->st_name)); 1866 1867 if (versym_data != NULL) 1868 { 1869 /* Get the version information. */ 1870 GElf_Versym versym_mem; 1871 GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem); 1872 1873 if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1)) 1874 { 1875 bool is_nobits = false; 1876 bool check_def = xndx != SHN_UNDEF; 1877 1878 if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX) 1879 { 1880 GElf_Shdr symshdr_mem; 1881 GElf_Shdr *symshdr = 1882 gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem); 1883 1884 is_nobits = (symshdr != NULL 1885 && symshdr->sh_type == SHT_NOBITS); 1886 } 1887 1888 if (is_nobits || ! check_def) 1889 { 1890 /* We must test both. */ 1891 GElf_Vernaux vernaux_mem; 1892 GElf_Vernaux *vernaux = NULL; 1893 size_t vn_offset = 0; 1894 1895 GElf_Verneed verneed_mem; 1896 GElf_Verneed *verneed = gelf_getverneed (verneed_data, 0, 1897 &verneed_mem); 1898 while (verneed != NULL) 1899 { 1900 size_t vna_offset = vn_offset; 1901 1902 vernaux = gelf_getvernaux (verneed_data, 1903 vna_offset += verneed->vn_aux, 1904 &vernaux_mem); 1905 while (vernaux != NULL 1906 && vernaux->vna_other != *versym 1907 && vernaux->vna_next != 0) 1908 { 1909 /* Update the offset. */ 1910 vna_offset += vernaux->vna_next; 1911 1912 vernaux = (vernaux->vna_next == 0 1913 ? NULL 1914 : gelf_getvernaux (verneed_data, 1915 vna_offset, 1916 &vernaux_mem)); 1917 } 1918 1919 /* Check whether we found the version. */ 1920 if (vernaux != NULL && vernaux->vna_other == *versym) 1921 /* Found it. */ 1922 break; 1923 1924 vn_offset += verneed->vn_next; 1925 verneed = (verneed->vn_next == 0 1926 ? NULL 1927 : gelf_getverneed (verneed_data, vn_offset, 1928 &verneed_mem)); 1929 } 1930 1931 if (vernaux != NULL && vernaux->vna_other == *versym) 1932 { 1933 printf ("@%s (%u)", 1934 elf_strptr (ebl->elf, verneed_stridx, 1935 vernaux->vna_name), 1936 (unsigned int) vernaux->vna_other); 1937 check_def = 0; 1938 } 1939 else if (unlikely (! is_nobits)) 1940 error (0, 0, gettext ("bad dynamic symbol")); 1941 else 1942 check_def = 1; 1943 } 1944 1945 if (check_def && *versym != 0x8001) 1946 { 1947 /* We must test both. */ 1948 size_t vd_offset = 0; 1949 1950 GElf_Verdef verdef_mem; 1951 GElf_Verdef *verdef = gelf_getverdef (verdef_data, 0, 1952 &verdef_mem); 1953 while (verdef != NULL) 1954 { 1955 if (verdef->vd_ndx == (*versym & 0x7fff)) 1956 /* Found the definition. */ 1957 break; 1958 1959 vd_offset += verdef->vd_next; 1960 verdef = (verdef->vd_next == 0 1961 ? NULL 1962 : gelf_getverdef (verdef_data, vd_offset, 1963 &verdef_mem)); 1964 } 1965 1966 if (verdef != NULL) 1967 { 1968 GElf_Verdaux verdaux_mem; 1969 GElf_Verdaux *verdaux 1970 = gelf_getverdaux (verdef_data, 1971 vd_offset + verdef->vd_aux, 1972 &verdaux_mem); 1973 1974 if (verdaux != NULL) 1975 printf ((*versym & 0x8000) ? "@%s" : "@@%s", 1976 elf_strptr (ebl->elf, verdef_stridx, 1977 verdaux->vda_name)); 1978 } 1979 } 1980 } 1981 } 1982 1983 putchar_unlocked ('\n'); 1984 } 1985} 1986 1987 1988/* Print version information. */ 1989static void 1990print_verinfo (Ebl *ebl) 1991{ 1992 /* Find the version information sections. For this we have to 1993 search through the section table. */ 1994 Elf_Scn *scn = NULL; 1995 1996 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1997 { 1998 /* Handle the section if it is part of the versioning handling. */ 1999 GElf_Shdr shdr_mem; 2000 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2001 2002 if (likely (shdr != NULL)) 2003 { 2004 if (shdr->sh_type == SHT_GNU_verneed) 2005 handle_verneed (ebl, scn, shdr); 2006 else if (shdr->sh_type == SHT_GNU_verdef) 2007 handle_verdef (ebl, scn, shdr); 2008 else if (shdr->sh_type == SHT_GNU_versym) 2009 handle_versym (ebl, scn, shdr); 2010 } 2011 } 2012} 2013 2014 2015static const char * 2016get_ver_flags (unsigned int flags) 2017{ 2018 static char buf[32]; 2019 char *endp; 2020 2021 if (flags == 0) 2022 return gettext ("none"); 2023 2024 if (flags & VER_FLG_BASE) 2025 endp = stpcpy (buf, "BASE "); 2026 else 2027 endp = buf; 2028 2029 if (flags & VER_FLG_WEAK) 2030 { 2031 if (endp != buf) 2032 endp = stpcpy (endp, "| "); 2033 2034 endp = stpcpy (endp, "WEAK "); 2035 } 2036 2037 if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))) 2038 { 2039 strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp); 2040 buf[sizeof (buf) - 1] = '\0'; 2041 } 2042 2043 return buf; 2044} 2045 2046 2047static void 2048handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 2049{ 2050 int class = gelf_getclass (ebl->elf); 2051 2052 /* Get the data of the section. */ 2053 Elf_Data *data = elf_getdata (scn, NULL); 2054 if (data == NULL) 2055 return; 2056 2057 /* Get the section header string table index. */ 2058 size_t shstrndx; 2059 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 2060 error (EXIT_FAILURE, 0, 2061 gettext ("cannot get section header string table index")); 2062 2063 GElf_Shdr glink; 2064 printf (ngettext ("\ 2065\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2066 "\ 2067\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2068 shdr->sh_info), 2069 (unsigned int) elf_ndxscn (scn), 2070 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info, 2071 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 2072 shdr->sh_offset, 2073 (unsigned int) shdr->sh_link, 2074 elf_strptr (ebl->elf, shstrndx, 2075 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2076 &glink)->sh_name)); 2077 2078 unsigned int offset = 0; 2079 for (int cnt = shdr->sh_info; --cnt >= 0; ) 2080 { 2081 /* Get the data at the next offset. */ 2082 GElf_Verneed needmem; 2083 GElf_Verneed *need = gelf_getverneed (data, offset, &needmem); 2084 if (unlikely (need == NULL)) 2085 break; 2086 2087 printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"), 2088 offset, (unsigned short int) need->vn_version, 2089 elf_strptr (ebl->elf, shdr->sh_link, need->vn_file), 2090 (unsigned short int) need->vn_cnt); 2091 2092 unsigned int auxoffset = offset + need->vn_aux; 2093 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; ) 2094 { 2095 GElf_Vernaux auxmem; 2096 GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem); 2097 if (unlikely (aux == NULL)) 2098 break; 2099 2100 printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"), 2101 auxoffset, 2102 elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name), 2103 get_ver_flags (aux->vna_flags), 2104 (unsigned short int) aux->vna_other); 2105 2106 auxoffset += aux->vna_next; 2107 } 2108 2109 /* Find the next offset. */ 2110 offset += need->vn_next; 2111 } 2112} 2113 2114 2115static void 2116handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 2117{ 2118 /* Get the data of the section. */ 2119 Elf_Data *data = elf_getdata (scn, NULL); 2120 if (data == NULL) 2121 return; 2122 2123 /* Get the section header string table index. */ 2124 size_t shstrndx; 2125 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 2126 error (EXIT_FAILURE, 0, 2127 gettext ("cannot get section header string table index")); 2128 2129 int class = gelf_getclass (ebl->elf); 2130 GElf_Shdr glink; 2131 printf (ngettext ("\ 2132\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2133 "\ 2134\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2135 shdr->sh_info), 2136 (unsigned int) elf_ndxscn (scn), 2137 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2138 shdr->sh_info, 2139 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 2140 shdr->sh_offset, 2141 (unsigned int) shdr->sh_link, 2142 elf_strptr (ebl->elf, shstrndx, 2143 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2144 &glink)->sh_name)); 2145 2146 unsigned int offset = 0; 2147 for (int cnt = shdr->sh_info; --cnt >= 0; ) 2148 { 2149 /* Get the data at the next offset. */ 2150 GElf_Verdef defmem; 2151 GElf_Verdef *def = gelf_getverdef (data, offset, &defmem); 2152 if (unlikely (def == NULL)) 2153 break; 2154 2155 unsigned int auxoffset = offset + def->vd_aux; 2156 GElf_Verdaux auxmem; 2157 GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem); 2158 if (unlikely (aux == NULL)) 2159 break; 2160 2161 printf (gettext ("\ 2162 %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"), 2163 offset, def->vd_version, 2164 get_ver_flags (def->vd_flags), 2165 def->vd_ndx, 2166 def->vd_cnt, 2167 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name)); 2168 2169 auxoffset += aux->vda_next; 2170 for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2) 2171 { 2172 aux = gelf_getverdaux (data, auxoffset, &auxmem); 2173 if (unlikely (aux == NULL)) 2174 break; 2175 2176 printf (gettext (" %#06x: Parent %d: %s\n"), 2177 auxoffset, cnt2, 2178 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name)); 2179 2180 auxoffset += aux->vda_next; 2181 } 2182 2183 /* Find the next offset. */ 2184 offset += def->vd_next; 2185 } 2186} 2187 2188 2189static void 2190handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) 2191{ 2192 int class = gelf_getclass (ebl->elf); 2193 const char **vername; 2194 const char **filename; 2195 2196 /* Get the data of the section. */ 2197 Elf_Data *data = elf_getdata (scn, NULL); 2198 if (data == NULL) 2199 return; 2200 2201 /* Get the section header string table index. */ 2202 size_t shstrndx; 2203 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 2204 error (EXIT_FAILURE, 0, 2205 gettext ("cannot get section header string table index")); 2206 2207 /* We have to find the version definition section and extract the 2208 version names. */ 2209 Elf_Scn *defscn = NULL; 2210 Elf_Scn *needscn = NULL; 2211 2212 Elf_Scn *verscn = NULL; 2213 while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL) 2214 { 2215 GElf_Shdr vershdr_mem; 2216 GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem); 2217 2218 if (likely (vershdr != NULL)) 2219 { 2220 if (vershdr->sh_type == SHT_GNU_verdef) 2221 defscn = verscn; 2222 else if (vershdr->sh_type == SHT_GNU_verneed) 2223 needscn = verscn; 2224 } 2225 } 2226 2227 size_t nvername; 2228 if (defscn != NULL || needscn != NULL) 2229 { 2230 /* We have a version information (better should have). Now get 2231 the version names. First find the maximum version number. */ 2232 nvername = 0; 2233 if (defscn != NULL) 2234 { 2235 /* Run through the version definitions and find the highest 2236 index. */ 2237 unsigned int offset = 0; 2238 Elf_Data *defdata; 2239 GElf_Shdr defshdrmem; 2240 GElf_Shdr *defshdr; 2241 2242 defdata = elf_getdata (defscn, NULL); 2243 if (unlikely (defdata == NULL)) 2244 return; 2245 2246 defshdr = gelf_getshdr (defscn, &defshdrmem); 2247 if (unlikely (defshdr == NULL)) 2248 return; 2249 2250 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt) 2251 { 2252 GElf_Verdef defmem; 2253 GElf_Verdef *def; 2254 2255 /* Get the data at the next offset. */ 2256 def = gelf_getverdef (defdata, offset, &defmem); 2257 if (unlikely (def == NULL)) 2258 break; 2259 2260 nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff)); 2261 2262 offset += def->vd_next; 2263 } 2264 } 2265 if (needscn != NULL) 2266 { 2267 unsigned int offset = 0; 2268 Elf_Data *needdata; 2269 GElf_Shdr needshdrmem; 2270 GElf_Shdr *needshdr; 2271 2272 needdata = elf_getdata (needscn, NULL); 2273 if (unlikely (needdata == NULL)) 2274 return; 2275 2276 needshdr = gelf_getshdr (needscn, &needshdrmem); 2277 if (unlikely (needshdr == NULL)) 2278 return; 2279 2280 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt) 2281 { 2282 GElf_Verneed needmem; 2283 GElf_Verneed *need; 2284 unsigned int auxoffset; 2285 int cnt2; 2286 2287 /* Get the data at the next offset. */ 2288 need = gelf_getverneed (needdata, offset, &needmem); 2289 if (unlikely (need == NULL)) 2290 break; 2291 2292 /* Run through the auxiliary entries. */ 2293 auxoffset = offset + need->vn_aux; 2294 for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) 2295 { 2296 GElf_Vernaux auxmem; 2297 GElf_Vernaux *aux; 2298 2299 aux = gelf_getvernaux (needdata, auxoffset, &auxmem); 2300 if (unlikely (aux == NULL)) 2301 break; 2302 2303 nvername = MAX (nvername, 2304 (size_t) (aux->vna_other & 0x7fff)); 2305 2306 auxoffset += aux->vna_next; 2307 } 2308 2309 offset += need->vn_next; 2310 } 2311 } 2312 2313 /* This is the number of versions we know about. */ 2314 ++nvername; 2315 2316 /* Allocate the array. */ 2317 vername = (const char **) alloca (nvername * sizeof (const char *)); 2318 filename = (const char **) alloca (nvername * sizeof (const char *)); 2319 2320 /* Run through the data structures again and collect the strings. */ 2321 if (defscn != NULL) 2322 { 2323 /* Run through the version definitions and find the highest 2324 index. */ 2325 unsigned int offset = 0; 2326 Elf_Data *defdata; 2327 GElf_Shdr defshdrmem; 2328 GElf_Shdr *defshdr; 2329 2330 defdata = elf_getdata (defscn, NULL); 2331 if (unlikely (defdata == NULL)) 2332 return; 2333 2334 defshdr = gelf_getshdr (defscn, &defshdrmem); 2335 if (unlikely (defshdr == NULL)) 2336 return; 2337 2338 for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt) 2339 { 2340 2341 /* Get the data at the next offset. */ 2342 GElf_Verdef defmem; 2343 GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem); 2344 GElf_Verdaux auxmem; 2345 GElf_Verdaux *aux = gelf_getverdaux (defdata, 2346 offset + def->vd_aux, 2347 &auxmem); 2348 if (unlikely (def == NULL || aux == NULL)) 2349 break; 2350 2351 vername[def->vd_ndx & 0x7fff] 2352 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name); 2353 filename[def->vd_ndx & 0x7fff] = NULL; 2354 2355 offset += def->vd_next; 2356 } 2357 } 2358 if (needscn != NULL) 2359 { 2360 unsigned int offset = 0; 2361 2362 Elf_Data *needdata = elf_getdata (needscn, NULL); 2363 GElf_Shdr needshdrmem; 2364 GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem); 2365 if (unlikely (needdata == NULL || needshdr == NULL)) 2366 return; 2367 2368 for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt) 2369 { 2370 /* Get the data at the next offset. */ 2371 GElf_Verneed needmem; 2372 GElf_Verneed *need = gelf_getverneed (needdata, offset, 2373 &needmem); 2374 if (unlikely (need == NULL)) 2375 break; 2376 2377 /* Run through the auxiliary entries. */ 2378 unsigned int auxoffset = offset + need->vn_aux; 2379 for (int cnt2 = need->vn_cnt; --cnt2 >= 0; ) 2380 { 2381 GElf_Vernaux auxmem; 2382 GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset, 2383 &auxmem); 2384 if (unlikely (aux == NULL)) 2385 break; 2386 2387 vername[aux->vna_other & 0x7fff] 2388 = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name); 2389 filename[aux->vna_other & 0x7fff] 2390 = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file); 2391 2392 auxoffset += aux->vna_next; 2393 } 2394 2395 offset += need->vn_next; 2396 } 2397 } 2398 } 2399 else 2400 { 2401 vername = NULL; 2402 nvername = 1; 2403 filename = NULL; 2404 } 2405 2406 /* Print the header. */ 2407 GElf_Shdr glink; 2408 printf (ngettext ("\ 2409\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", 2410 "\ 2411\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", 2412 shdr->sh_size / shdr->sh_entsize), 2413 (unsigned int) elf_ndxscn (scn), 2414 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2415 (int) (shdr->sh_size / shdr->sh_entsize), 2416 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 2417 shdr->sh_offset, 2418 (unsigned int) shdr->sh_link, 2419 elf_strptr (ebl->elf, shstrndx, 2420 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2421 &glink)->sh_name)); 2422 2423 /* Now we can finally look at the actual contents of this section. */ 2424 for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 2425 { 2426 if (cnt % 2 == 0) 2427 printf ("\n %4d:", cnt); 2428 2429 GElf_Versym symmem; 2430 GElf_Versym *sym = gelf_getversym (data, cnt, &symmem); 2431 if (sym == NULL) 2432 break; 2433 2434 switch (*sym) 2435 { 2436 ssize_t n; 2437 case 0: 2438 fputs_unlocked (gettext (" 0 *local* "), 2439 stdout); 2440 break; 2441 2442 case 1: 2443 fputs_unlocked (gettext (" 1 *global* "), 2444 stdout); 2445 break; 2446 2447 default: 2448 n = printf ("%4d%c%s", 2449 *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ', 2450 (unsigned int) (*sym & 0x7fff) < nvername 2451 ? vername[*sym & 0x7fff] : "???"); 2452 if ((unsigned int) (*sym & 0x7fff) < nvername 2453 && filename[*sym & 0x7fff] != NULL) 2454 n += printf ("(%s)", filename[*sym & 0x7fff]); 2455 printf ("%*s", MAX (0, 33 - (int) n), " "); 2456 break; 2457 } 2458 } 2459 putchar_unlocked ('\n'); 2460} 2461 2462 2463static void 2464print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx, 2465 uint_fast32_t maxlength, Elf32_Word nbucket, 2466 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr) 2467{ 2468 uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t)); 2469 2470 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) 2471 ++counts[lengths[cnt]]; 2472 2473 GElf_Shdr glink; 2474 printf (ngettext ("\ 2475\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2476 "\ 2477\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2478 nbucket), 2479 (unsigned int) elf_ndxscn (scn), 2480 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2481 (int) nbucket, 2482 gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18, 2483 shdr->sh_addr, 2484 shdr->sh_offset, 2485 (unsigned int) shdr->sh_link, 2486 elf_strptr (ebl->elf, shstrndx, 2487 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2488 &glink)->sh_name)); 2489 2490 if (extrastr != NULL) 2491 fputs (extrastr, stdout); 2492 2493 if (likely (nbucket > 0)) 2494 { 2495 uint64_t success = 0; 2496 2497 fputs_unlocked (gettext ("\ 2498 Length Number % of total Coverage\n"), stdout); 2499 printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"), 2500 counts[0], (counts[0] * 100.0) / nbucket); 2501 2502 uint64_t nzero_counts = 0; 2503 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt) 2504 { 2505 nzero_counts += counts[cnt] * cnt; 2506 printf (gettext ("\ 2507%7d %6" PRIu32 " %5.1f%% %5.1f%%\n"), 2508 (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket, 2509 (nzero_counts * 100.0) / nsyms); 2510 } 2511 2512 Elf32_Word acc = 0; 2513 for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt) 2514 { 2515 acc += cnt; 2516 success += counts[cnt] * acc; 2517 } 2518 2519 printf (gettext ("\ 2520 Average number of tests: successful lookup: %f\n\ 2521 unsuccessful lookup: %f\n"), 2522 (double) success / (double) nzero_counts, 2523 (double) nzero_counts / (double) nbucket); 2524 } 2525 2526 free (counts); 2527} 2528 2529 2530/* This function handles the traditional System V-style hash table format. */ 2531static void 2532handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) 2533{ 2534 Elf_Data *data = elf_getdata (scn, NULL); 2535 if (unlikely (data == NULL)) 2536 { 2537 error (0, 0, gettext ("cannot get data for section %d: %s"), 2538 (int) elf_ndxscn (scn), elf_errmsg (-1)); 2539 return; 2540 } 2541 2542 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; 2543 Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1]; 2544 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2]; 2545 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket]; 2546 2547 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t)); 2548 2549 uint_fast32_t maxlength = 0; 2550 uint_fast32_t nsyms = 0; 2551 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) 2552 { 2553 Elf32_Word inner = bucket[cnt]; 2554 while (inner > 0 && inner < nchain) 2555 { 2556 ++nsyms; 2557 if (maxlength < ++lengths[cnt]) 2558 ++maxlength; 2559 2560 inner = chain[inner]; 2561 } 2562 } 2563 2564 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms, 2565 lengths, NULL); 2566 2567 free (lengths); 2568} 2569 2570 2571/* This function handles the incorrect, System V-style hash table 2572 format some 64-bit architectures use. */ 2573static void 2574handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) 2575{ 2576 Elf_Data *data = elf_getdata (scn, NULL); 2577 if (unlikely (data == NULL)) 2578 { 2579 error (0, 0, gettext ("cannot get data for section %d: %s"), 2580 (int) elf_ndxscn (scn), elf_errmsg (-1)); 2581 return; 2582 } 2583 2584 Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0]; 2585 Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1]; 2586 Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2]; 2587 Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket]; 2588 2589 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t)); 2590 2591 uint_fast32_t maxlength = 0; 2592 uint_fast32_t nsyms = 0; 2593 for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt) 2594 { 2595 Elf64_Xword inner = bucket[cnt]; 2596 while (inner > 0 && inner < nchain) 2597 { 2598 ++nsyms; 2599 if (maxlength < ++lengths[cnt]) 2600 ++maxlength; 2601 2602 inner = chain[inner]; 2603 } 2604 } 2605 2606 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms, 2607 lengths, NULL); 2608 2609 free (lengths); 2610} 2611 2612 2613/* This function handles the GNU-style hash table format. */ 2614static void 2615handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) 2616{ 2617 Elf_Data *data = elf_getdata (scn, NULL); 2618 if (unlikely (data == NULL)) 2619 { 2620 error (0, 0, gettext ("cannot get data for section %d: %s"), 2621 (int) elf_ndxscn (scn), elf_errmsg (-1)); 2622 return; 2623 } 2624 2625 Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; 2626 Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1]; 2627 2628 /* Next comes the size of the bitmap. It's measured in words for 2629 the architecture. It's 32 bits for 32 bit archs, and 64 bits for 2630 64 bit archs. */ 2631 Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2]; 2632 if (gelf_getclass (ebl->elf) == ELFCLASS64) 2633 bitmask_words *= 2; 2634 2635 Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3]; 2636 2637 uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t)); 2638 2639 Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4]; 2640 Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words]; 2641 Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words 2642 + nbucket]; 2643 2644 /* Compute distribution of chain lengths. */ 2645 uint_fast32_t maxlength = 0; 2646 uint_fast32_t nsyms = 0; 2647 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) 2648 if (bucket[cnt] != 0) 2649 { 2650 Elf32_Word inner = bucket[cnt] - symbias; 2651 do 2652 { 2653 ++nsyms; 2654 if (maxlength < ++lengths[cnt]) 2655 ++maxlength; 2656 } 2657 while ((chain[inner++] & 1) == 0); 2658 } 2659 2660 /* Count bits in bitmask. */ 2661 uint_fast32_t nbits = 0; 2662 for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt) 2663 { 2664 uint_fast32_t word = bitmask[cnt]; 2665 2666 word = (word & 0x55555555) + ((word >> 1) & 0x55555555); 2667 word = (word & 0x33333333) + ((word >> 2) & 0x33333333); 2668 word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f); 2669 word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff); 2670 nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff); 2671 } 2672 2673 char *str; 2674 if (unlikely (asprintf (&str, gettext ("\ 2675 Symbol Bias: %u\n\ 2676 Bitmask Size: %zu bytes %" PRIuFAST32 "%% bits set 2nd hash shift: %u\n"), 2677 (unsigned int) symbias, 2678 bitmask_words * sizeof (Elf32_Word), 2679 ((nbits * 100 + 50) 2680 / (uint_fast32_t) (bitmask_words 2681 * sizeof (Elf32_Word) * 8)), 2682 (unsigned int) shift) == -1)) 2683 error (EXIT_FAILURE, 0, gettext ("memory exhausted")); 2684 2685 print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms, 2686 lengths, str); 2687 2688 free (str); 2689 free (lengths); 2690} 2691 2692 2693/* Find the symbol table(s). For this we have to search through the 2694 section table. */ 2695static void 2696handle_hash (Ebl *ebl) 2697{ 2698 /* Get the section header string table index. */ 2699 size_t shstrndx; 2700 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 2701 error (EXIT_FAILURE, 0, 2702 gettext ("cannot get section header string table index")); 2703 2704 Elf_Scn *scn = NULL; 2705 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 2706 { 2707 /* Handle the section if it is a symbol table. */ 2708 GElf_Shdr shdr_mem; 2709 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2710 2711 if (likely (shdr != NULL)) 2712 { 2713 if (shdr->sh_type == SHT_HASH) 2714 { 2715 if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword)) 2716 handle_sysv_hash64 (ebl, scn, shdr, shstrndx); 2717 else 2718 handle_sysv_hash (ebl, scn, shdr, shstrndx); 2719 } 2720 else if (shdr->sh_type == SHT_GNU_HASH) 2721 handle_gnu_hash (ebl, scn, shdr, shstrndx); 2722 } 2723 } 2724} 2725 2726 2727static void 2728print_liblist (Ebl *ebl) 2729{ 2730 /* Find the library list sections. For this we have to search 2731 through the section table. */ 2732 Elf_Scn *scn = NULL; 2733 2734 /* Get the section header string table index. */ 2735 size_t shstrndx; 2736 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 2737 error (EXIT_FAILURE, 0, 2738 gettext ("cannot get section header string table index")); 2739 2740 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 2741 { 2742 GElf_Shdr shdr_mem; 2743 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2744 2745 if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST) 2746 { 2747 int nentries = shdr->sh_size / shdr->sh_entsize; 2748 printf (ngettext ("\ 2749\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 2750 "\ 2751\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 2752 nentries), 2753 elf_ndxscn (scn), 2754 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2755 shdr->sh_offset, 2756 nentries); 2757 2758 Elf_Data *data = elf_getdata (scn, NULL); 2759 if (data == NULL) 2760 return; 2761 2762 puts (gettext ("\ 2763 Library Time Stamp Checksum Version Flags")); 2764 2765 for (int cnt = 0; cnt < nentries; ++cnt) 2766 { 2767 GElf_Lib lib_mem; 2768 GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem); 2769 if (unlikely (lib == NULL)) 2770 continue; 2771 2772 time_t t = (time_t) lib->l_time_stamp; 2773 struct tm *tm = gmtime (&t); 2774 if (unlikely (tm == NULL)) 2775 continue; 2776 2777 printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n", 2778 cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name), 2779 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 2780 tm->tm_hour, tm->tm_min, tm->tm_sec, 2781 (unsigned int) lib->l_checksum, 2782 (unsigned int) lib->l_version, 2783 (unsigned int) lib->l_flags); 2784 } 2785 } 2786 } 2787} 2788 2789static void 2790print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) 2791{ 2792 /* Find the object attributes sections. For this we have to search 2793 through the section table. */ 2794 Elf_Scn *scn = NULL; 2795 2796 /* Get the section header string table index. */ 2797 size_t shstrndx; 2798 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 2799 error (EXIT_FAILURE, 0, 2800 gettext ("cannot get section header string table index")); 2801 2802 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 2803 { 2804 GElf_Shdr shdr_mem; 2805 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2806 2807 if (shdr == NULL || shdr->sh_type != SHT_GNU_ATTRIBUTES) 2808 continue; 2809 2810 printf (gettext ("\ 2811\nObject attributes section [%2zu] '%s' of %" PRIu64 2812 " bytes at offset %#0" PRIx64 ":\n"), 2813 elf_ndxscn (scn), 2814 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2815 shdr->sh_size, shdr->sh_offset); 2816 2817 Elf_Data *data = elf_rawdata (scn, NULL); 2818 if (data == NULL) 2819 return; 2820 2821 const unsigned char *p = data->d_buf; 2822 2823 if (unlikely (*p++ != 'A')) 2824 return; 2825 2826 fputs_unlocked (gettext (" Owner Size\n"), stdout); 2827 2828 inline size_t left (void) 2829 { 2830 return (const unsigned char *) data->d_buf + data->d_size - p; 2831 } 2832 2833 while (left () >= 4) 2834 { 2835 uint32_t len; 2836 memcpy (&len, p, sizeof len); 2837 2838 if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) 2839 CONVERT (len); 2840 2841 if (unlikely (len > left ())) 2842 break; 2843 2844 const unsigned char *name = p + sizeof len; 2845 p += len; 2846 2847 unsigned const char *q = memchr (name, '\0', len); 2848 if (unlikely (q == NULL)) 2849 continue; 2850 ++q; 2851 2852 printf (gettext (" %-13s %4" PRIu32 "\n"), name, len); 2853 2854 if (q - name == sizeof "gnu" 2855 && !memcmp (name, "gnu", sizeof "gnu")) 2856 while (q < p) 2857 { 2858 const unsigned char *const sub = q; 2859 2860 unsigned int subsection_tag; 2861 get_uleb128 (subsection_tag, q); 2862 if (unlikely (q >= p)) 2863 break; 2864 2865 uint32_t subsection_len; 2866 if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len)) 2867 break; 2868 2869 memcpy (&subsection_len, q, sizeof subsection_len); 2870 2871 if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) 2872 CONVERT (subsection_len); 2873 2874 if (unlikely (p - sub < (ptrdiff_t) subsection_len)) 2875 break; 2876 2877 const unsigned char *r = q + sizeof subsection_len; 2878 q = sub + subsection_len; 2879 2880 switch (subsection_tag) 2881 { 2882 default: 2883 printf (gettext (" %-4u %12" PRIu32 "\n"), 2884 subsection_tag, subsection_len); 2885 break; 2886 2887 case 1: /* Tag_File */ 2888 printf (gettext (" File: %11" PRIu32 "\n"), 2889 subsection_len); 2890 2891 while (r < q) 2892 { 2893 unsigned int tag; 2894 get_uleb128 (tag, r); 2895 if (unlikely (r >= q)) 2896 break; 2897 2898 uint64_t value = 0; 2899 const char *string = NULL; 2900 if (tag == 32 || (tag & 1) == 0) 2901 { 2902 get_uleb128 (value, r); 2903 if (r > q) 2904 break; 2905 } 2906 if (tag == 32 || (tag & 1) != 0) 2907 { 2908 r = memchr (r, '\0', q - r); 2909 if (r == NULL) 2910 break; 2911 ++r; 2912 } 2913 2914 const char *tag_name = NULL; 2915 const char *value_name = NULL; 2916 ebl_check_object_attribute (ebl, (const char *) name, 2917 tag, value, 2918 &tag_name, &value_name); 2919 2920 if (tag_name != NULL) 2921 { 2922 if (tag == 32) 2923 printf (gettext (" %s: %" PRId64 ", %s\n"), 2924 tag_name, value, string); 2925 else if (string == NULL && value_name == NULL) 2926 printf (gettext (" %s: %" PRId64 "\n"), 2927 tag_name, value); 2928 else 2929 printf (gettext (" %s: %s\n"), 2930 tag_name, string ?: value_name); 2931 } 2932 else 2933 { 2934 assert (tag != 32); 2935 if (string == NULL) 2936 printf (gettext (" %u: %" PRId64 "\n"), 2937 tag, value); 2938 else 2939 printf (gettext (" %u: %s\n"), 2940 tag, string); 2941 } 2942 } 2943 } 2944 } 2945 } 2946 } 2947} 2948 2949 2950static char * 2951format_dwarf_addr (Dwfl_Module *dwflmod, 2952 int address_size, Dwarf_Addr address) 2953{ 2954 /* See if there is a name we can give for this address. */ 2955 GElf_Sym sym; 2956 const char *name = dwfl_module_addrsym (dwflmod, address, &sym, NULL); 2957 if (name != NULL) 2958 sym.st_value = address - sym.st_value; 2959 2960 /* Relativize the address. */ 2961 int n = dwfl_module_relocations (dwflmod); 2962 int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address); 2963 2964 /* In an ET_REL file there is a section name to refer to. */ 2965 const char *scn = (i < 0 ? NULL 2966 : dwfl_module_relocation_info (dwflmod, i, NULL)); 2967 2968 char *result; 2969 if ((name != NULL 2970 ? (sym.st_value != 0 2971 ? (scn != NULL 2972 ? (address_size == 0 2973 ? asprintf (&result, 2974 gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"), 2975 scn, address, name, sym.st_value) 2976 : asprintf (&result, 2977 gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"), 2978 scn, 2 + address_size * 2, address, 2979 name, sym.st_value)) 2980 : (address_size == 0 2981 ? asprintf (&result, 2982 gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"), 2983 address, name, sym.st_value) 2984 : asprintf (&result, 2985 gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"), 2986 2 + address_size * 2, address, 2987 name, sym.st_value))) 2988 : (scn != NULL 2989 ? (address_size == 0 2990 ? asprintf (&result, 2991 gettext ("%s+%#" PRIx64 " <%s>"), 2992 scn, address, name) 2993 : asprintf (&result, 2994 gettext ("%s+%#0*" PRIx64 " <%s>"), 2995 scn, 2 + address_size * 2, address, name)) 2996 : (address_size == 0 2997 ? asprintf (&result, 2998 gettext ("%#" PRIx64 " <%s>"), 2999 address, name) 3000 : asprintf (&result, 3001 gettext ("%#0*" PRIx64 " <%s>"), 3002 2 + address_size * 2, address, name)))) 3003 : (scn != NULL 3004 ? (address_size == 0 3005 ? asprintf (&result, 3006 gettext ("%s+%#" PRIx64), 3007 scn, address) 3008 : asprintf (&result, 3009 gettext ("%s+%#0*" PRIx64), 3010 scn, 2 + address_size * 2, address)) 3011 : (address_size == 0 3012 ? asprintf (&result, 3013 "%#" PRIx64, 3014 address) 3015 : asprintf (&result, 3016 "%#0*" PRIx64, 3017 2 + address_size * 2, address)))) < 0) 3018 error (EXIT_FAILURE, 0, _("memory exhausted")); 3019 3020 return result; 3021} 3022 3023static const char * 3024dwarf_tag_string (unsigned int tag) 3025{ 3026 static const char *const known_tags[] = 3027 { 3028 [DW_TAG_array_type] = "array_type", 3029 [DW_TAG_class_type] = "class_type", 3030 [DW_TAG_entry_point] = "entry_point", 3031 [DW_TAG_enumeration_type] = "enumeration_type", 3032 [DW_TAG_formal_parameter] = "formal_parameter", 3033 [DW_TAG_imported_declaration] = "imported_declaration", 3034 [DW_TAG_label] = "label", 3035 [DW_TAG_lexical_block] = "lexical_block", 3036 [DW_TAG_member] = "member", 3037 [DW_TAG_pointer_type] = "pointer_type", 3038 [DW_TAG_reference_type] = "reference_type", 3039 [DW_TAG_compile_unit] = "compile_unit", 3040 [DW_TAG_string_type] = "string_type", 3041 [DW_TAG_structure_type] = "structure_type", 3042 [DW_TAG_subroutine_type] = "subroutine_type", 3043 [DW_TAG_typedef] = "typedef", 3044 [DW_TAG_union_type] = "union_type", 3045 [DW_TAG_unspecified_parameters] = "unspecified_parameters", 3046 [DW_TAG_variant] = "variant", 3047 [DW_TAG_common_block] = "common_block", 3048 [DW_TAG_common_inclusion] = "common_inclusion", 3049 [DW_TAG_inheritance] = "inheritance", 3050 [DW_TAG_inlined_subroutine] = "inlined_subroutine", 3051 [DW_TAG_module] = "module", 3052 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type", 3053 [DW_TAG_set_type] = "set_type", 3054 [DW_TAG_subrange_type] = "subrange_type", 3055 [DW_TAG_with_stmt] = "with_stmt", 3056 [DW_TAG_access_declaration] = "access_declaration", 3057 [DW_TAG_base_type] = "base_type", 3058 [DW_TAG_catch_block] = "catch_block", 3059 [DW_TAG_const_type] = "const_type", 3060 [DW_TAG_constant] = "constant", 3061 [DW_TAG_enumerator] = "enumerator", 3062 [DW_TAG_file_type] = "file_type", 3063 [DW_TAG_friend] = "friend", 3064 [DW_TAG_namelist] = "namelist", 3065 [DW_TAG_namelist_item] = "namelist_item", 3066 [DW_TAG_packed_type] = "packed_type", 3067 [DW_TAG_subprogram] = "subprogram", 3068 [DW_TAG_template_type_parameter] = "template_type_parameter", 3069 [DW_TAG_template_value_parameter] = "template_value_parameter", 3070 [DW_TAG_thrown_type] = "thrown_type", 3071 [DW_TAG_try_block] = "try_block", 3072 [DW_TAG_variant_part] = "variant_part", 3073 [DW_TAG_variable] = "variable", 3074 [DW_TAG_volatile_type] = "volatile_type", 3075 [DW_TAG_dwarf_procedure] = "dwarf_procedure", 3076 [DW_TAG_restrict_type] = "restrict_type", 3077 [DW_TAG_interface_type] = "interface_type", 3078 [DW_TAG_namespace] = "namespace", 3079 [DW_TAG_imported_module] = "imported_module", 3080 [DW_TAG_unspecified_type] = "unspecified_type", 3081 [DW_TAG_partial_unit] = "partial_unit", 3082 [DW_TAG_imported_unit] = "imported_unit", 3083 [DW_TAG_mutable_type] = "mutable_type", 3084 [DW_TAG_condition] = "condition", 3085 [DW_TAG_shared_type] = "shared_type", 3086 }; 3087 const unsigned int nknown_tags = (sizeof (known_tags) 3088 / sizeof (known_tags[0])); 3089 static char buf[40]; 3090 const char *result = NULL; 3091 3092 if (likely (tag < nknown_tags)) 3093 result = known_tags[tag]; 3094 3095 if (unlikely (result == NULL)) 3096 /* There are a few known extensions. */ 3097 switch (tag) 3098 { 3099 case DW_TAG_MIPS_loop: 3100 result = "MIPS_loop"; 3101 break; 3102 3103 case DW_TAG_format_label: 3104 result = "format_label"; 3105 break; 3106 3107 case DW_TAG_function_template: 3108 result = "function_template"; 3109 break; 3110 3111 case DW_TAG_class_template: 3112 result = "class_template"; 3113 break; 3114 3115 default: 3116 if (tag < DW_TAG_lo_user) 3117 snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag); 3118 else 3119 snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag); 3120 result = buf; 3121 break; 3122 } 3123 3124 return result; 3125} 3126 3127 3128static const char * 3129dwarf_attr_string (unsigned int attrnum) 3130{ 3131 static const char *const known_attrs[] = 3132 { 3133 [DW_AT_sibling] = "sibling", 3134 [DW_AT_location] = "location", 3135 [DW_AT_name] = "name", 3136 [DW_AT_ordering] = "ordering", 3137 [DW_AT_subscr_data] = "subscr_data", 3138 [DW_AT_byte_size] = "byte_size", 3139 [DW_AT_bit_offset] = "bit_offset", 3140 [DW_AT_bit_size] = "bit_size", 3141 [DW_AT_element_list] = "element_list", 3142 [DW_AT_stmt_list] = "stmt_list", 3143 [DW_AT_low_pc] = "low_pc", 3144 [DW_AT_high_pc] = "high_pc", 3145 [DW_AT_language] = "language", 3146 [DW_AT_member] = "member", 3147 [DW_AT_discr] = "discr", 3148 [DW_AT_discr_value] = "discr_value", 3149 [DW_AT_visibility] = "visibility", 3150 [DW_AT_import] = "import", 3151 [DW_AT_string_length] = "string_length", 3152 [DW_AT_common_reference] = "common_reference", 3153 [DW_AT_comp_dir] = "comp_dir", 3154 [DW_AT_const_value] = "const_value", 3155 [DW_AT_containing_type] = "containing_type", 3156 [DW_AT_default_value] = "default_value", 3157 [DW_AT_inline] = "inline", 3158 [DW_AT_is_optional] = "is_optional", 3159 [DW_AT_lower_bound] = "lower_bound", 3160 [DW_AT_producer] = "producer", 3161 [DW_AT_prototyped] = "prototyped", 3162 [DW_AT_return_addr] = "return_addr", 3163 [DW_AT_start_scope] = "start_scope", 3164 [DW_AT_bit_stride] = "bit_stride", 3165 [DW_AT_upper_bound] = "upper_bound", 3166 [DW_AT_abstract_origin] = "abstract_origin", 3167 [DW_AT_accessibility] = "accessibility", 3168 [DW_AT_address_class] = "address_class", 3169 [DW_AT_artificial] = "artificial", 3170 [DW_AT_base_types] = "base_types", 3171 [DW_AT_calling_convention] = "calling_convention", 3172 [DW_AT_count] = "count", 3173 [DW_AT_data_member_location] = "data_member_location", 3174 [DW_AT_decl_column] = "decl_column", 3175 [DW_AT_decl_file] = "decl_file", 3176 [DW_AT_decl_line] = "decl_line", 3177 [DW_AT_declaration] = "declaration", 3178 [DW_AT_discr_list] = "discr_list", 3179 [DW_AT_encoding] = "encoding", 3180 [DW_AT_external] = "external", 3181 [DW_AT_frame_base] = "frame_base", 3182 [DW_AT_friend] = "friend", 3183 [DW_AT_identifier_case] = "identifier_case", 3184 [DW_AT_macro_info] = "macro_info", 3185 [DW_AT_namelist_item] = "namelist_item", 3186 [DW_AT_priority] = "priority", 3187 [DW_AT_segment] = "segment", 3188 [DW_AT_specification] = "specification", 3189 [DW_AT_static_link] = "static_link", 3190 [DW_AT_type] = "type", 3191 [DW_AT_use_location] = "use_location", 3192 [DW_AT_variable_parameter] = "variable_parameter", 3193 [DW_AT_virtuality] = "virtuality", 3194 [DW_AT_vtable_elem_location] = "vtable_elem_location", 3195 [DW_AT_allocated] = "allocated", 3196 [DW_AT_associated] = "associated", 3197 [DW_AT_data_location] = "data_location", 3198 [DW_AT_byte_stride] = "byte_stride", 3199 [DW_AT_entry_pc] = "entry_pc", 3200 [DW_AT_use_UTF8] = "use_UTF8", 3201 [DW_AT_extension] = "extension", 3202 [DW_AT_ranges] = "ranges", 3203 [DW_AT_trampoline] = "trampoline", 3204 [DW_AT_call_column] = "call_column", 3205 [DW_AT_call_file] = "call_file", 3206 [DW_AT_call_line] = "call_line", 3207 [DW_AT_description] = "description", 3208 [DW_AT_binary_scale] = "binary_scale", 3209 [DW_AT_decimal_scale] = "decimal_scale", 3210 [DW_AT_small] = "small", 3211 [DW_AT_decimal_sign] = "decimal_sign", 3212 [DW_AT_digit_count] = "digit_count", 3213 [DW_AT_picture_string] = "picture_string", 3214 [DW_AT_mutable] = "mutable", 3215 [DW_AT_threads_scaled] = "threads_scaled", 3216 [DW_AT_explicit] = "explicit", 3217 [DW_AT_object_pointer] = "object_pointer", 3218 [DW_AT_endianity] = "endianity", 3219 [DW_AT_elemental] = "elemental", 3220 [DW_AT_pure] = "pure", 3221 [DW_AT_recursive] = "recursive", 3222 }; 3223 const unsigned int nknown_attrs = (sizeof (known_attrs) 3224 / sizeof (known_attrs[0])); 3225 static char buf[40]; 3226 const char *result = NULL; 3227 3228 if (likely (attrnum < nknown_attrs)) 3229 result = known_attrs[attrnum]; 3230 3231 if (unlikely (result == NULL)) 3232 /* There are a few known extensions. */ 3233 switch (attrnum) 3234 { 3235 case DW_AT_MIPS_fde: 3236 result = "MIPS_fde"; 3237 break; 3238 3239 case DW_AT_MIPS_loop_begin: 3240 result = "MIPS_loop_begin"; 3241 break; 3242 3243 case DW_AT_MIPS_tail_loop_begin: 3244 result = "MIPS_tail_loop_begin"; 3245 break; 3246 3247 case DW_AT_MIPS_epilog_begin: 3248 result = "MIPS_epilog_begin"; 3249 break; 3250 3251 case DW_AT_MIPS_loop_unroll_factor: 3252 result = "MIPS_loop_unroll_factor"; 3253 break; 3254 3255 case DW_AT_MIPS_software_pipeline_depth: 3256 result = "MIPS_software_pipeline_depth"; 3257 break; 3258 3259 case DW_AT_MIPS_linkage_name: 3260 result = "MIPS_linkage_name"; 3261 break; 3262 3263 case DW_AT_MIPS_stride: 3264 result = "MIPS_stride"; 3265 break; 3266 3267 case DW_AT_MIPS_abstract_name: 3268 result = "MIPS_abstract_name"; 3269 break; 3270 3271 case DW_AT_MIPS_clone_origin: 3272 result = "MIPS_clone_origin"; 3273 break; 3274 3275 case DW_AT_MIPS_has_inlines: 3276 result = "MIPS_has_inlines"; 3277 break; 3278 3279 case DW_AT_MIPS_stride_byte: 3280 result = "MIPS_stride_byte"; 3281 break; 3282 3283 case DW_AT_MIPS_stride_elem: 3284 result = "MIPS_stride_elem"; 3285 break; 3286 3287 case DW_AT_MIPS_ptr_dopetype: 3288 result = "MIPS_ptr_dopetype"; 3289 break; 3290 3291 case DW_AT_MIPS_allocatable_dopetype: 3292 result = "MIPS_allocatable_dopetype"; 3293 break; 3294 3295 case DW_AT_MIPS_assumed_shape_dopetype: 3296 result = "MIPS_assumed_shape_dopetype"; 3297 break; 3298 3299 case DW_AT_MIPS_assumed_size: 3300 result = "MIPS_assumed_size"; 3301 break; 3302 3303 case DW_AT_sf_names: 3304 result = "sf_names"; 3305 break; 3306 3307 case DW_AT_src_info: 3308 result = "src_info"; 3309 break; 3310 3311 case DW_AT_mac_info: 3312 result = "mac_info"; 3313 break; 3314 3315 case DW_AT_src_coords: 3316 result = "src_coords"; 3317 break; 3318 3319 case DW_AT_body_begin: 3320 result = "body_begin"; 3321 break; 3322 3323 case DW_AT_body_end: 3324 result = "body_end"; 3325 break; 3326 3327 default: 3328 if (attrnum < DW_AT_lo_user) 3329 snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"), 3330 attrnum); 3331 else 3332 snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"), 3333 attrnum); 3334 result = buf; 3335 break; 3336 } 3337 3338 return result; 3339} 3340 3341 3342static const char * 3343dwarf_form_string (unsigned int form) 3344{ 3345 static const char *const known_forms[] = 3346 { 3347 [DW_FORM_addr] = "addr", 3348 [DW_FORM_block2] = "block2", 3349 [DW_FORM_block4] = "block4", 3350 [DW_FORM_data2] = "data2", 3351 [DW_FORM_data4] = "data4", 3352 [DW_FORM_data8] = "data8", 3353 [DW_FORM_string] = "string", 3354 [DW_FORM_block] = "block", 3355 [DW_FORM_block1] = "block1", 3356 [DW_FORM_data1] = "data1", 3357 [DW_FORM_flag] = "flag", 3358 [DW_FORM_sdata] = "sdata", 3359 [DW_FORM_strp] = "strp", 3360 [DW_FORM_udata] = "udata", 3361 [DW_FORM_ref_addr] = "ref_addr", 3362 [DW_FORM_ref1] = "ref1", 3363 [DW_FORM_ref2] = "ref2", 3364 [DW_FORM_ref4] = "ref4", 3365 [DW_FORM_ref8] = "ref8", 3366 [DW_FORM_ref_udata] = "ref_udata", 3367 [DW_FORM_indirect] = "indirect" 3368 }; 3369 const unsigned int nknown_forms = (sizeof (known_forms) 3370 / sizeof (known_forms[0])); 3371 static char buf[40]; 3372 const char *result = NULL; 3373 3374 if (likely (form < nknown_forms)) 3375 result = known_forms[form]; 3376 3377 if (unlikely (result == NULL)) 3378 snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64), 3379 (uint64_t) form); 3380 3381 return result; 3382} 3383 3384 3385static const char * 3386dwarf_lang_string (unsigned int lang) 3387{ 3388 static const char *const known[] = 3389 { 3390 [DW_LANG_C89] = "ISO C89", 3391 [DW_LANG_C] = "C", 3392 [DW_LANG_Ada83] = "Ada83", 3393 [DW_LANG_C_plus_plus] = "C++", 3394 [DW_LANG_Cobol74] = "Cobol74", 3395 [DW_LANG_Cobol85] = "Cobol85", 3396 [DW_LANG_Fortran77] = "Fortran77", 3397 [DW_LANG_Fortran90] = "Fortran90", 3398 [DW_LANG_Pascal83] = "Pascal83", 3399 [DW_LANG_Modula2] = "Modula2", 3400 [DW_LANG_Java] = "Java", 3401 [DW_LANG_C99] = "ISO C99", 3402 [DW_LANG_Ada95] = "Ada95", 3403 [DW_LANG_Fortran95] = "Fortran95", 3404 [DW_LANG_PL1] = "PL1", 3405 [DW_LANG_Objc] = "Objective C", 3406 [DW_LANG_ObjC_plus_plus] = "Objective C++", 3407 [DW_LANG_UPC] = "UPC", 3408 [DW_LANG_D] = "D", 3409 }; 3410 3411 if (likely (lang < sizeof (known) / sizeof (known[0]))) 3412 return known[lang]; 3413 else if (lang == DW_LANG_Mips_Assembler) 3414 /* This language tag is used for assembler in general. */ 3415 return "Assembler"; 3416 3417 if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user) 3418 { 3419 static char buf[30]; 3420 snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user); 3421 return buf; 3422 } 3423 3424 return "???"; 3425} 3426 3427 3428static const char * 3429dwarf_inline_string (unsigned int code) 3430{ 3431 static const char *const known[] = 3432 { 3433 [DW_INL_not_inlined] = "not_inlined", 3434 [DW_INL_inlined] = "inlined", 3435 [DW_INL_declared_not_inlined] = "declared_not_inlined", 3436 [DW_INL_declared_inlined] = "declared_inlined" 3437 }; 3438 3439 if (likely (code < sizeof (known) / sizeof (known[0]))) 3440 return known[code]; 3441 3442 return "???"; 3443} 3444 3445 3446static const char * 3447dwarf_encoding_string (unsigned int code) 3448{ 3449 static const char *const known[] = 3450 { 3451 [DW_ATE_void] = "void", 3452 [DW_ATE_address] = "address", 3453 [DW_ATE_boolean] = "boolean", 3454 [DW_ATE_complex_float] = "complex_float", 3455 [DW_ATE_float] = "float", 3456 [DW_ATE_signed] = "signed", 3457 [DW_ATE_signed_char] = "signed_char", 3458 [DW_ATE_unsigned] = "unsigned", 3459 [DW_ATE_unsigned_char] = "unsigned_char", 3460 [DW_ATE_imaginary_float] = "imaginary_float", 3461 [DW_ATE_packed_decimal] = "packed_decimal", 3462 [DW_ATE_numeric_string] = "numeric_string", 3463 [DW_ATE_edited] = "edited", 3464 [DW_ATE_signed_fixed] = "signed_fixed", 3465 [DW_ATE_unsigned_fixed] = "unsigned_fixed", 3466 [DW_ATE_decimal_float] = "decimal_float", 3467 }; 3468 3469 if (likely (code < sizeof (known) / sizeof (known[0]))) 3470 return known[code]; 3471 3472 if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user) 3473 { 3474 static char buf[30]; 3475 snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user); 3476 return buf; 3477 } 3478 3479 return "???"; 3480} 3481 3482 3483static const char * 3484dwarf_access_string (unsigned int code) 3485{ 3486 static const char *const known[] = 3487 { 3488 [DW_ACCESS_public] = "public", 3489 [DW_ACCESS_protected] = "protected", 3490 [DW_ACCESS_private] = "private" 3491 }; 3492 3493 if (likely (code < sizeof (known) / sizeof (known[0]))) 3494 return known[code]; 3495 3496 return "???"; 3497} 3498 3499 3500static const char * 3501dwarf_visibility_string (unsigned int code) 3502{ 3503 static const char *const known[] = 3504 { 3505 [DW_VIS_local] = "local", 3506 [DW_VIS_exported] = "exported", 3507 [DW_VIS_qualified] = "qualified" 3508 }; 3509 3510 if (likely (code < sizeof (known) / sizeof (known[0]))) 3511 return known[code]; 3512 3513 return "???"; 3514} 3515 3516 3517static const char * 3518dwarf_virtuality_string (unsigned int code) 3519{ 3520 static const char *const known[] = 3521 { 3522 [DW_VIRTUALITY_none] = "none", 3523 [DW_VIRTUALITY_virtual] = "virtual", 3524 [DW_VIRTUALITY_pure_virtual] = "pure_virtual" 3525 }; 3526 3527 if (likely (code < sizeof (known) / sizeof (known[0]))) 3528 return known[code]; 3529 3530 return "???"; 3531} 3532 3533 3534static const char * 3535dwarf_identifier_case_string (unsigned int code) 3536{ 3537 static const char *const known[] = 3538 { 3539 [DW_ID_case_sensitive] = "sensitive", 3540 [DW_ID_up_case] = "up_case", 3541 [DW_ID_down_case] = "down_case", 3542 [DW_ID_case_insensitive] = "insensitive" 3543 }; 3544 3545 if (likely (code < sizeof (known) / sizeof (known[0]))) 3546 return known[code]; 3547 3548 return "???"; 3549} 3550 3551 3552static const char * 3553dwarf_calling_convention_string (unsigned int code) 3554{ 3555 static const char *const known[] = 3556 { 3557 [DW_CC_normal] = "normal", 3558 [DW_CC_program] = "program", 3559 [DW_CC_nocall] = "nocall", 3560 }; 3561 3562 if (likely (code < sizeof (known) / sizeof (known[0]))) 3563 return known[code]; 3564 3565 if (code >= DW_CC_lo_user && code <= DW_CC_hi_user) 3566 { 3567 static char buf[30]; 3568 snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user); 3569 return buf; 3570 } 3571 3572 return "???"; 3573} 3574 3575 3576static const char * 3577dwarf_ordering_string (unsigned int code) 3578{ 3579 static const char *const known[] = 3580 { 3581 [DW_ORD_row_major] = "row_major", 3582 [DW_ORD_col_major] = "col_major" 3583 }; 3584 3585 if (likely (code < sizeof (known) / sizeof (known[0]))) 3586 return known[code]; 3587 3588 return "???"; 3589} 3590 3591 3592static const char * 3593dwarf_discr_list_string (unsigned int code) 3594{ 3595 static const char *const known[] = 3596 { 3597 [DW_DSC_label] = "label", 3598 [DW_DSC_range] = "range" 3599 }; 3600 3601 if (likely (code < sizeof (known) / sizeof (known[0]))) 3602 return known[code]; 3603 3604 return "???"; 3605} 3606 3607 3608static void 3609print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, 3610 unsigned int addrsize, Dwarf_Word len, const unsigned char *data) 3611{ 3612 static const char *const known[] = 3613 { 3614 [DW_OP_addr] = "addr", 3615 [DW_OP_deref] = "deref", 3616 [DW_OP_const1u] = "const1u", 3617 [DW_OP_const1s] = "const1s", 3618 [DW_OP_const2u] = "const2u", 3619 [DW_OP_const2s] = "const2s", 3620 [DW_OP_const4u] = "const4u", 3621 [DW_OP_const4s] = "const4s", 3622 [DW_OP_const8u] = "const8u", 3623 [DW_OP_const8s] = "const8s", 3624 [DW_OP_constu] = "constu", 3625 [DW_OP_consts] = "consts", 3626 [DW_OP_dup] = "dup", 3627 [DW_OP_drop] = "drop", 3628 [DW_OP_over] = "over", 3629 [DW_OP_pick] = "pick", 3630 [DW_OP_swap] = "swap", 3631 [DW_OP_rot] = "rot", 3632 [DW_OP_xderef] = "xderef", 3633 [DW_OP_abs] = "abs", 3634 [DW_OP_and] = "and", 3635 [DW_OP_div] = "div", 3636 [DW_OP_minus] = "minus", 3637 [DW_OP_mod] = "mod", 3638 [DW_OP_mul] = "mul", 3639 [DW_OP_neg] = "neg", 3640 [DW_OP_not] = "not", 3641 [DW_OP_or] = "or", 3642 [DW_OP_plus] = "plus", 3643 [DW_OP_plus_uconst] = "plus_uconst", 3644 [DW_OP_shl] = "shl", 3645 [DW_OP_shr] = "shr", 3646 [DW_OP_shra] = "shra", 3647 [DW_OP_xor] = "xor", 3648 [DW_OP_bra] = "bra", 3649 [DW_OP_eq] = "eq", 3650 [DW_OP_ge] = "ge", 3651 [DW_OP_gt] = "gt", 3652 [DW_OP_le] = "le", 3653 [DW_OP_lt] = "lt", 3654 [DW_OP_ne] = "ne", 3655 [DW_OP_skip] = "skip", 3656 [DW_OP_lit0] = "lit0", 3657 [DW_OP_lit1] = "lit1", 3658 [DW_OP_lit2] = "lit2", 3659 [DW_OP_lit3] = "lit3", 3660 [DW_OP_lit4] = "lit4", 3661 [DW_OP_lit5] = "lit5", 3662 [DW_OP_lit6] = "lit6", 3663 [DW_OP_lit7] = "lit7", 3664 [DW_OP_lit8] = "lit8", 3665 [DW_OP_lit9] = "lit9", 3666 [DW_OP_lit10] = "lit10", 3667 [DW_OP_lit11] = "lit11", 3668 [DW_OP_lit12] = "lit12", 3669 [DW_OP_lit13] = "lit13", 3670 [DW_OP_lit14] = "lit14", 3671 [DW_OP_lit15] = "lit15", 3672 [DW_OP_lit16] = "lit16", 3673 [DW_OP_lit17] = "lit17", 3674 [DW_OP_lit18] = "lit18", 3675 [DW_OP_lit19] = "lit19", 3676 [DW_OP_lit20] = "lit20", 3677 [DW_OP_lit21] = "lit21", 3678 [DW_OP_lit22] = "lit22", 3679 [DW_OP_lit23] = "lit23", 3680 [DW_OP_lit24] = "lit24", 3681 [DW_OP_lit25] = "lit25", 3682 [DW_OP_lit26] = "lit26", 3683 [DW_OP_lit27] = "lit27", 3684 [DW_OP_lit28] = "lit28", 3685 [DW_OP_lit29] = "lit29", 3686 [DW_OP_lit30] = "lit30", 3687 [DW_OP_lit31] = "lit31", 3688 [DW_OP_reg0] = "reg0", 3689 [DW_OP_reg1] = "reg1", 3690 [DW_OP_reg2] = "reg2", 3691 [DW_OP_reg3] = "reg3", 3692 [DW_OP_reg4] = "reg4", 3693 [DW_OP_reg5] = "reg5", 3694 [DW_OP_reg6] = "reg6", 3695 [DW_OP_reg7] = "reg7", 3696 [DW_OP_reg8] = "reg8", 3697 [DW_OP_reg9] = "reg9", 3698 [DW_OP_reg10] = "reg10", 3699 [DW_OP_reg11] = "reg11", 3700 [DW_OP_reg12] = "reg12", 3701 [DW_OP_reg13] = "reg13", 3702 [DW_OP_reg14] = "reg14", 3703 [DW_OP_reg15] = "reg15", 3704 [DW_OP_reg16] = "reg16", 3705 [DW_OP_reg17] = "reg17", 3706 [DW_OP_reg18] = "reg18", 3707 [DW_OP_reg19] = "reg19", 3708 [DW_OP_reg20] = "reg20", 3709 [DW_OP_reg21] = "reg21", 3710 [DW_OP_reg22] = "reg22", 3711 [DW_OP_reg23] = "reg23", 3712 [DW_OP_reg24] = "reg24", 3713 [DW_OP_reg25] = "reg25", 3714 [DW_OP_reg26] = "reg26", 3715 [DW_OP_reg27] = "reg27", 3716 [DW_OP_reg28] = "reg28", 3717 [DW_OP_reg29] = "reg29", 3718 [DW_OP_reg30] = "reg30", 3719 [DW_OP_reg31] = "reg31", 3720 [DW_OP_breg0] = "breg0", 3721 [DW_OP_breg1] = "breg1", 3722 [DW_OP_breg2] = "breg2", 3723 [DW_OP_breg3] = "breg3", 3724 [DW_OP_breg4] = "breg4", 3725 [DW_OP_breg5] = "breg5", 3726 [DW_OP_breg6] = "breg6", 3727 [DW_OP_breg7] = "breg7", 3728 [DW_OP_breg8] = "breg8", 3729 [DW_OP_breg9] = "breg9", 3730 [DW_OP_breg10] = "breg10", 3731 [DW_OP_breg11] = "breg11", 3732 [DW_OP_breg12] = "breg12", 3733 [DW_OP_breg13] = "breg13", 3734 [DW_OP_breg14] = "breg14", 3735 [DW_OP_breg15] = "breg15", 3736 [DW_OP_breg16] = "breg16", 3737 [DW_OP_breg17] = "breg17", 3738 [DW_OP_breg18] = "breg18", 3739 [DW_OP_breg19] = "breg19", 3740 [DW_OP_breg20] = "breg20", 3741 [DW_OP_breg21] = "breg21", 3742 [DW_OP_breg22] = "breg22", 3743 [DW_OP_breg23] = "breg23", 3744 [DW_OP_breg24] = "breg24", 3745 [DW_OP_breg25] = "breg25", 3746 [DW_OP_breg26] = "breg26", 3747 [DW_OP_breg27] = "breg27", 3748 [DW_OP_breg28] = "breg28", 3749 [DW_OP_breg29] = "breg29", 3750 [DW_OP_breg30] = "breg30", 3751 [DW_OP_breg31] = "breg31", 3752 [DW_OP_regx] = "regx", 3753 [DW_OP_fbreg] = "fbreg", 3754 [DW_OP_bregx] = "bregx", 3755 [DW_OP_piece] = "piece", 3756 [DW_OP_deref_size] = "deref_size", 3757 [DW_OP_xderef_size] = "xderef_size", 3758 [DW_OP_nop] = "nop", 3759 [DW_OP_push_object_address] = "push_object_address", 3760 [DW_OP_call2] = "call2", 3761 [DW_OP_call4] = "call4", 3762 [DW_OP_call_ref] = "call_ref", 3763 [DW_OP_form_tls_address] = "form_tls_address", 3764 [DW_OP_call_frame_cfa] = "call_frame_cfa", 3765 [DW_OP_bit_piece] = "bit_piece", 3766 }; 3767 3768 Dwarf_Word offset = 0; 3769 while (len-- > 0) 3770 { 3771 uint_fast8_t op = *data++; 3772 3773 switch (op) 3774 { 3775 case DW_OP_call_ref: 3776 case DW_OP_addr:; 3777 /* Address operand. */ 3778 Dwarf_Word addr; 3779 if (addrsize == 4) 3780 addr = read_4ubyte_unaligned (dbg, data); 3781 else 3782 { 3783 assert (addrsize == 8); 3784 addr = read_8ubyte_unaligned (dbg, data); 3785 } 3786 data += addrsize; 3787 len -= addrsize; 3788 3789 if (op == DW_OP_addr) 3790 { 3791 char *a = format_dwarf_addr (dwflmod, 0, addr); 3792 printf ("%*s[%4" PRIuMAX "] %s %s\n", 3793 indent, "", (uintmax_t) offset, 3794 known[op] ?: "???", a); 3795 free (a); 3796 } 3797 else 3798 printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n", 3799 indent, "", (uintmax_t) offset, 3800 known[op] ?: "???", (uintmax_t) addr); 3801 offset += 1 + addrsize; 3802 break; 3803 3804 case DW_OP_deref_size: 3805 case DW_OP_xderef_size: 3806 case DW_OP_pick: 3807 case DW_OP_const1u: 3808 printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n", 3809 indent, "", (uintmax_t) offset, 3810 known[op] ?: "???", *((uint8_t *) data)); 3811 ++data; 3812 --len; 3813 offset += 2; 3814 break; 3815 3816 case DW_OP_const2u: 3817 printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n", 3818 indent, "", (uintmax_t) offset, 3819 known[op] ?: "???", read_2ubyte_unaligned (dbg, data)); 3820 len -= 2; 3821 data += 2; 3822 offset += 3; 3823 break; 3824 3825 case DW_OP_const4u: 3826 printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n", 3827 indent, "", (uintmax_t) offset, 3828 known[op] ?: "???", read_4ubyte_unaligned (dbg, data)); 3829 len -= 4; 3830 data += 4; 3831 offset += 5; 3832 break; 3833 3834 case DW_OP_const8u: 3835 printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n", 3836 indent, "", (uintmax_t) offset, 3837 known[op] ?: "???", read_8ubyte_unaligned (dbg, data)); 3838 len -= 8; 3839 data += 8; 3840 offset += 9; 3841 break; 3842 3843 case DW_OP_const1s: 3844 printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n", 3845 indent, "", (uintmax_t) offset, 3846 known[op] ?: "???", *((int8_t *) data)); 3847 ++data; 3848 --len; 3849 offset += 2; 3850 break; 3851 3852 case DW_OP_const2s: 3853 printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n", 3854 indent, "", (uintmax_t) offset, 3855 known[op] ?: "???", read_2sbyte_unaligned (dbg, data)); 3856 len -= 2; 3857 data += 2; 3858 offset += 3; 3859 break; 3860 3861 case DW_OP_const4s: 3862 printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n", 3863 indent, "", (uintmax_t) offset, 3864 known[op] ?: "???", read_4sbyte_unaligned (dbg, data)); 3865 len -= 4; 3866 data += 4; 3867 offset += 5; 3868 break; 3869 3870 case DW_OP_const8s: 3871 printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n", 3872 indent, "", (uintmax_t) offset, 3873 known[op] ?: "???", read_8sbyte_unaligned (dbg, data)); 3874 len -= 8; 3875 data += 8; 3876 offset += 9; 3877 break; 3878 3879 case DW_OP_piece: 3880 case DW_OP_regx: 3881 case DW_OP_plus_uconst: 3882 case DW_OP_constu:; 3883 const unsigned char *start = data; 3884 unsigned int uleb; 3885 get_uleb128 (uleb, data); 3886 printf ("%*s[%4" PRIuMAX "] %s %u\n", 3887 indent, "", (uintmax_t) offset, 3888 known[op] ?: "???", uleb); 3889 len -= data - start; 3890 offset += 1 + (data - start); 3891 break; 3892 3893 case DW_OP_bit_piece: 3894 start = data; 3895 unsigned int uleb2; 3896 get_uleb128 (uleb, data); 3897 get_uleb128 (uleb2, data); 3898 printf ("%*s[%4" PRIuMAX "] %s %u, %u\n", 3899 indent, "", (uintmax_t) offset, 3900 known[op] ?: "???", uleb, uleb2); 3901 len -= data - start; 3902 offset += 1 + (data - start); 3903 break; 3904 3905 case DW_OP_fbreg: 3906 case DW_OP_breg0 ... DW_OP_breg31: 3907 case DW_OP_consts: 3908 start = data; 3909 unsigned int sleb; 3910 get_sleb128 (sleb, data); 3911 printf ("%*s[%4" PRIuMAX "] %s %d\n", 3912 indent, "", (uintmax_t) offset, 3913 known[op] ?: "???", sleb); 3914 len -= data - start; 3915 offset += 1 + (data - start); 3916 break; 3917 3918 case DW_OP_bregx: 3919 start = data; 3920 get_uleb128 (uleb, data); 3921 get_sleb128 (sleb, data); 3922 printf ("%*s[%4" PRIuMAX "] %s %u %d\n", 3923 indent, "", (uintmax_t) offset, 3924 known[op] ?: "???", uleb, sleb); 3925 len -= data - start; 3926 offset += 1 + (data - start); 3927 break; 3928 3929 case DW_OP_call2: 3930 case DW_OP_call4: 3931 case DW_OP_skip: 3932 case DW_OP_bra: 3933 printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n", 3934 indent, "", (uintmax_t) offset, 3935 known[op] ?: "???", 3936 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data))); 3937 len -= 2; 3938 data += 2; 3939 offset += 3; 3940 break; 3941 3942 default: 3943 /* No Operand. */ 3944 if (op < sizeof known / sizeof known[0] && known[op] != NULL) 3945 printf ("%*s[%4" PRIuMAX "] %s\n", 3946 indent, "", (uintmax_t) offset, known[op]); 3947 else 3948 printf ("%*s[%4" PRIuMAX "] %#x\n", 3949 indent, "", (uintmax_t) offset, op); 3950 ++offset; 3951 break; 3952 } 3953 3954 indent = indentrest; 3955 } 3956} 3957 3958 3959static void 3960print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), 3961 Ebl *ebl __attribute__ ((unused)), 3962 GElf_Ehdr *ehdr __attribute__ ((unused)), 3963 Elf_Scn *scn __attribute__ ((unused)), 3964 GElf_Shdr *shdr, Dwarf *dbg) 3965{ 3966 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n" 3967 " [ Code]\n"), 3968 ".debug_abbrev", (uint64_t) shdr->sh_offset); 3969 3970 Dwarf_Off offset = 0; 3971 while (offset < shdr->sh_size) 3972 { 3973 printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"), 3974 offset); 3975 3976 while (1) 3977 { 3978 size_t length; 3979 Dwarf_Abbrev abbrev; 3980 3981 int res = dwarf_offabbrev (dbg, offset, &length, &abbrev); 3982 if (res != 0) 3983 { 3984 if (unlikely (res < 0)) 3985 { 3986 printf (gettext ("\ 3987 *** error while reading abbreviation: %s\n"), 3988 dwarf_errmsg (-1)); 3989 return; 3990 } 3991 3992 /* This is the NUL byte at the end of the section. */ 3993 ++offset; 3994 break; 3995 } 3996 3997 /* We know these calls can never fail. */ 3998 unsigned int code = dwarf_getabbrevcode (&abbrev); 3999 unsigned int tag = dwarf_getabbrevtag (&abbrev); 4000 int has_children = dwarf_abbrevhaschildren (&abbrev); 4001 4002 printf (gettext (" [%5u] offset: %" PRId64 4003 ", children: %s, tag: %s\n"), 4004 code, (int64_t) offset, 4005 has_children ? gettext ("yes") : gettext ("no"), 4006 dwarf_tag_string (tag)); 4007 4008 size_t cnt = 0; 4009 unsigned int name; 4010 unsigned int form; 4011 Dwarf_Off enoffset; 4012 while (dwarf_getabbrevattr (&abbrev, cnt, 4013 &name, &form, &enoffset) == 0) 4014 { 4015 printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n", 4016 dwarf_attr_string (name), dwarf_form_string (form), 4017 (uint64_t) enoffset); 4018 4019 ++cnt; 4020 } 4021 4022 offset += length; 4023 } 4024 } 4025} 4026 4027 4028/* Print content of DWARF .debug_aranges section. We fortunately do 4029 not have to know a bit about the structure of the section, libdwarf 4030 takes care of it. */ 4031static void 4032print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), 4033 Ebl *ebl __attribute__ ((unused)), 4034 GElf_Ehdr *ehdr __attribute__ ((unused)), 4035 Elf_Scn *scn __attribute__ ((unused)), 4036 GElf_Shdr *shdr, Dwarf *dbg) 4037{ 4038 Dwarf_Aranges *aranges; 4039 size_t cnt; 4040 if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0)) 4041 { 4042 error (0, 0, gettext ("cannot get .debug_aranges content: %s"), 4043 dwarf_errmsg (-1)); 4044 return; 4045 } 4046 4047 printf (ngettext ("\ 4048\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n", 4049 "\ 4050\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n", 4051 cnt), 4052 ".debug_aranges", (uint64_t) shdr->sh_offset, cnt); 4053 4054 /* Compute floor(log16(cnt)). */ 4055 size_t tmp = cnt; 4056 int digits = 1; 4057 while (tmp >= 16) 4058 { 4059 ++digits; 4060 tmp >>= 4; 4061 } 4062 4063 for (size_t n = 0; n < cnt; ++n) 4064 { 4065 Dwarf_Arange *runp = dwarf_onearange (aranges, n); 4066 if (unlikely (runp == NULL)) 4067 { 4068 printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1)); 4069 return; 4070 } 4071 4072 Dwarf_Addr start; 4073 Dwarf_Word length; 4074 Dwarf_Off offset; 4075 4076 if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0)) 4077 printf (gettext (" [%*zu] ???\n"), digits, n); 4078 else 4079 printf (gettext (" [%*zu] start: %0#*" PRIx64 4080 ", length: %5" PRIu64 ", CU DIE offset: %6" 4081 PRId64 "\n"), 4082 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18, 4083 (uint64_t) start, (uint64_t) length, (int64_t) offset); 4084 } 4085} 4086 4087/* Print content of DWARF .debug_ranges section. */ 4088static void 4089print_debug_ranges_section (Dwfl_Module *dwflmod, 4090 Ebl *ebl __attribute__ ((unused)), 4091 GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, 4092 Dwarf *dbg) 4093{ 4094 Elf_Data *data = elf_rawdata (scn, NULL); 4095 4096 if (unlikely (data == NULL)) 4097 { 4098 error (0, 0, gettext ("cannot get .debug_ranges content: %s"), 4099 elf_errmsg (-1)); 4100 return; 4101 } 4102 4103 printf (gettext ("\ 4104\nDWARF section '%s' at offset %#" PRIx64 ":\n"), 4105 ".debug_ranges", (uint64_t) shdr->sh_offset); 4106 4107 size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 4108 4109 bool first = true; 4110 unsigned char *readp = data->d_buf; 4111 while (readp < (unsigned char *) data->d_buf + data->d_size) 4112 { 4113 ptrdiff_t offset = readp - (unsigned char *) data->d_buf; 4114 4115 if (unlikely (data->d_size - offset < address_size * 2)) 4116 { 4117 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset); 4118 break; 4119 } 4120 4121 Dwarf_Addr begin; 4122 Dwarf_Addr end; 4123 if (address_size == 8) 4124 { 4125 begin = read_8ubyte_unaligned_inc (dbg, readp); 4126 end = read_8ubyte_unaligned_inc (dbg, readp); 4127 } 4128 else 4129 { 4130 begin = read_4ubyte_unaligned_inc (dbg, readp); 4131 end = read_4ubyte_unaligned_inc (dbg, readp); 4132 if (begin == (Dwarf_Addr) (uint32_t) -1) 4133 begin = (Dwarf_Addr) -1l; 4134 } 4135 4136 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */ 4137 { 4138 char *b = format_dwarf_addr (dwflmod, address_size, end); 4139 printf (gettext (" [%6tx] base address %s\n"), offset, b); 4140 free (b); 4141 } 4142 else if (begin == 0 && end == 0) /* End of list entry. */ 4143 first = true; 4144 else 4145 { 4146 char *b = format_dwarf_addr (dwflmod, address_size, begin); 4147 char *e = format_dwarf_addr (dwflmod, address_size, end); 4148 /* We have an address range entry. */ 4149 if (first) /* First address range entry in a list. */ 4150 printf (gettext (" [%6tx] %s..%s\n"), offset, b, e); 4151 else 4152 printf (gettext (" %s..%s\n"), b, e); 4153 free (b); 4154 free (e); 4155 4156 first = false; 4157 } 4158 } 4159} 4160 4161 4162static void 4163print_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)), 4164 Ebl *ebl __attribute__ ((unused)), 4165 GElf_Ehdr *ehdr __attribute__ ((unused)), 4166 Elf_Scn *scn __attribute__ ((unused)), 4167 GElf_Shdr *shdr __attribute__ ((unused)), 4168 Dwarf *dbg __attribute__ ((unused))) 4169{ 4170} 4171 4172 4173struct attrcb_args 4174{ 4175 Dwfl_Module *dwflmod; 4176 Dwarf *dbg; 4177 int level; 4178 unsigned int addrsize; 4179 Dwarf_Off cu_offset; 4180}; 4181 4182 4183static int 4184attr_callback (Dwarf_Attribute *attrp, void *arg) 4185{ 4186 struct attrcb_args *cbargs = (struct attrcb_args *) arg; 4187 const int level = cbargs->level; 4188 4189 unsigned int attr = dwarf_whatattr (attrp); 4190 if (unlikely (attr == 0)) 4191 { 4192 error (0, 0, gettext ("cannot get attribute code: %s"), 4193 dwarf_errmsg (-1)); 4194 return DWARF_CB_ABORT; 4195 } 4196 4197 unsigned int form = dwarf_whatform (attrp); 4198 if (unlikely (form == 0)) 4199 { 4200 error (0, 0, gettext ("cannot get attribute form: %s"), 4201 dwarf_errmsg (-1)); 4202 return DWARF_CB_ABORT; 4203 } 4204 4205 switch (form) 4206 { 4207 case DW_FORM_addr: 4208 { 4209 Dwarf_Addr addr; 4210 if (unlikely (dwarf_formaddr (attrp, &addr) != 0)) 4211 { 4212 attrval_out: 4213 error (0, 0, gettext ("cannot get attribute value: %s"), 4214 dwarf_errmsg (-1)); 4215 return DWARF_CB_ABORT; 4216 } 4217 char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr); 4218 printf (" %*s%-20s %s\n", 4219 (int) (level * 2), "", dwarf_attr_string (attr), a); 4220 free (a); 4221 } 4222 break; 4223 4224 case DW_FORM_indirect: 4225 case DW_FORM_strp: 4226 case DW_FORM_string:; 4227 const char *str = dwarf_formstring (attrp); 4228 if (unlikely (str == NULL)) 4229 goto attrval_out; 4230 printf (" %*s%-20s \"%s\"\n", 4231 (int) (level * 2), "", dwarf_attr_string (attr), str); 4232 break; 4233 4234 case DW_FORM_ref_addr: 4235 case DW_FORM_ref_udata: 4236 case DW_FORM_ref8: 4237 case DW_FORM_ref4: 4238 case DW_FORM_ref2: 4239 case DW_FORM_ref1:; 4240 Dwarf_Die ref; 4241 if (unlikely (dwarf_formref_die (attrp, &ref) == NULL)) 4242 goto attrval_out; 4243 4244 printf (" %*s%-20s [%6" PRIxMAX "]\n", 4245 (int) (level * 2), "", dwarf_attr_string (attr), 4246 (uintmax_t) dwarf_dieoffset (&ref)); 4247 break; 4248 4249 case DW_FORM_udata: 4250 case DW_FORM_sdata: 4251 case DW_FORM_data8: 4252 case DW_FORM_data4: 4253 case DW_FORM_data2: 4254 case DW_FORM_data1:; 4255 Dwarf_Word num; 4256 if (unlikely (dwarf_formudata (attrp, &num) != 0)) 4257 goto attrval_out; 4258 4259 const char *valuestr = NULL; 4260 switch (attr) 4261 { 4262 case DW_AT_location: 4263 case DW_AT_data_location: 4264 case DW_AT_data_member_location: 4265 case DW_AT_vtable_elem_location: 4266 case DW_AT_string_length: 4267 case DW_AT_use_location: 4268 case DW_AT_frame_base: 4269 case DW_AT_return_addr: 4270 case DW_AT_static_link: 4271 printf (" %*s%-20s location list [%6" PRIxMAX "]\n", 4272 (int) (level * 2), "", dwarf_attr_string (attr), 4273 (uintmax_t) num); 4274 return DWARF_CB_OK; 4275 4276 case DW_AT_ranges: 4277 printf (" %*s%-20s range list [%6" PRIxMAX "]\n", 4278 (int) (level * 2), "", dwarf_attr_string (attr), 4279 (uintmax_t) num); 4280 return DWARF_CB_OK; 4281 4282 case DW_AT_language: 4283 valuestr = dwarf_lang_string (num); 4284 break; 4285 case DW_AT_encoding: 4286 valuestr = dwarf_encoding_string (num); 4287 break; 4288 case DW_AT_accessibility: 4289 valuestr = dwarf_access_string (num); 4290 break; 4291 case DW_AT_visibility: 4292 valuestr = dwarf_visibility_string (num); 4293 break; 4294 case DW_AT_virtuality: 4295 valuestr = dwarf_virtuality_string (num); 4296 break; 4297 case DW_AT_identifier_case: 4298 valuestr = dwarf_identifier_case_string (num); 4299 break; 4300 case DW_AT_calling_convention: 4301 valuestr = dwarf_calling_convention_string (num); 4302 break; 4303 case DW_AT_inline: 4304 valuestr = dwarf_inline_string (num); 4305 break; 4306 case DW_AT_ordering: 4307 valuestr = dwarf_ordering_string (num); 4308 break; 4309 case DW_AT_discr_list: 4310 valuestr = dwarf_discr_list_string (num); 4311 break; 4312 default: 4313 /* Nothing. */ 4314 break; 4315 } 4316 4317 if (valuestr == NULL) 4318 printf (" %*s%-20s %" PRIuMAX "\n", 4319 (int) (level * 2), "", dwarf_attr_string (attr), 4320 (uintmax_t) num); 4321 else 4322 printf (" %*s%-20s %s (%" PRIuMAX ")\n", 4323 (int) (level * 2), "", dwarf_attr_string (attr), 4324 valuestr, (uintmax_t) num); 4325 break; 4326 4327 case DW_FORM_flag:; 4328 bool flag; 4329 if (unlikely (dwarf_formflag (attrp, &flag) != 0)) 4330 goto attrval_out; 4331 4332 printf (" %*s%-20s %s\n", 4333 (int) (level * 2), "", dwarf_attr_string (attr), 4334 nl_langinfo (flag ? YESSTR : NOSTR)); 4335 break; 4336 4337 case DW_FORM_block4: 4338 case DW_FORM_block2: 4339 case DW_FORM_block1: 4340 case DW_FORM_block:; 4341 Dwarf_Block block; 4342 if (unlikely (dwarf_formblock (attrp, &block) != 0)) 4343 goto attrval_out; 4344 4345 printf (" %*s%-20s %" PRIxMAX " byte block\n", 4346 (int) (level * 2), "", dwarf_attr_string (attr), 4347 (uintmax_t) block.length); 4348 4349 switch (attr) 4350 { 4351 case DW_AT_location: 4352 case DW_AT_data_location: 4353 case DW_AT_data_member_location: 4354 case DW_AT_vtable_elem_location: 4355 case DW_AT_string_length: 4356 case DW_AT_use_location: 4357 case DW_AT_frame_base: 4358 case DW_AT_return_addr: 4359 case DW_AT_static_link: 4360 case DW_AT_allocated: 4361 case DW_AT_associated: 4362 case DW_AT_bit_size: 4363 case DW_AT_bit_offset: 4364 case DW_AT_bit_stride: 4365 case DW_AT_byte_size: 4366 case DW_AT_byte_stride: 4367 case DW_AT_count: 4368 case DW_AT_lower_bound: 4369 case DW_AT_upper_bound: 4370 print_ops (cbargs->dwflmod, cbargs->dbg, 4371 12 + level * 2, 12 + level * 2, 4372 cbargs->addrsize, block.length, block.data); 4373 break; 4374 } 4375 break; 4376 4377 default: 4378 printf (" %*s%-20s [form: %d] ???\n", 4379 (int) (level * 2), "", dwarf_attr_string (attr), 4380 (int) form); 4381 break; 4382 } 4383 4384 return DWARF_CB_OK; 4385} 4386 4387 4388static void 4389print_debug_info_section (Dwfl_Module *dwflmod, 4390 Ebl *ebl __attribute__ ((unused)), 4391 GElf_Ehdr *ehdr __attribute__ ((unused)), 4392 Elf_Scn *scn __attribute__ ((unused)), 4393 GElf_Shdr *shdr, Dwarf *dbg) 4394{ 4395 printf (gettext ("\ 4396\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"), 4397 ".debug_info", (uint64_t) shdr->sh_offset); 4398 4399 /* If the section is empty we don't have to do anything. */ 4400 if (shdr->sh_size == 0) 4401 return; 4402 4403 int maxdies = 20; 4404 Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die)); 4405 4406 Dwarf_Off offset = 0; 4407 4408 /* New compilation unit. */ 4409 size_t cuhl; 4410 //Dwarf_Half version; 4411 Dwarf_Off abbroffset; 4412 uint8_t addrsize; 4413 uint8_t offsize; 4414 Dwarf_Off nextcu; 4415 next_cu: 4416 if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize, 4417 &offsize) != 0) 4418 goto do_return; 4419 4420 printf (gettext (" Compilation unit at offset %" PRIu64 ":\n" 4421 " Version: %" PRIu16 ", Abbreviation section offset: %" 4422 PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"), 4423 (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize); 4424 4425 4426 struct attrcb_args args; 4427 args.dwflmod = dwflmod; 4428 args.dbg = dbg; 4429 args.addrsize = addrsize; 4430 args.cu_offset = offset; 4431 4432 offset += cuhl; 4433 4434 int level = 0; 4435 4436 if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL)) 4437 { 4438 error (0, 0, gettext ("cannot get DIE at offset %" PRIu64 4439 " in section '%s': %s"), 4440 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1)); 4441 goto do_return; 4442 } 4443 4444 do 4445 { 4446 offset = dwarf_dieoffset (&dies[level]); 4447 if (unlikely (offset == ~0ul)) 4448 { 4449 error (0, 0, gettext ("cannot get DIE offset: %s"), 4450 dwarf_errmsg (-1)); 4451 goto do_return; 4452 } 4453 4454 int tag = dwarf_tag (&dies[level]); 4455 if (unlikely (tag == DW_TAG_invalid)) 4456 { 4457 error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64 4458 " in section '%s': %s"), 4459 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1)); 4460 goto do_return; 4461 } 4462 4463 printf (" [%6" PRIx64 "] %*s%s\n", 4464 (uint64_t) offset, (int) (level * 2), "", 4465 dwarf_tag_string (tag)); 4466 4467 /* Print the attribute values. */ 4468 args.level = level; 4469 (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0); 4470 4471 /* Make room for the next level's DIE. */ 4472 if (level + 1 == maxdies) 4473 dies = (Dwarf_Die *) xrealloc (dies, 4474 (maxdies += 10) 4475 * sizeof (Dwarf_Die)); 4476 4477 int res = dwarf_child (&dies[level], &dies[level + 1]); 4478 if (res > 0) 4479 { 4480 while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1) 4481 if (level-- == 0) 4482 break; 4483 4484 if (unlikely (res == -1)) 4485 { 4486 error (0, 0, gettext ("cannot get next DIE: %s\n"), 4487 dwarf_errmsg (-1)); 4488 goto do_return; 4489 } 4490 } 4491 else if (unlikely (res < 0)) 4492 { 4493 error (0, 0, gettext ("cannot get next DIE: %s"), 4494 dwarf_errmsg (-1)); 4495 goto do_return; 4496 } 4497 else 4498 ++level; 4499 } 4500 while (level >= 0); 4501 4502 offset = nextcu; 4503 if (offset != 0) 4504 goto next_cu; 4505 4506 do_return: 4507 free (dies); 4508} 4509 4510 4511static void 4512print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, 4513 GElf_Ehdr *ehdr __attribute__ ((unused)), 4514 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) 4515{ 4516 printf (gettext ("\ 4517\nDWARF section '%s' at offset %#" PRIx64 ":\n"), 4518 ".debug_line", (uint64_t) shdr->sh_offset); 4519 4520 if (shdr->sh_size == 0) 4521 return; 4522 4523 /* There is no functionality in libdw to read the information in the 4524 way it is represented here. Hardcode the decoder. */ 4525 Elf_Data *data = elf_getdata (scn, NULL); 4526 if (unlikely (data == NULL || data->d_buf == NULL)) 4527 { 4528 error (0, 0, gettext ("cannot get line data section data: %s"), 4529 elf_errmsg (-1)); 4530 return; 4531 } 4532 4533 const unsigned char *linep = (const unsigned char *) data->d_buf; 4534 const unsigned char *lineendp; 4535 4536 while (linep 4537 < (lineendp = (const unsigned char *) data->d_buf + data->d_size)) 4538 { 4539 size_t start_offset = linep - (const unsigned char *) data->d_buf; 4540 4541 printf (gettext ("\nTable at offset %Zu:\n"), start_offset); 4542 4543 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); 4544 unsigned int length = 4; 4545 if (unlikely (unit_length == 0xffffffff)) 4546 { 4547 if (unlikely (linep + 8 > lineendp)) 4548 { 4549 invalid_data: 4550 error (0, 0, gettext ("invalid data in section [%zu] '%s'"), 4551 elf_ndxscn (scn), ".debug_line"); 4552 return; 4553 } 4554 unit_length = read_8ubyte_unaligned_inc (dbg, linep); 4555 length = 8; 4556 } 4557 4558 /* Check whether we have enough room in the section. */ 4559 if (unit_length < 2 + length + 5 * 1 4560 || unlikely (linep + unit_length > lineendp)) 4561 goto invalid_data; 4562 lineendp = linep + unit_length; 4563 4564 /* The next element of the header is the version identifier. */ 4565 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); 4566 4567 /* Next comes the header length. */ 4568 Dwarf_Word header_length; 4569 if (length == 4) 4570 header_length = read_4ubyte_unaligned_inc (dbg, linep); 4571 else 4572 header_length = read_8ubyte_unaligned_inc (dbg, linep); 4573 //const unsigned char *header_start = linep; 4574 4575 /* Next the minimum instruction length. */ 4576 uint_fast8_t minimum_instr_len = *linep++; 4577 4578 /* Then the flag determining the default value of the is_stmt 4579 register. */ 4580 uint_fast8_t default_is_stmt = *linep++; 4581 4582 /* Now the line base. */ 4583 int_fast8_t line_base = *((const int_fast8_t *) linep); 4584 ++linep; 4585 4586 /* And the line range. */ 4587 uint_fast8_t line_range = *linep++; 4588 4589 /* The opcode base. */ 4590 uint_fast8_t opcode_base = *linep++; 4591 4592 /* Print what we got so far. */ 4593 printf (gettext ("\n" 4594 " Length: %" PRIu64 "\n" 4595 " DWARF version: %" PRIuFAST16 "\n" 4596 " Prologue length: %" PRIu64 "\n" 4597 " Minimum instruction length: %" PRIuFAST8 "\n" 4598 " Initial value if '%s': %" PRIuFAST8 "\n" 4599 " Line base: %" PRIdFAST8 "\n" 4600 " Line range: %" PRIuFAST8 "\n" 4601 " Opcode base: %" PRIuFAST8 "\n" 4602 "\n" 4603 "Opcodes:\n"), 4604 (uint64_t) unit_length, version, (uint64_t) header_length, 4605 minimum_instr_len, "is_stmt", default_is_stmt, line_base, 4606 line_range, opcode_base); 4607 4608 if (unlikely (linep + opcode_base - 1 >= lineendp)) 4609 { 4610 invalid_unit: 4611 error (0, 0, 4612 gettext ("invalid data at offset %tu in section [%zu] '%s'"), 4613 linep - (const unsigned char *) data->d_buf, 4614 elf_ndxscn (scn), ".debug_line"); 4615 linep = lineendp; 4616 continue; 4617 } 4618 int opcode_base_l10 = 1; 4619 unsigned int tmp = opcode_base; 4620 while (tmp > 10) 4621 { 4622 tmp /= 10; 4623 ++opcode_base_l10; 4624 } 4625 const uint8_t *standard_opcode_lengths = linep - 1; 4626 for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt) 4627 printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n", 4628 " [%*" PRIuFAST8 "] %hhu arguments\n", 4629 (int) linep[cnt - 1]), 4630 opcode_base_l10, cnt, linep[cnt - 1]); 4631 linep += opcode_base - 1; 4632 if (unlikely (linep >= lineendp)) 4633 goto invalid_unit; 4634 4635 puts (gettext ("\nDirectory table:")); 4636 while (*linep != 0) 4637 { 4638 unsigned char *endp = memchr (linep, '\0', lineendp - linep); 4639 if (unlikely (endp == NULL)) 4640 goto invalid_unit; 4641 4642 printf (" %s\n", (char *) linep); 4643 4644 linep = endp + 1; 4645 } 4646 /* Skip the final NUL byte. */ 4647 ++linep; 4648 4649 if (unlikely (linep >= lineendp)) 4650 goto invalid_unit; 4651 puts (gettext ("\nFile name table:\n" 4652 " Entry Dir Time Size Name")); 4653 for (unsigned int cnt = 1; *linep != 0; ++cnt) 4654 { 4655 /* First comes the file name. */ 4656 char *fname = (char *) linep; 4657 unsigned char *endp = memchr (fname, '\0', lineendp - linep); 4658 if (unlikely (endp == NULL)) 4659 goto invalid_unit; 4660 linep = endp + 1; 4661 4662 /* Then the index. */ 4663 unsigned int diridx; 4664 get_uleb128 (diridx, linep); 4665 4666 /* Next comes the modification time. */ 4667 unsigned int mtime; 4668 get_uleb128 (mtime, linep); 4669 4670 /* Finally the length of the file. */ 4671 unsigned int fsize; 4672 get_uleb128 (fsize, linep); 4673 4674 printf (" %-5u %-5u %-9u %-9u %s\n", 4675 cnt, diridx, mtime, fsize, fname); 4676 } 4677 /* Skip the final NUL byte. */ 4678 ++linep; 4679 4680 puts (gettext ("\nLine number statements:")); 4681 Dwarf_Word address = 0; 4682 size_t line = 1; 4683 uint_fast8_t is_stmt = default_is_stmt; 4684 4685 /* Default address value, in case we do not find the CU. */ 4686 size_t address_size 4687 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8; 4688 4689 /* Determine the CU this block is for. */ 4690 Dwarf_Off cuoffset; 4691 Dwarf_Off ncuoffset = 0; 4692 size_t hsize; 4693 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize, 4694 NULL, NULL, NULL) == 0) 4695 { 4696 Dwarf_Die cudie; 4697 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL) 4698 continue; 4699 Dwarf_Attribute stmt_list; 4700 if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL) 4701 continue; 4702 Dwarf_Word lineoff; 4703 if (dwarf_formudata (&stmt_list, &lineoff) != 0) 4704 continue; 4705 if (lineoff == start_offset) 4706 { 4707 /* Found the CU. */ 4708 address_size = cudie.cu->address_size; 4709 break; 4710 } 4711 } 4712 4713 while (linep < lineendp) 4714 { 4715 unsigned int u128; 4716 int s128; 4717 4718 /* Read the opcode. */ 4719 unsigned int opcode = *linep++; 4720 4721 /* Is this a special opcode? */ 4722 if (likely (opcode >= opcode_base)) 4723 { 4724 /* Yes. Handling this is quite easy since the opcode value 4725 is computed with 4726 4727 opcode = (desired line increment - line_base) 4728 + (line_range * address advance) + opcode_base 4729 */ 4730 int line_increment = (line_base 4731 + (opcode - opcode_base) % line_range); 4732 unsigned int address_increment = (minimum_instr_len 4733 * ((opcode - opcode_base) 4734 / line_range)); 4735 4736 /* Perform the increments. */ 4737 line += line_increment; 4738 address += address_increment; 4739 4740 char *a = format_dwarf_addr (dwflmod, 0, address); 4741 printf (gettext ("\ 4742 special opcode %u: address+%u = %s, line%+d = %zu\n"), 4743 opcode, address_increment, a, line_increment, line); 4744 free (a); 4745 } 4746 else if (opcode == 0) 4747 { 4748 /* This an extended opcode. */ 4749 if (unlikely (linep + 2 > lineendp)) 4750 goto invalid_unit; 4751 4752 /* The length. */ 4753 unsigned int len = *linep++; 4754 4755 if (unlikely (linep + len > lineendp)) 4756 goto invalid_unit; 4757 4758 /* The sub-opcode. */ 4759 opcode = *linep++; 4760 4761 printf (gettext (" extended opcode %u: "), opcode); 4762 4763 switch (opcode) 4764 { 4765 case DW_LNE_end_sequence: 4766 puts (gettext ("end of sequence")); 4767 4768 /* Reset the registers we care about. */ 4769 address = 0; 4770 line = 1; 4771 is_stmt = default_is_stmt; 4772 break; 4773 4774 case DW_LNE_set_address: 4775 if (address_size == 4) 4776 address = read_4ubyte_unaligned_inc (dbg, linep); 4777 else 4778 address = read_8ubyte_unaligned_inc (dbg, linep); 4779 { 4780 char *a = format_dwarf_addr (dwflmod, 0, address); 4781 printf (gettext ("set address to %s\n"), a); 4782 free (a); 4783 } 4784 break; 4785 4786 case DW_LNE_define_file: 4787 { 4788 char *fname = (char *) linep; 4789 unsigned char *endp = memchr (linep, '\0', 4790 lineendp - linep); 4791 if (unlikely (endp == NULL)) 4792 goto invalid_unit; 4793 linep = endp + 1; 4794 4795 unsigned int diridx; 4796 get_uleb128 (diridx, linep); 4797 Dwarf_Word mtime; 4798 get_uleb128 (mtime, linep); 4799 Dwarf_Word filelength; 4800 get_uleb128 (filelength, linep); 4801 4802 printf (gettext ("\ 4803define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"), 4804 diridx, (uint64_t) mtime, (uint64_t) filelength, 4805 fname); 4806 } 4807 break; 4808 4809 default: 4810 /* Unknown, ignore it. */ 4811 puts (gettext ("unknown opcode")); 4812 linep += len - 1; 4813 break; 4814 } 4815 } 4816 else if (opcode <= DW_LNS_set_epilogue_begin) 4817 { 4818 /* This is a known standard opcode. */ 4819 switch (opcode) 4820 { 4821 case DW_LNS_copy: 4822 /* Takes no argument. */ 4823 puts (gettext (" copy")); 4824 break; 4825 4826 case DW_LNS_advance_pc: 4827 /* Takes one uleb128 parameter which is added to the 4828 address. */ 4829 get_uleb128 (u128, linep); 4830 address += minimum_instr_len * u128; 4831 { 4832 char *a = format_dwarf_addr (dwflmod, 0, address); 4833 printf (gettext ("advance address by %u to %s\n"), 4834 u128, a); 4835 free (a); 4836 } 4837 break; 4838 4839 case DW_LNS_advance_line: 4840 /* Takes one sleb128 parameter which is added to the 4841 line. */ 4842 get_sleb128 (s128, linep); 4843 line += s128; 4844 printf (gettext ("\ 4845 advance line by constant %d to %" PRId64 "\n"), 4846 s128, (int64_t) line); 4847 break; 4848 4849 case DW_LNS_set_file: 4850 /* Takes one uleb128 parameter which is stored in file. */ 4851 get_uleb128 (u128, linep); 4852 printf (gettext (" set file to %" PRIu64 "\n"), 4853 (uint64_t) u128); 4854 break; 4855 4856 case DW_LNS_set_column: 4857 /* Takes one uleb128 parameter which is stored in column. */ 4858 if (unlikely (standard_opcode_lengths[opcode] != 1)) 4859 goto invalid_unit; 4860 4861 get_uleb128 (u128, linep); 4862 printf (gettext (" set column to %" PRIu64 "\n"), 4863 (uint64_t) u128); 4864 break; 4865 4866 case DW_LNS_negate_stmt: 4867 /* Takes no argument. */ 4868 is_stmt = 1 - is_stmt; 4869 printf (gettext (" set '%s' to %" PRIuFAST8 "\n"), 4870 "is_stmt", is_stmt); 4871 break; 4872 4873 case DW_LNS_set_basic_block: 4874 /* Takes no argument. */ 4875 puts (gettext (" set basic block flag")); 4876 break; 4877 4878 case DW_LNS_const_add_pc: 4879 /* Takes no argument. */ 4880 u128 = (minimum_instr_len 4881 * ((255 - opcode_base) / line_range)); 4882 address += u128; 4883 { 4884 char *a = format_dwarf_addr (dwflmod, 0, address); 4885 printf (gettext ("advance address by constant %u to %s\n"), 4886 u128, a); 4887 free (a); 4888 } 4889 break; 4890 4891 case DW_LNS_fixed_advance_pc: 4892 /* Takes one 16 bit parameter which is added to the 4893 address. */ 4894 if (unlikely (standard_opcode_lengths[opcode] != 1)) 4895 goto invalid_unit; 4896 4897 u128 = read_2ubyte_unaligned_inc (dbg, linep); 4898 address += u128; 4899 { 4900 char *a = format_dwarf_addr (dwflmod, 0, address); 4901 printf (gettext ("\ 4902advance address by fixed value %u to %s\n"), 4903 u128, a); 4904 free (a); 4905 } 4906 break; 4907 4908 case DW_LNS_set_prologue_end: 4909 /* Takes no argument. */ 4910 puts (gettext (" set prologue end flag")); 4911 break; 4912 4913 case DW_LNS_set_epilogue_begin: 4914 /* Takes no argument. */ 4915 puts (gettext (" set epilogue begin flag")); 4916 break; 4917 } 4918 } 4919 else 4920 { 4921 /* This is a new opcode the generator but not we know about. 4922 Read the parameters associated with it but then discard 4923 everything. Read all the parameters for this opcode. */ 4924 printf (ngettext (" unknown opcode with %" PRIu8 " parameter:", 4925 " unknown opcode with %" PRIu8 " parameters:", 4926 standard_opcode_lengths[opcode]), 4927 standard_opcode_lengths[opcode]); 4928 for (int n = standard_opcode_lengths[opcode]; n > 0; --n) 4929 { 4930 get_uleb128 (u128, linep); 4931 if (n != standard_opcode_lengths[opcode]) 4932 putc_unlocked (',', stdout); 4933 printf (" %u", u128); 4934 } 4935 4936 /* Next round, ignore this opcode. */ 4937 continue; 4938 } 4939 } 4940 } 4941 4942 /* There must only be one data block. */ 4943 assert (elf_getdata (scn, data) == NULL); 4944} 4945 4946 4947static void 4948print_debug_loc_section (Dwfl_Module *dwflmod, 4949 Ebl *ebl __attribute__ ((unused)), 4950 GElf_Ehdr *ehdr __attribute__ ((unused)), 4951 Elf_Scn *scn __attribute__ ((unused)), 4952 GElf_Shdr *shdr, 4953 Dwarf *dbg __attribute__ ((unused))) 4954{ 4955 Elf_Data *data = elf_rawdata (scn, NULL); 4956 4957 if (unlikely (data == NULL)) 4958 { 4959 error (0, 0, gettext ("cannot get .debug_loc content: %s"), 4960 elf_errmsg (-1)); 4961 return; 4962 } 4963 4964 printf (gettext ("\ 4965\nDWARF section '%s' at offset %#" PRIx64 ":\n"), 4966 ".debug_loc", (uint64_t) shdr->sh_offset); 4967 4968 size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 4969 4970 bool first = true; 4971 unsigned char *readp = data->d_buf; 4972 while (readp < (unsigned char *) data->d_buf + data->d_size) 4973 { 4974 ptrdiff_t offset = readp - (unsigned char *) data->d_buf; 4975 4976 if (unlikely (data->d_size - offset < address_size * 2)) 4977 { 4978 printf (gettext (" [%6tx] <INVALID DATA>\n"), offset); 4979 break; 4980 } 4981 4982 Dwarf_Addr begin; 4983 Dwarf_Addr end; 4984 if (address_size == 8) 4985 { 4986 begin = read_8ubyte_unaligned_inc (dbg, readp); 4987 end = read_8ubyte_unaligned_inc (dbg, readp); 4988 } 4989 else 4990 { 4991 begin = read_4ubyte_unaligned_inc (dbg, readp); 4992 end = read_4ubyte_unaligned_inc (dbg, readp); 4993 if (begin == (Dwarf_Addr) (uint32_t) -1) 4994 begin = (Dwarf_Addr) -1l; 4995 } 4996 4997 if (begin == (Dwarf_Addr) -1l) /* Base address entry. */ 4998 { 4999 char *b = format_dwarf_addr (dwflmod, address_size, end); 5000 printf (gettext (" [%6tx] base address %s\n"), offset, b); 5001 free (b); 5002 } 5003 else if (begin == 0 && end == 0) /* End of list entry. */ 5004 first = true; 5005 else 5006 { 5007 /* We have a location expression entry. */ 5008 uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp); 5009 5010 char *b = format_dwarf_addr (dwflmod, address_size, begin); 5011 char *e = format_dwarf_addr (dwflmod, address_size, end); 5012 5013 if (first) /* First entry in a list. */ 5014 printf (gettext (" [%6tx] %s..%s"), offset, b, e); 5015 else 5016 printf (gettext (" %s..%s"), b, e); 5017 5018 free (b); 5019 free (e); 5020 5021 print_ops (dwflmod, dbg, 1, 18 + (address_size * 4), 5022 address_size, len, readp); 5023 5024 first = false; 5025 readp += len; 5026 } 5027 } 5028} 5029 5030struct mac_culist 5031{ 5032 Dwarf_Die die; 5033 Dwarf_Off offset; 5034 Dwarf_Files *files; 5035 struct mac_culist *next; 5036}; 5037 5038 5039static int 5040mac_compare (const void *p1, const void *p2) 5041{ 5042 struct mac_culist *m1 = (struct mac_culist *) p1; 5043 struct mac_culist *m2 = (struct mac_culist *) p2; 5044 5045 if (m1->offset < m2->offset) 5046 return -1; 5047 if (m1->offset > m2->offset) 5048 return 1; 5049 return 0; 5050} 5051 5052 5053static void 5054print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), 5055 Ebl *ebl __attribute__ ((unused)), 5056 GElf_Ehdr *ehdr __attribute__ ((unused)), 5057 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) 5058{ 5059 printf (gettext ("\ 5060\nDWARF section '%s' at offset %#" PRIx64 ":\n"), 5061 ".debug_macinfo", (uint64_t) shdr->sh_offset); 5062 putc_unlocked ('\n', stdout); 5063 5064 /* There is no function in libdw to iterate over the raw content of 5065 the section but it is easy enough to do. */ 5066 Elf_Data *data = elf_getdata (scn, NULL); 5067 if (unlikely (data == NULL || data->d_buf == NULL)) 5068 { 5069 error (0, 0, gettext ("cannot get macro information section data: %s"), 5070 elf_errmsg (-1)); 5071 return; 5072 } 5073 5074 /* Get the source file information for all CUs. */ 5075 Dwarf_Off offset; 5076 Dwarf_Off ncu = 0; 5077 size_t hsize; 5078 struct mac_culist *culist = NULL; 5079 size_t nculist = 0; 5080 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0) 5081 { 5082 Dwarf_Die cudie; 5083 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL) 5084 continue; 5085 5086 Dwarf_Attribute attr; 5087 if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL) 5088 continue; 5089 5090 Dwarf_Word macoff; 5091 if (dwarf_formudata (&attr, &macoff) != 0) 5092 continue; 5093 5094 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp)); 5095 newp->die = cudie; 5096 newp->offset = macoff; 5097 newp->files = NULL; 5098 newp->next = culist; 5099 culist = newp; 5100 ++nculist; 5101 } 5102 5103 /* Convert the list into an array for easier consumption. */ 5104 struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1) 5105 * sizeof (*cus)); 5106 /* Add sentinel. */ 5107 cus[nculist].offset = data->d_size; 5108 if (nculist > 0) 5109 { 5110 for (size_t cnt = nculist - 1; culist != NULL; --cnt) 5111 { 5112 assert (cnt < nculist); 5113 cus[cnt] = *culist; 5114 culist = culist->next; 5115 } 5116 5117 /* Sort the array according to the offset in the .debug_macinfo 5118 section. Note we keep the sentinel at the end. */ 5119 qsort (cus, nculist, sizeof (*cus), mac_compare); 5120 } 5121 5122 const unsigned char *readp = (const unsigned char *) data->d_buf; 5123 const unsigned char *readendp = readp + data->d_size; 5124 int level = 1; 5125 5126 while (readp < readendp) 5127 { 5128 unsigned int opcode = *readp++; 5129 unsigned int u128; 5130 unsigned int u128_2; 5131 const unsigned char *endp; 5132 5133 switch (opcode) 5134 { 5135 case DW_MACINFO_define: 5136 case DW_MACINFO_undef: 5137 case DW_MACINFO_vendor_ext: 5138 /* For the first two opcodes the parameters are 5139 line, string 5140 For the latter 5141 number, string. 5142 We can treat these cases together. */ 5143 get_uleb128 (u128, readp); 5144 5145 endp = memchr (readp, '\0', readendp - readp); 5146 if (unlikely (endp == NULL)) 5147 { 5148 printf (gettext ("\ 5149%*s*** non-terminated string at end of section"), 5150 level, ""); 5151 return; 5152 } 5153 5154 if (opcode == DW_MACINFO_define) 5155 printf ("%*s#define %s, line %u\n", 5156 level, "", (char *) readp, u128); 5157 else if (opcode == DW_MACINFO_undef) 5158 printf ("%*s#undef %s, line %u\n", 5159 level, "", (char *) readp, u128); 5160 else 5161 printf (" #vendor-ext %s, number %u\n", (char *) readp, u128); 5162 5163 readp = endp + 1; 5164 break; 5165 5166 case DW_MACINFO_start_file: 5167 /* The two parameters are line and file index, in this order. */ 5168 get_uleb128 (u128, readp); 5169 get_uleb128 (u128_2, readp); 5170 5171 /* Find the CU DIE for this file. */ 5172 size_t macoff = readp - (const unsigned char *) data->d_buf; 5173 const char *fname = "???"; 5174 if (macoff >= cus[0].offset) 5175 { 5176 while (macoff >= cus[1].offset) 5177 ++cus; 5178 5179 if (cus[0].files == NULL 5180 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0) 5181 cus[0].files = (Dwarf_Files *) -1l; 5182 5183 if (cus[0].files != (Dwarf_Files *) -1l) 5184 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL) 5185 ?: "???"); 5186 } 5187 5188 printf ("%*sstart_file %u, [%u] %s\n", 5189 level, "", u128, u128_2, fname); 5190 ++level; 5191 break; 5192 5193 case DW_MACINFO_end_file: 5194 --level; 5195 printf ("%*send_file\n", level, ""); 5196 /* Nothing more to do. */ 5197 break; 5198 5199 default: 5200 // XXX gcc seems to generate files with a trailing zero. 5201 if (unlikely (opcode != 0 || readp != readendp)) 5202 printf ("%*s*** invalid opcode %u\n", level, "", opcode); 5203 break; 5204 } 5205 } 5206} 5207 5208 5209/* Callback for printing global names. */ 5210static int 5211print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global, 5212 void *arg) 5213{ 5214 int *np = (int *) arg; 5215 5216 printf (gettext (" [%5d] DIE offset: %6" PRId64 5217 ", CU DIE offset: %6" PRId64 ", name: %s\n"), 5218 (*np)++, global->die_offset, global->cu_offset, global->name); 5219 5220 return 0; 5221} 5222 5223 5224/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */ 5225static void 5226print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)), 5227 Ebl *ebl __attribute__ ((unused)), 5228 GElf_Ehdr *ehdr __attribute__ ((unused)), 5229 Elf_Scn *scn __attribute__ ((unused)), 5230 GElf_Shdr *shdr, Dwarf *dbg) 5231{ 5232 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"), 5233 ".debug_pubnames", (uint64_t) shdr->sh_offset); 5234 5235 int n = 0; 5236 (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0); 5237} 5238 5239/* Print the content of the DWARF string section '.debug_str'. */ 5240static void 5241print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)), 5242 Ebl *ebl __attribute__ ((unused)), 5243 GElf_Ehdr *ehdr __attribute__ ((unused)), 5244 Elf_Scn *scn __attribute__ ((unused)), 5245 GElf_Shdr *shdr, Dwarf *dbg) 5246{ 5247 /* Compute floor(log16(shdr->sh_size)). */ 5248 GElf_Addr tmp = shdr->sh_size; 5249 int digits = 1; 5250 while (tmp >= 16) 5251 { 5252 ++digits; 5253 tmp >>= 4; 5254 } 5255 digits = MAX (4, digits); 5256 5257 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n" 5258 " %*s String\n"), 5259 ".debug_str", (uint64_t) shdr->sh_offset, 5260 /* TRANS: the debugstr| prefix makes the string unique. */ 5261 digits + 2, sgettext ("debugstr|Offset")); 5262 5263 Dwarf_Off offset = 0; 5264 while (offset < shdr->sh_size) 5265 { 5266 size_t len; 5267 const char *str = dwarf_getstring (dbg, offset, &len); 5268 if (unlikely (str == NULL)) 5269 { 5270 printf (gettext (" *** error while reading strings: %s\n"), 5271 dwarf_errmsg (-1)); 5272 break; 5273 } 5274 5275 printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str); 5276 5277 offset += len + 1; 5278 } 5279} 5280 5281static void 5282print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) 5283{ 5284 /* Before we start the real work get a debug context descriptor. */ 5285 Dwarf_Addr dwbias; 5286 Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias); 5287 if (dbg == NULL) 5288 { 5289 error (0, 0, gettext ("cannot get debug context descriptor: %s"), 5290 dwfl_errmsg (-1)); 5291 return; 5292 } 5293 5294 /* Get the section header string table index. */ 5295 size_t shstrndx; 5296 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 5297 error (EXIT_FAILURE, 0, 5298 gettext ("cannot get section header string table index")); 5299 5300 /* Look through all the sections for the debugging sections to print. */ 5301 Elf_Scn *scn = NULL; 5302 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 5303 { 5304 GElf_Shdr shdr_mem; 5305 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 5306 5307 if (shdr != NULL && shdr->sh_type == SHT_PROGBITS) 5308 { 5309 static const struct 5310 { 5311 const char *name; 5312 enum section_e bitmask; 5313 void (*fp) (Dwfl_Module *, Ebl *, 5314 GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *); 5315 } debug_sections[] = 5316 { 5317#define NEW_SECTION(name) \ 5318 { ".debug_" #name, section_##name, print_debug_##name##_section } 5319 NEW_SECTION (abbrev), 5320 NEW_SECTION (aranges), 5321 NEW_SECTION (frame), 5322 NEW_SECTION (info), 5323 NEW_SECTION (line), 5324 NEW_SECTION (loc), 5325 NEW_SECTION (pubnames), 5326 NEW_SECTION (str), 5327 NEW_SECTION (macinfo), 5328 NEW_SECTION (ranges), 5329 { ".eh_frame", section_frame, print_debug_frame_section } 5330 }; 5331 const int ndebug_sections = (sizeof (debug_sections) 5332 / sizeof (debug_sections[0])); 5333 const char *name = elf_strptr (ebl->elf, shstrndx, 5334 shdr->sh_name); 5335 int n; 5336 5337 for (n = 0; n < ndebug_sections; ++n) 5338 if (strcmp (name, debug_sections[n].name) == 0) 5339 { 5340 if (print_debug_sections & debug_sections[n].bitmask) 5341 debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg); 5342 break; 5343 } 5344 } 5345 } 5346} 5347 5348 5349#define ITEM_INDENT 4 5350#define ITEM_WRAP_COLUMN 150 5351#define REGISTER_WRAP_COLUMN 75 5352 5353/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would 5354 make the line exceed ITEM_WRAP_COLUMN. Unpadded numbers look better 5355 for the core items. But we do not want the line breaks to depend on 5356 the particular values. */ 5357static unsigned int 5358__attribute__ ((format (printf, 7, 8))) 5359print_core_item (unsigned int colno, char sep, unsigned int wrap, 5360 size_t name_width, const char *name, 5361 size_t format_max, const char *format, ...) 5362{ 5363 size_t len = strlen (name); 5364 if (name_width < len) 5365 name_width = len; 5366 5367 size_t n = name_width + sizeof ": " - 1 + format_max; 5368 5369 if (colno == 0) 5370 { 5371 printf ("%*s", ITEM_INDENT, ""); 5372 colno = ITEM_INDENT + n; 5373 } 5374 else if (colno + 2 + n < wrap) 5375 { 5376 printf ("%c ", sep); 5377 colno += 2 + n; 5378 } 5379 else 5380 { 5381 printf ("\n%*s", ITEM_INDENT, ""); 5382 colno = ITEM_INDENT + n; 5383 } 5384 5385 printf ("%s: %*s", name, (int) (name_width - len), ""); 5386 5387 va_list ap; 5388 va_start (ap, format); 5389 vprintf (format, ap); 5390 va_end (ap); 5391 5392 return colno; 5393} 5394 5395static const void * 5396convert (Elf *core, Elf_Type type, uint_fast16_t count, 5397 void *value, const void *data, size_t size) 5398{ 5399 Elf_Data valuedata = 5400 { 5401 .d_type = type, 5402 .d_buf = value, 5403 .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT), 5404 .d_version = EV_CURRENT, 5405 }; 5406 Elf_Data indata = 5407 { 5408 .d_type = type, 5409 .d_buf = (void *) data, 5410 .d_size = valuedata.d_size, 5411 .d_version = EV_CURRENT, 5412 }; 5413 5414 Elf_Data *d = (gelf_getclass (core) == ELFCLASS32 5415 ? elf32_xlatetom : elf64_xlatetom) 5416 (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]); 5417 if (d == NULL) 5418 error (EXIT_FAILURE, 0, 5419 gettext ("cannot convert core note data: %s"), elf_errmsg (-1)); 5420 5421 return data + indata.d_size; 5422} 5423 5424typedef uint8_t GElf_Byte; 5425 5426static unsigned int 5427handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, 5428 unsigned int colno, size_t *repeated_size) 5429{ 5430 uint_fast16_t count = item->count ?: 1; 5431 5432#define TYPES \ 5433 DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4); \ 5434 DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6); \ 5435 DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11); \ 5436 DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11); \ 5437 DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20); \ 5438 DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20) 5439 5440#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count] 5441 union { TYPES; } value; 5442#undef DO_TYPE 5443 5444 void *data = &value; 5445 size_t size = gelf_fsize (core, item->type, count, EV_CURRENT); 5446 size_t convsize = size; 5447 if (repeated_size != NULL) 5448 { 5449 if (*repeated_size > size && (item->format == 'b' || item->format == 'B')) 5450 { 5451 data = alloca (*repeated_size); 5452 count *= *repeated_size / size; 5453 convsize = count * size; 5454 *repeated_size -= convsize; 5455 } 5456 else 5457 *repeated_size -= size; 5458 } 5459 5460 desc = convert (core, item->type, count, data, desc + item->offset, convsize); 5461 5462 Elf_Type type = item->type; 5463 if (type == ELF_T_ADDR) 5464 type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD; 5465 5466 switch (item->format) 5467 { 5468 case 'd': 5469 assert (count == 1); 5470 switch (type) 5471 { 5472#define DO_TYPE(NAME, Name, hex, dec, max) \ 5473 case ELF_T_##NAME: \ 5474 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \ 5475 0, item->name, max, dec, value.Name[0]); \ 5476 break 5477 TYPES; 5478#undef DO_TYPE 5479 default: 5480 abort (); 5481 } 5482 break; 5483 5484 case 'x': 5485 assert (count == 1); 5486 switch (type) 5487 { 5488#define DO_TYPE(NAME, Name, hex, dec, max) \ 5489 case ELF_T_##NAME: \ 5490 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \ 5491 0, item->name, max, hex, value.Name[0]); \ 5492 break 5493 TYPES; 5494#undef DO_TYPE 5495 default: 5496 abort (); 5497 } 5498 break; 5499 5500 case 'b': 5501 case 'B': 5502 assert (size % sizeof (unsigned int) == 0); 5503 unsigned int nbits = count * size * 8; 5504 unsigned int pop = 0; 5505 for (const unsigned int *i = data; (void *) i < data + count * size; ++i) 5506 pop += __builtin_popcount (*i); 5507 bool negate = pop > nbits / 2; 5508 const unsigned int bias = item->format == 'b'; 5509 5510 { 5511 char printed[(negate ? nbits - pop : pop) * 16]; 5512 char *p = printed; 5513 *p = '\0'; 5514 5515 if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int)) 5516 { 5517 assert (size == sizeof (unsigned int) * 2); 5518 for (unsigned int *i = data; 5519 (void *) i < data + count * size; i += 2) 5520 { 5521 unsigned int w = i[1]; 5522 i[1] = i[0]; 5523 i[0] = w; 5524 } 5525 } 5526 5527 unsigned int lastbit = 0; 5528 for (const unsigned int *i = data; 5529 (void *) i < data + count * size; ++i) 5530 { 5531 unsigned int bit = ((void *) i - data) * 8; 5532 unsigned int w = negate ? ~*i : *i; 5533 while (w != 0) 5534 { 5535 int n = ffs (w); 5536 w >>= n; 5537 bit += n; 5538 5539 if (lastbit + 1 != bit) 5540 p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias); 5541 else if (lastbit == 0) 5542 p += sprintf (p, "%u", bit - bias); 5543 5544 lastbit = bit; 5545 } 5546 } 5547 if (lastbit > 0 && lastbit + 1 != nbits) 5548 p += sprintf (p, "-%u", nbits - bias); 5549 5550 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, 5551 4 + nbits * 4, 5552 negate ? "~<%s>" : "<%s>", printed); 5553 } 5554 break; 5555 5556 case 'T': 5557 case (char) ('T'|0x80): 5558 assert (count == 2); 5559 Dwarf_Word sec; 5560 Dwarf_Word usec; 5561 size_t maxfmt = 7; 5562 switch (type) 5563 { 5564#define DO_TYPE(NAME, Name, hex, dec, max) \ 5565 case ELF_T_##NAME: \ 5566 sec = value.Name[0]; \ 5567 usec = value.Name[1]; \ 5568 maxfmt += max; \ 5569 break 5570 TYPES; 5571#undef DO_TYPE 5572 default: 5573 abort (); 5574 } 5575 if (unlikely (item->format == (char) ('T'|0x80))) 5576 { 5577 /* This is a hack for an ill-considered 64-bit ABI where 5578 tv_usec is actually a 32-bit field with 32 bits of padding 5579 rounding out struct timeval. We've already converted it as 5580 a 64-bit field. For little-endian, this just means the 5581 high half is the padding; it's presumably zero, but should 5582 be ignored anyway. For big-endian, it means the 32-bit 5583 field went into the high half of USEC. */ 5584 GElf_Ehdr ehdr_mem; 5585 GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem); 5586 if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)) 5587 usec >>= 32; 5588 else 5589 usec &= UINT32_MAX; 5590 } 5591 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, 5592 maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec); 5593 break; 5594 5595 case 'c': 5596 assert (count == 1); 5597 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, 5598 1, "%c", value.Byte[0]); 5599 break; 5600 5601 case 's': 5602 colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, 5603 count, "%.*s", (int) count, value.Byte); 5604 break; 5605 5606 default: 5607 error (0, 0, "XXX not handling format '%c' for %s", 5608 item->format, item->name); 5609 break; 5610 } 5611 5612#undef TYPES 5613 5614 return colno; 5615} 5616 5617 5618/* Sort items by group, and by layout offset within each group. */ 5619static int 5620compare_core_items (const void *a, const void *b) 5621{ 5622 const Ebl_Core_Item *const *p1 = a; 5623 const Ebl_Core_Item *const *p2 = b; 5624 const Ebl_Core_Item *item1 = *p1; 5625 const Ebl_Core_Item *item2 = *p2; 5626 5627 return ((item1->group == item2->group ? 0 5628 : strcmp (item1->group, item2->group)) 5629 ?: (int) item1->offset - (int) item2->offset); 5630} 5631 5632/* Sort item groups by layout offset of the first item in the group. */ 5633static int 5634compare_core_item_groups (const void *a, const void *b) 5635{ 5636 const Ebl_Core_Item *const *const *p1 = a; 5637 const Ebl_Core_Item *const *const *p2 = b; 5638 const Ebl_Core_Item *const *group1 = *p1; 5639 const Ebl_Core_Item *const *group2 = *p2; 5640 const Ebl_Core_Item *item1 = *group1; 5641 const Ebl_Core_Item *item2 = *group2; 5642 5643 return (int) item1->offset - (int) item2->offset; 5644} 5645 5646static unsigned int 5647handle_core_items (Elf *core, const void *desc, size_t descsz, 5648 const Ebl_Core_Item *items, size_t nitems) 5649{ 5650 if (nitems == 0) 5651 return 0; 5652 5653 /* Sort to collect the groups together. */ 5654 const Ebl_Core_Item *sorted_items[nitems]; 5655 for (size_t i = 0; i < nitems; ++i) 5656 sorted_items[i] = &items[i]; 5657 qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items); 5658 5659 /* Collect the unique groups and sort them. */ 5660 const Ebl_Core_Item **groups[nitems]; 5661 groups[0] = &sorted_items[0]; 5662 size_t ngroups = 1; 5663 for (size_t i = 1; i < nitems; ++i) 5664 if (sorted_items[i]->group != sorted_items[i - 1]->group 5665 && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group)) 5666 groups[ngroups++] = &sorted_items[i]; 5667 qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups); 5668 5669 /* Write out all the groups. */ 5670 unsigned int colno = 0; 5671 5672 const void *last = desc; 5673 if (nitems == 1) 5674 { 5675 size_t size = descsz; 5676 colno = handle_core_item (core, sorted_items[0], desc, colno, &size); 5677 if (size == 0) 5678 return colno; 5679 desc += descsz - size; 5680 descsz = size; 5681 } 5682 5683 do 5684 { 5685 for (size_t i = 0; i < ngroups; ++i) 5686 { 5687 for (const Ebl_Core_Item **item = groups[i]; 5688 (item < &sorted_items[nitems] 5689 && ((*item)->group == groups[i][0]->group 5690 || !strcmp ((*item)->group, groups[i][0]->group))); 5691 ++item) 5692 colno = handle_core_item (core, *item, desc, colno, NULL); 5693 5694 /* Force a line break at the end of the group. */ 5695 colno = ITEM_WRAP_COLUMN; 5696 } 5697 5698 if (descsz == 0) 5699 break; 5700 5701 /* This set of items consumed a certain amount of the note's data. 5702 If there is more data there, we have another unit of the same size. 5703 Loop to print that out too. */ 5704 const Ebl_Core_Item *item = &items[nitems - 1]; 5705 size_t eltsz = item->offset + gelf_fsize (core, item->type, 5706 item->count ?: 1, EV_CURRENT); 5707 5708 int reps = -1; 5709 do 5710 { 5711 ++reps; 5712 desc += eltsz; 5713 descsz -= eltsz; 5714 } 5715 while (descsz >= eltsz && !memcmp (desc, last, eltsz)); 5716 5717 if (reps == 1) 5718 { 5719 /* For just one repeat, print it unabridged twice. */ 5720 desc -= eltsz; 5721 descsz += eltsz; 5722 } 5723 else if (reps > 1) 5724 printf (gettext ("\n%*s... <repeats %u more times> ..."), 5725 ITEM_INDENT, "", reps); 5726 5727 last = desc; 5728 } 5729 while (descsz > 0); 5730 5731 return colno; 5732} 5733 5734static unsigned int 5735handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc, 5736 unsigned int colno) 5737{ 5738 desc += regloc->offset; 5739 5740 abort (); /* XXX */ 5741 return colno; 5742} 5743 5744 5745static unsigned int 5746handle_core_register (Ebl *ebl, Elf *core, int maxregname, 5747 const Ebl_Register_Location *regloc, const void *desc, 5748 unsigned int colno) 5749{ 5750 if (regloc->bits % 8 != 0) 5751 return handle_bit_registers (regloc, desc, colno); 5752 5753 desc += regloc->offset; 5754 5755 for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg) 5756 { 5757 const char *pfx; 5758 const char *set; 5759 char name[16]; 5760 int bits; 5761 int type; 5762 ssize_t n = ebl_register_info (ebl, reg, name, sizeof name, 5763 &pfx, &set, &bits, &type); 5764 if (n <= 0) 5765 error (EXIT_FAILURE, 0, 5766 gettext ("unable to handle register number %d"), 5767 regloc->regno); 5768 5769#define TYPES \ 5770 BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4); \ 5771 BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6); \ 5772 BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11); \ 5773 BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64, 20) 5774 5775#define BITS(bits, xtype, sfmt, ufmt, max) \ 5776 uint##bits##_t b##bits; int##bits##_t b##bits##s 5777 union { TYPES; uint64_t b128[2]; } value; 5778#undef BITS 5779 5780 switch (type) 5781 { 5782 case DW_ATE_unsigned: 5783 case DW_ATE_signed: 5784 case DW_ATE_address: 5785 switch (bits) 5786 { 5787#define BITS(bits, xtype, sfmt, ufmt, max) \ 5788 case bits: \ 5789 desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \ 5790 if (type == DW_ATE_signed) \ 5791 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \ 5792 maxregname, name, \ 5793 max, sfmt, value.b##bits##s); \ 5794 else \ 5795 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \ 5796 maxregname, name, \ 5797 max, ufmt, value.b##bits); \ 5798 break 5799 5800 TYPES; 5801 5802 case 128: 5803 assert (type == DW_ATE_unsigned); 5804 desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0); 5805 int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB; 5806 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, 5807 maxregname, name, 5808 34, "0x%.16" PRIx64 "%.16" PRIx64, 5809 value.b128[!be], value.b128[be]); 5810 break; 5811 5812 default: 5813 abort (); 5814#undef BITS 5815 } 5816 break; 5817 5818 default: 5819 /* Print each byte in hex, the whole thing in native byte order. */ 5820 assert (bits % 8 == 0); 5821 const uint8_t *bytes = desc; 5822 desc += bits / 8; 5823 char hex[bits / 4 + 1]; 5824 hex[bits / 4] = '\0'; 5825 int incr = 1; 5826 if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB) 5827 { 5828 bytes += bits / 8 - 1; 5829 incr = -1; 5830 } 5831 size_t idx = 0; 5832 for (char *h = hex; bits > 0; bits -= 8, idx += incr) 5833 { 5834 *h++ = "0123456789abcdef"[bytes[idx] >> 4]; 5835 *h++ = "0123456789abcdef"[bytes[idx] & 0xf]; 5836 } 5837 colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, 5838 maxregname, name, 5839 2 + sizeof hex - 1, "0x%s", hex); 5840 break; 5841 } 5842 desc += regloc->pad; 5843 5844#undef TYPES 5845 } 5846 5847 return colno; 5848} 5849 5850 5851struct register_info 5852{ 5853 const Ebl_Register_Location *regloc; 5854 const char *set; 5855 char name[16]; 5856 Dwarf_Half regno; 5857 uint8_t bits; 5858 uint8_t type; 5859}; 5860 5861static int 5862register_bitpos (const struct register_info *r) 5863{ 5864 return (r->regloc->offset * 8 5865 + ((r->regno - r->regloc->regno) 5866 * (r->regloc->bits + r->regloc->pad * 8))); 5867} 5868 5869static int 5870compare_sets_by_info (const struct register_info *r1, 5871 const struct register_info *r2) 5872{ 5873 return ((int) r2->bits - (int) r1->bits 5874 ?: register_bitpos (r1) - register_bitpos (r2)); 5875} 5876 5877/* Sort registers by set, and by size and layout offset within each set. */ 5878static int 5879compare_registers (const void *a, const void *b) 5880{ 5881 const struct register_info *r1 = a; 5882 const struct register_info *r2 = b; 5883 5884 /* Unused elements sort last. */ 5885 if (r1->regloc == NULL) 5886 return r2->regloc == NULL ? 0 : 1; 5887 if (r2->regloc == NULL) 5888 return -1; 5889 5890 return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set)) 5891 ?: compare_sets_by_info (r1, r2)); 5892} 5893 5894/* Sort register sets by layout offset of the first register in the set. */ 5895static int 5896compare_register_sets (const void *a, const void *b) 5897{ 5898 const struct register_info *const *p1 = a; 5899 const struct register_info *const *p2 = b; 5900 return compare_sets_by_info (*p1, *p2); 5901} 5902 5903static unsigned int 5904handle_core_registers (Ebl *ebl, Elf *core, const void *desc, 5905 const Ebl_Register_Location *reglocs, size_t nregloc) 5906{ 5907 if (nregloc == 0) 5908 return 0; 5909 5910 ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL); 5911 if (maxnreg <= 0) 5912 error (EXIT_FAILURE, 0, 5913 gettext ("cannot register info: %s"), elf_errmsg (-1)); 5914 5915 struct register_info regs[maxnreg]; 5916 memset (regs, 0, sizeof regs); 5917 5918 /* Sort to collect the sets together. */ 5919 int maxreg = 0; 5920 for (size_t i = 0; i < nregloc; ++i) 5921 for (int reg = reglocs[i].regno; 5922 reg < reglocs[i].regno + reglocs[i].count; 5923 ++reg) 5924 { 5925 assert (reg < maxnreg); 5926 if (reg > maxreg) 5927 maxreg = reg; 5928 struct register_info *info = ®s[reg]; 5929 5930 const char *pfx; 5931 int bits; 5932 int type; 5933 ssize_t n = ebl_register_info (ebl, reg, info->name, sizeof info->name, 5934 &pfx, &info->set, &bits, &type); 5935 if (n <= 0) 5936 error (EXIT_FAILURE, 0, 5937 gettext ("cannot register info: %s"), elf_errmsg (-1)); 5938 5939 info->regloc = ®locs[i]; 5940 info->regno = reg; 5941 info->bits = bits; 5942 info->type = type; 5943 } 5944 qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers); 5945 5946 /* Collect the unique sets and sort them. */ 5947 inline bool same_set (const struct register_info *a, 5948 const struct register_info *b) 5949 { 5950 return (a < ®s[maxnreg] && a->regloc != NULL 5951 && b < ®s[maxnreg] && b->regloc != NULL 5952 && a->bits == b->bits 5953 && (a->set == b->set || !strcmp (a->set, b->set))); 5954 } 5955 struct register_info *sets[maxreg + 1]; 5956 sets[0] = ®s[0]; 5957 size_t nsets = 1; 5958 for (int i = 1; i <= maxreg; ++i) 5959 if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1])) 5960 sets[nsets++] = ®s[i]; 5961 qsort (sets, nsets, sizeof sets[0], &compare_register_sets); 5962 5963 /* Write out all the sets. */ 5964 unsigned int colno = 0; 5965 for (size_t i = 0; i < nsets; ++i) 5966 { 5967 /* Find the longest name of a register in this set. */ 5968 size_t maxname = 0; 5969 const struct register_info *end; 5970 for (end = sets[i]; same_set (sets[i], end); ++end) 5971 { 5972 size_t len = strlen (end->name); 5973 if (len > maxname) 5974 maxname = len; 5975 } 5976 5977 for (const struct register_info *reg = sets[i]; 5978 reg < end; 5979 reg += reg->regloc->count ?: 1) 5980 colno = handle_core_register (ebl, core, maxname, 5981 reg->regloc, desc, colno); 5982 5983 /* Force a line break at the end of the group. */ 5984 colno = REGISTER_WRAP_COLUMN; 5985 } 5986 5987 return colno; 5988} 5989 5990static void 5991handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos) 5992{ 5993 Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV); 5994 if (data == NULL) 5995 elf_error: 5996 error (EXIT_FAILURE, 0, 5997 gettext ("cannot convert core note data: %s"), elf_errmsg (-1)); 5998 5999 const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT); 6000 for (size_t i = 0; i < nauxv; ++i) 6001 { 6002 GElf_auxv_t av_mem; 6003 GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem); 6004 if (av == NULL) 6005 goto elf_error; 6006 6007 const char *name; 6008 const char *fmt; 6009 if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0) 6010 { 6011 /* Unknown type. */ 6012 if (av->a_un.a_val == 0) 6013 printf (" %" PRIu64 "\n", av->a_type); 6014 else 6015 printf (" %" PRIu64 ": %#" PRIx64 "\n", 6016 av->a_type, av->a_un.a_val); 6017 } 6018 else 6019 switch (fmt[0]) 6020 { 6021 case '\0': /* Normally zero. */ 6022 if (av->a_un.a_val == 0) 6023 { 6024 printf (" %s\n", name); 6025 break; 6026 } 6027 /* Fall through */ 6028 case 'x': /* hex */ 6029 case 'p': /* address */ 6030 case 's': /* address of string */ 6031 printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val); 6032 break; 6033 case 'u': 6034 printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val); 6035 break; 6036 case 'd': 6037 printf (" %s: %" PRId64 "\n", name, av->a_un.a_val); 6038 break; 6039 6040 case 'b': 6041 printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val); 6042 GElf_Xword bit = 1; 6043 const char *pfx = "<"; 6044 for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1) 6045 { 6046 if (av->a_un.a_val & bit) 6047 { 6048 printf ("%s%s", pfx, p); 6049 pfx = " "; 6050 } 6051 bit <<= 1; 6052 } 6053 printf (">\n"); 6054 break; 6055 6056 default: 6057 abort (); 6058 } 6059 } 6060} 6061 6062static void 6063handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc) 6064{ 6065 GElf_Word regs_offset; 6066 size_t nregloc; 6067 const Ebl_Register_Location *reglocs; 6068 size_t nitems; 6069 const Ebl_Core_Item *items; 6070 6071 if (! ebl_core_note (ebl, nhdr->n_type, nhdr->n_descsz, 6072 ®s_offset, &nregloc, ®locs, &nitems, &items)) 6073 return; 6074 6075 /* Pass 0 for DESCSZ when there are registers in the note, 6076 so that the ITEMS array does not describe the whole thing. 6077 For non-register notes, the actual descsz might be a multiple 6078 of the unit size, not just exactly the unit size. */ 6079 unsigned int colno = handle_core_items (ebl->elf, desc, 6080 nregloc == 0 ? nhdr->n_descsz : 0, 6081 items, nitems); 6082 if (colno != 0) 6083 putchar_unlocked ('\n'); 6084 6085 colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset, 6086 reglocs, nregloc); 6087 if (colno != 0) 6088 putchar_unlocked ('\n'); 6089} 6090 6091static void 6092handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr, 6093 GElf_Off start, Elf_Data *data) 6094{ 6095 fputs_unlocked (gettext (" Owner Data size Type\n"), stdout); 6096 6097 if (data == NULL) 6098 goto bad_note; 6099 6100 size_t offset = 0; 6101 GElf_Nhdr nhdr; 6102 size_t name_offset; 6103 size_t desc_offset; 6104 while (offset < data->d_size 6105 && (offset = gelf_getnote (data, offset, 6106 &nhdr, &name_offset, &desc_offset)) > 0) 6107 { 6108 const char *name = data->d_buf + name_offset; 6109 const char *desc = data->d_buf + desc_offset; 6110 6111 char buf[100]; 6112 char buf2[100]; 6113 printf (gettext (" %-13.*s %9" PRId32 " %s\n"), 6114 (int) nhdr.n_namesz, name, nhdr.n_descsz, 6115 ehdr->e_type == ET_CORE 6116 ? ebl_core_note_type_name (ebl, nhdr.n_type, 6117 buf, sizeof (buf)) 6118 : ebl_object_note_type_name (ebl, nhdr.n_type, 6119 buf2, sizeof (buf2))); 6120 6121 /* Filter out invalid entries. */ 6122 if (memchr (name, '\0', nhdr.n_namesz) != NULL 6123 /* XXX For now help broken Linux kernels. */ 6124 || 1) 6125 { 6126 if (ehdr->e_type == ET_CORE) 6127 { 6128 if (nhdr.n_type == NT_AUXV) 6129 handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz, 6130 start + desc_offset); 6131 else 6132 handle_core_note (ebl, &nhdr, desc); 6133 } 6134 else 6135 ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc); 6136 } 6137 } 6138 6139 if (offset == data->d_size) 6140 return; 6141 6142 bad_note: 6143 error (EXIT_FAILURE, 0, 6144 gettext ("cannot get content of note section: %s"), 6145 elf_errmsg (-1)); 6146} 6147 6148static void 6149handle_notes (Ebl *ebl, GElf_Ehdr *ehdr) 6150{ 6151 /* If we have section headers, just look for SHT_NOTE sections. 6152 In a debuginfo file, the program headers are not reliable. */ 6153 if (shnum != 0) 6154 { 6155 /* Get the section header string table index. */ 6156 size_t shstrndx; 6157 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 6158 error (EXIT_FAILURE, 0, 6159 gettext ("cannot get section header string table index")); 6160 6161 Elf_Scn *scn = NULL; 6162 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 6163 { 6164 GElf_Shdr shdr_mem; 6165 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 6166 6167 if (shdr == NULL || shdr->sh_type != SHT_NOTE) 6168 /* Not what we are looking for. */ 6169 continue; 6170 6171 printf (gettext ("\ 6172\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"), 6173 elf_ndxscn (scn), 6174 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 6175 shdr->sh_size, shdr->sh_offset); 6176 6177 handle_notes_data (ebl, ehdr, shdr->sh_offset, 6178 elf_getdata (scn, NULL)); 6179 } 6180 return; 6181 } 6182 6183 /* We have to look through the program header to find the note 6184 sections. There can be more than one. */ 6185 for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt) 6186 { 6187 GElf_Phdr mem; 6188 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem); 6189 6190 if (phdr == NULL || phdr->p_type != PT_NOTE) 6191 /* Not what we are looking for. */ 6192 continue; 6193 6194 printf (gettext ("\ 6195\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"), 6196 phdr->p_filesz, phdr->p_offset); 6197 6198 handle_notes_data (ebl, ehdr, phdr->p_offset, 6199 elf_getdata_rawchunk (ebl->elf, 6200 phdr->p_offset, phdr->p_filesz, 6201 ELF_T_NHDR)); 6202 } 6203} 6204 6205 6206static void 6207hex_dump (const uint8_t *data, size_t len) 6208{ 6209 size_t pos = 0; 6210 while (pos < len) 6211 { 6212 printf (" 0x%08Zx ", pos); 6213 6214 const size_t chunk = MIN (len - pos, 16); 6215 6216 for (size_t i = 0; i < chunk; ++i) 6217 if (i % 4 == 3) 6218 printf ("%02x ", data[pos + i]); 6219 else 6220 printf ("%02x", data[pos + i]); 6221 6222 if (chunk < 16) 6223 printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), ""); 6224 6225 for (size_t i = 0; i < chunk; ++i) 6226 { 6227 unsigned char b = data[pos + i]; 6228 printf ("%c", isprint (b) ? b : '.'); 6229 } 6230 6231 putchar ('\n'); 6232 pos += chunk; 6233 } 6234} 6235 6236static void 6237dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name) 6238{ 6239 if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS) 6240 printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"), 6241 elf_ndxscn (scn), name); 6242 else 6243 { 6244 Elf_Data *data = elf_rawdata (scn, NULL); 6245 if (data == NULL) 6246 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"), 6247 elf_ndxscn (scn), name, elf_errmsg (-1)); 6248 else 6249 { 6250 printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64 6251 " bytes at offset %#0" PRIx64 ":\n"), 6252 elf_ndxscn (scn), name, 6253 shdr->sh_size, shdr->sh_offset); 6254 hex_dump (data->d_buf, data->d_size); 6255 } 6256 } 6257} 6258 6259static void 6260print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name) 6261{ 6262 if (shdr->sh_size == 0) 6263 printf (gettext ("\nSection [%Zu] '%s' is empty.\n"), 6264 elf_ndxscn (scn), name); 6265 6266 Elf_Data *data = elf_rawdata (scn, NULL); 6267 if (data == NULL) 6268 error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"), 6269 elf_ndxscn (scn), name, elf_errmsg (-1)); 6270 else 6271 { 6272 printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64 6273 " bytes at offset %#0" PRIx64 ":\n"), 6274 elf_ndxscn (scn), name, 6275 shdr->sh_size, shdr->sh_offset); 6276 6277 const char *start = data->d_buf; 6278 const char *const limit = start + data->d_size; 6279 do 6280 { 6281 const char *end = memchr (start, '\0', limit - start); 6282 const size_t pos = start - (const char *) data->d_buf; 6283 if (unlikely (end == NULL)) 6284 { 6285 printf (" [%6Zx]- %.*s\n", 6286 pos, (int) (limit - start), start); 6287 break; 6288 } 6289 printf (" [%6Zx] %s\n", pos, start); 6290 start = end + 1; 6291 } while (start < limit); 6292 } 6293} 6294 6295static void 6296for_each_section_argument (Elf *elf, const struct section_argument *list, 6297 void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr, 6298 const char *name)) 6299{ 6300 /* Get the section header string table index. */ 6301 size_t shstrndx; 6302 if (elf_getshstrndx (elf, &shstrndx) < 0) 6303 error (EXIT_FAILURE, 0, 6304 gettext ("cannot get section header string table index")); 6305 6306 for (const struct section_argument *a = list; a != NULL; a = a->next) 6307 { 6308 Elf_Scn *scn; 6309 GElf_Shdr shdr_mem; 6310 const char *name = NULL; 6311 6312 char *endp = NULL; 6313 unsigned long int shndx = strtoul (a->arg, &endp, 0); 6314 if (endp != a->arg && *endp == '\0') 6315 { 6316 scn = elf_getscn (elf, shndx); 6317 if (scn == NULL) 6318 { 6319 error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx); 6320 continue; 6321 } 6322 6323 if (gelf_getshdr (scn, &shdr_mem) == NULL) 6324 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"), 6325 elf_errmsg (-1)); 6326 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name); 6327 } 6328 else 6329 { 6330 /* Need to look up the section by name. */ 6331 scn = NULL; 6332 while ((scn = elf_nextscn (elf, scn)) != NULL) 6333 { 6334 if (gelf_getshdr (scn, &shdr_mem) == NULL) 6335 continue; 6336 name = elf_strptr (elf, shstrndx, shdr_mem.sh_name); 6337 if (name == NULL) 6338 continue; 6339 if (!strcmp (name, a->arg)) 6340 break; 6341 } 6342 6343 if (unlikely (scn == NULL)) 6344 { 6345 error (0, 0, gettext ("\nsection '%s' does not exist"), a->arg); 6346 continue; 6347 } 6348 } 6349 6350 (*dump) (scn, &shdr_mem, name); 6351 } 6352} 6353 6354static void 6355dump_data (Ebl *ebl) 6356{ 6357 for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section); 6358} 6359 6360static void 6361dump_strings (Ebl *ebl) 6362{ 6363 for_each_section_argument (ebl->elf, string_sections, &print_string_section); 6364} 6365 6366static void 6367print_strings (Ebl *ebl) 6368{ 6369 /* Get the section header string table index. */ 6370 size_t shstrndx; 6371 if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) 6372 error (EXIT_FAILURE, 0, 6373 gettext ("cannot get section header string table index")); 6374 6375 Elf_Scn *scn; 6376 GElf_Shdr shdr_mem; 6377 const char *name; 6378 scn = NULL; 6379 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 6380 { 6381 if (gelf_getshdr (scn, &shdr_mem) == NULL) 6382 continue; 6383 6384 if (shdr_mem.sh_type != SHT_PROGBITS 6385 || !(shdr_mem.sh_flags & SHF_STRINGS)) 6386 continue; 6387 6388 name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name); 6389 if (name == NULL) 6390 continue; 6391 6392 print_string_section (scn, &shdr_mem, name); 6393 } 6394} 6395 6396static void 6397dump_archive_index (Elf *elf, const char *fname) 6398{ 6399 size_t narsym; 6400 const Elf_Arsym *arsym = elf_getarsym (elf, &narsym); 6401 if (arsym == NULL) 6402 { 6403 int result = elf_errno (); 6404 if (unlikely (result != ELF_E_NO_INDEX)) 6405 error (EXIT_FAILURE, 0, 6406 gettext ("cannot get symbol index of archive '%s': %s"), 6407 fname, elf_errmsg (result)); 6408 else 6409 printf (gettext ("\nArchive '%s' has no symbol index\n"), fname); 6410 return; 6411 } 6412 6413 printf (gettext ("\nIndex of archive '%s' has %Zu entries:\n"), 6414 fname, narsym); 6415 6416 size_t as_off = 0; 6417 for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s) 6418 { 6419 if (s->as_off != as_off) 6420 { 6421 as_off = s->as_off; 6422 6423 Elf *subelf; 6424 if (unlikely (elf_rand (elf, as_off) == 0) 6425 || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf)) 6426 == NULL)) 6427#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7) 6428 while (1) 6429#endif 6430 error (EXIT_FAILURE, 0, 6431 gettext ("cannot extract member at offset %Zu in '%s': %s"), 6432 as_off, fname, elf_errmsg (-1)); 6433 6434 const Elf_Arhdr *h = elf_getarhdr (subelf); 6435 6436 printf (gettext ("Archive member '%s' contains:\n"), h->ar_name); 6437 6438 elf_end (subelf); 6439 } 6440 6441 printf ("\t%s\n", s->as_name); 6442 } 6443} 6444 6445#include "debugpred.h" 6446