1 /* Print information from ELF file in human-readable form. 2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 1999. 4 5 This program is Open Source software; you can redistribute it and/or 6 modify it under the terms of the Open Software License version 1.0 as 7 published by the Open Source Initiative. 8 9 You should have received a copy of the Open Software License along 10 with this program; if not, you may obtain a copy of the Open Software 11 License version 1.0 from http://www.opensource.org/licenses/osl.php or 12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 13 3001 King Ranch Road, Ukiah, CA 95482. */ 14 15 #ifdef HAVE_CONFIG_H 16 # include <config.h> 17 #endif 18 19 #include <argp.h> 20 #include <assert.h> 21 #include <dwarf.h> 22 #include <errno.h> 23 #include <error.h> 24 #include <fcntl.h> 25 #include <gelf.h> 26 #include <inttypes.h> 27 #include <langinfo.h> 28 #include <libdw.h> 29 #include <libebl.h> 30 #include <libintl.h> 31 #include <locale.h> 32 #include <stdbool.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #include <unistd.h> 37 #include <sys/param.h> 38 39 #include <system.h> 40 #include "../libdw/libdwP.h" 41 #include "../libdw/memory-access.h" 42 43 44 /* Name and version of program. */ 45 static void print_version (FILE *stream, struct argp_state *state); 46 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; 47 48 /* Definitions of arguments for argp functions. */ 49 static const struct argp_option options[] = 50 { 51 { NULL, 0, NULL, 0, N_("Output selection:") }, 52 { "all", 'a', NULL, 0, N_("Equivalent to: -h -l") }, 53 { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment") }, 54 { "file-header", 'h', NULL, 0, N_("Display the ELF file header") }, 55 { "histogram", 'I', NULL, 0, 56 N_("Display histogram of bucket list lengths") }, 57 { "program-headers", 'l', NULL, 0, N_("Display the program headers") }, 58 { "relocs", 'r', NULL, 0, N_("Display relocations") }, 59 { "section-headers", 'S', NULL, 0, N_("Display the sections' header") }, 60 { "symbols", 's', NULL, 0, N_("Display the symbol table") }, 61 { "version-info", 'V', NULL, 0, N_("Display versioning information") }, 62 { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, 63 N_("Display DWARF section content. SECTION can be one of abbrev, " 64 "aranges, frame, info, loc, line, pubnames, str, or macinfo.") }, 65 { "notes", 'n', NULL, 0, N_("Display the core notes") }, 66 { "arch-specific", 'A', NULL, 0, 67 N_("Display architecture specific information (if any)") }, 68 69 { NULL, 0, NULL, 0, N_("Output control:") }, 70 71 { NULL, 0, NULL, 0, NULL } 72 }; 73 74 /* Short description of program. */ 75 static const char doc[] = N_("\ 76 Print information from ELF file in human-readable form."); 77 78 /* Strings for arguments in help texts. */ 79 static const char args_doc[] = N_("FILE..."); 80 81 /* Prototype for option handler. */ 82 static error_t parse_opt (int key, char *arg, struct argp_state *state); 83 84 /* Function to print some extra text in the help message. */ 85 static char *more_help (int key, const char *text, void *input); 86 87 /* Data structure to communicate with argp functions. */ 88 static struct argp argp = 89 { 90 options, parse_opt, args_doc, doc, NULL, more_help 91 }; 92 93 94 /* Flags set by the option controlling the output. */ 95 96 /* True if any of the control options is set. */ 97 static bool any_control_option; 98 99 /* True if dynamic segment should be printed. */ 100 static bool print_dynamic_table; 101 102 /* True if the file header should be printed. */ 103 static bool print_file_header; 104 105 /* True if the program headers should be printed. */ 106 static bool print_program_header; 107 108 /* True if relocations should be printed. */ 109 static bool print_relocations; 110 111 /* True if the section headers should be printed. */ 112 static bool print_section_header; 113 114 /* True if the symbol table should be printed. */ 115 static bool print_symbol_table; 116 117 /* True if the version information should be printed. */ 118 static bool print_version_info; 119 120 /* True if section groups should be printed. */ 121 static bool print_section_groups; 122 123 /* True if bucket list length histogram should be printed. */ 124 static bool print_histogram; 125 126 /* True if the architecture specific data should be printed. */ 127 static bool print_arch; 128 129 /* True if note section content should be printed. */ 130 static bool print_notes; 131 132 /* Select printing of debugging sections. */ 133 static enum section_e 134 { 135 section_abbrev = 1, /* .debug_abbrev */ 136 section_aranges = 2, /* .debug_aranges */ 137 section_frame = 4, /* .debug_frame or .eh_frame */ 138 section_info = 8, /* .debug_info */ 139 section_line = 16, /* .debug_line */ 140 section_loc = 32, /* .debug_loc */ 141 section_pubnames = 64,/* .debug_pubnames */ 142 section_str = 128, /* .debug_str */ 143 section_macinfo = 256,/* .debug_macinfo */ 144 section_all = (section_abbrev | section_aranges | section_frame 145 | section_info | section_line | section_loc 146 | section_pubnames | section_str | section_macinfo) 147 } print_debug_sections; 148 149 /* Number of sections in the file. */ 150 static size_t shnum; 151 152 153 /* Declarations of local functions. */ 154 static void process_file (int fd, Elf *elf, const char *prefix, 155 const char *fname, bool only_one); 156 static void process_elf_file (Elf *elf, const char *prefix, const char *fname, 157 bool only_one); 158 static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr); 159 static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); 160 static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); 161 static void print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr); 162 static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr); 163 static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr); 164 static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 165 GElf_Shdr *shdr); 166 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 167 GElf_Shdr *shdr); 168 static void print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type); 169 static void handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 170 GElf_Shdr *shdr); 171 static void print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr); 172 static void handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 173 GElf_Shdr *shdr); 174 static void handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 175 GElf_Shdr *shdr); 176 static void handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 177 GElf_Shdr *shdr); 178 static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr); 179 static void handle_hash (Ebl *ebl, GElf_Ehdr *ehdr); 180 static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr); 181 static void print_liblist (Ebl *ebl, GElf_Ehdr *ehdr); 182 183 184 int 185 main (int argc, char *argv[]) 186 { 187 int remaining; 188 bool only_one; 189 190 /* Set locale. */ 191 setlocale (LC_ALL, ""); 192 193 /* Initialize the message catalog. */ 194 textdomain (PACKAGE); 195 196 /* Parse and process arguments. */ 197 argp_parse (&argp, argc, argv, 0, &remaining, NULL); 198 199 /* If no control option or no ELF file is given punt. */ 200 if ((any_control_option == 0 && print_debug_sections == 0) 201 || remaining >= argc) 202 { 203 argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, 204 program_invocation_short_name); 205 exit (1); 206 } 207 208 /* Before we start tell the ELF library which version we are using. */ 209 elf_version (EV_CURRENT); 210 211 /* Now process all the files given at the command line. */ 212 only_one = remaining + 1 == argc; 213 do 214 { 215 int fd; 216 Elf *elf; 217 218 /* Open the file. */ 219 fd = open (argv[remaining], O_RDONLY); 220 if (fd == -1) 221 { 222 error (0, errno, gettext ("cannot open input file")); 223 continue; 224 } 225 226 /* Create an `Elf' descriptor. */ 227 elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 228 if (elf == NULL) 229 error (0, 0, gettext ("cannot generate Elf descriptor: %s\n"), 230 elf_errmsg (-1)); 231 else 232 { 233 process_file (fd, elf, NULL, argv[remaining], only_one); 234 235 /* Now we can close the descriptor. */ 236 if (elf_end (elf) != 0) 237 error (0, 0, gettext ("error while closing Elf descriptor: %s"), 238 elf_errmsg (-1)); 239 } 240 241 close (fd); 242 } 243 while (++remaining < argc); 244 245 return error_message_count != 0; 246 } 247 248 249 /* Handle program arguments. */ 250 static error_t 251 parse_opt (int key, char *arg, struct argp_state *state) 252 { 253 switch (key) 254 { 255 case 'a': 256 print_file_header = true; 257 print_program_header = true; 258 print_relocations = true; 259 print_section_header = true; 260 print_symbol_table = true; 261 print_version_info = true; 262 print_dynamic_table = true; 263 print_section_groups = true; 264 print_histogram = true; 265 print_arch = true; 266 print_notes = true; 267 any_control_option = true; 268 break; 269 case 'A': 270 print_arch = true; 271 any_control_option = true; 272 break; 273 case 'd': 274 print_dynamic_table = true; 275 any_control_option = true; 276 break; 277 case 'g': 278 print_section_groups = true; 279 any_control_option = true; 280 break; 281 case 'h': 282 print_file_header = true; 283 any_control_option = true; 284 break; 285 case 'I': 286 print_histogram = true; 287 any_control_option = true; 288 break; 289 case 'l': 290 print_program_header = true; 291 any_control_option = true; 292 break; 293 case 'n': 294 print_notes = true; 295 any_control_option = true; 296 break; 297 case 'r': 298 print_relocations = true; 299 any_control_option = true; 300 break; 301 case 'S': 302 print_section_header = true; 303 any_control_option = true; 304 break; 305 case 's': 306 print_symbol_table = true; 307 any_control_option = true; 308 break; 309 case 'V': 310 print_version_info = true; 311 any_control_option = true; 312 break; 313 case 'w': 314 if (arg == NULL) 315 print_debug_sections = section_all; 316 else if (strcmp (arg, "abbrev") == 0) 317 print_debug_sections |= section_abbrev; 318 else if (strcmp (arg, "aranges") == 0) 319 print_debug_sections |= section_aranges; 320 else if (strcmp (arg, "frame") == 0) 321 print_debug_sections |= section_frame; 322 else if (strcmp (arg, "info") == 0) 323 print_debug_sections |= section_info; 324 else if (strcmp (arg, "loc") == 0) 325 print_debug_sections |= section_loc; 326 else if (strcmp (arg, "line") == 0) 327 print_debug_sections |= section_line; 328 else if (strcmp (arg, "pubnames") == 0) 329 print_debug_sections |= section_pubnames; 330 else if (strcmp (arg, "str") == 0) 331 print_debug_sections |= section_str; 332 else if (strcmp (arg, "macinfo") == 0) 333 print_debug_sections |= section_macinfo; 334 else 335 { 336 fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"), 337 arg); 338 argp_help (&argp, stderr, ARGP_HELP_SEE, 339 program_invocation_short_name); 340 exit (1); 341 } 342 break; 343 default: 344 return ARGP_ERR_UNKNOWN; 345 } 346 return 0; 347 } 348 349 350 static char * 351 more_help (int key, const char *text, void *input) 352 { 353 char *buf; 354 355 switch (key) 356 { 357 case ARGP_KEY_HELP_EXTRA: 358 /* We print some extra information. */ 359 if (asprintf (&buf, gettext ("Please report bugs to %s.\n"), 360 PACKAGE_BUGREPORT) < 0) 361 buf = NULL; 362 return buf; 363 364 default: 365 break; 366 } 367 return (char *) text; 368 } 369 370 371 /* Print the version information. */ 372 static void 373 print_version (FILE *stream, struct argp_state *state) 374 { 375 fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, VERSION); 376 fprintf (stream, gettext ("\ 377 Copyright (C) %s Red Hat, Inc.\n\ 378 This is free software; see the source for copying conditions. There is NO\n\ 379 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 380 "), "2004"); 381 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 382 } 383 384 385 /* Process one file. */ 386 static void 387 process_file (int fd, Elf *elf, const char *prefix, const char *fname, 388 bool only_one) 389 { 390 /* We can handle two types of files: ELF files and archives. */ 391 Elf_Kind kind = elf_kind (elf); 392 struct stat64 st; 393 394 switch (kind) 395 { 396 case ELF_K_ELF: 397 /* Yes! It's an ELF file. */ 398 process_elf_file (elf, prefix, fname, only_one); 399 break; 400 401 case ELF_K_AR: 402 { 403 Elf *subelf; 404 Elf_Cmd cmd = ELF_C_READ_MMAP; 405 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 406 size_t fname_len = strlen (fname) + 1; 407 char new_prefix[prefix_len + 1 + fname_len]; 408 char *cp = new_prefix; 409 410 /* Create the full name of the file. */ 411 if (prefix != NULL) 412 { 413 cp = mempcpy (cp, prefix, prefix_len); 414 *cp++ = ':'; 415 } 416 memcpy (cp, fname, fname_len); 417 418 /* It's an archive. We process each file in it. */ 419 while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 420 { 421 kind = elf_kind (subelf); 422 423 /* Call this function recursively. */ 424 if (kind == ELF_K_ELF || kind == ELF_K_AR) 425 { 426 Elf_Arhdr *arhdr = elf_getarhdr (subelf); 427 assert (arhdr != NULL); 428 429 process_file (fd, subelf, new_prefix, arhdr->ar_name, false); 430 } 431 432 /* Get next archive element. */ 433 cmd = elf_next (subelf); 434 if (elf_end (subelf) != 0) 435 error (0, 0, 436 gettext (" error while freeing sub-ELF descriptor: %s\n"), 437 elf_errmsg (-1)); 438 } 439 } 440 break; 441 442 default: 443 if (fstat64 (fd, &st) != 0) 444 error (0, errno, gettext ("cannot stat input file")); 445 else if (st.st_size == 0) 446 error (0, 0, gettext ("input file is empty")); 447 else 448 /* We cannot do anything. */ 449 error (0, 0, gettext ("\ 450 Not an ELF file - it has the wrong magic bytes at the start")); 451 break; 452 } 453 } 454 455 456 /* Process one file. */ 457 static void 458 process_elf_file (Elf *elf, const char *prefix, const char *fname, 459 bool only_one) 460 { 461 GElf_Ehdr ehdr_mem; 462 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 463 Ebl *ebl; 464 465 /* Print the file name. */ 466 if (!only_one) 467 { 468 if (prefix != NULL) 469 printf ("\n%s(%s):\n\n", prefix, fname); 470 else 471 printf ("\n%s:\n\n", fname); 472 } 473 474 if (ehdr == NULL) 475 { 476 error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1)); 477 return; 478 } 479 480 ebl = ebl_openbackend (elf); 481 if (ebl == NULL) 482 { 483 error (0, errno, gettext ("cannot create EBL handle")); 484 return; 485 } 486 487 /* Determine the number of sections. */ 488 if (elf_getshnum (ebl->elf, &shnum) < 0) 489 error (EXIT_FAILURE, 0, 490 gettext ("cannot determine number of sections: %s"), 491 elf_errmsg (-1)); 492 493 if (print_file_header) 494 print_ehdr (ebl, ehdr); 495 if (print_section_header) 496 print_shdr (ebl, ehdr); 497 if (print_program_header) 498 print_phdr (ebl, ehdr); 499 if (print_section_groups) 500 print_scngrp (ebl, ehdr); 501 if (print_dynamic_table) 502 print_dynamic (ebl, ehdr); 503 if (print_relocations) 504 print_relocs (ebl, ehdr); 505 if (print_histogram) 506 handle_hash (ebl, ehdr); 507 if (print_symbol_table) 508 print_symtab (ebl, ehdr, SHT_DYNSYM); 509 if (print_version_info) 510 print_verinfo (ebl, ehdr); 511 if (print_symbol_table) 512 print_symtab (ebl, ehdr, SHT_SYMTAB); 513 if (print_arch) 514 print_liblist (ebl, ehdr); 515 if (print_debug_sections != 0) 516 print_debug (ebl, ehdr); 517 if (print_notes) 518 handle_notes (ebl, ehdr); 519 520 ebl_closebackend (ebl); 521 } 522 523 524 /* Print file type. */ 525 static void 526 print_file_type (unsigned short int e_type) 527 { 528 if (e_type <= ET_CORE) 529 { 530 static const char *knowntypes[] = 531 { 532 N_("NONE (None)"), 533 N_("REL (Relocatable file)"), 534 N_("EXEC (Executable file)"), 535 N_("DYN (Shared object file)"), 536 N_("CORE (Core file)") 537 }; 538 puts (gettext (knowntypes[e_type])); 539 } 540 else if (e_type >= ET_LOOS && e_type <= ET_HIOS) 541 printf (gettext ("OS Specific: (%x)\n"), e_type); 542 else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */) 543 printf (gettext ("Processor Specific: (%x)\n"), e_type); 544 else 545 puts ("???"); 546 } 547 548 549 /* Print ELF header. */ 550 static void 551 print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) 552 { 553 char buf[512]; 554 size_t cnt; 555 556 fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout); 557 for (cnt = 0; cnt < EI_NIDENT; ++cnt) 558 printf (" %02hhx", ehdr->e_ident[cnt]); 559 560 printf (gettext ("\n Class: %s\n"), 561 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32" 562 : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64" 563 : "\?\?\?"); 564 565 printf (gettext (" Data: %s\n"), 566 ehdr->e_ident[EI_DATA] == ELFDATA2LSB 567 ? "2's complement, little endian" 568 : ehdr->e_ident[EI_DATA] == ELFDATA2MSB 569 ? "2's complement, big endian" : "\?\?\?"); 570 571 printf (gettext (" Version: %hhd %s\n"), 572 ehdr->e_ident[EI_VERSION], 573 ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)") 574 : "(\?\?\?)"); 575 576 printf (gettext (" OS/ABI: %s\n"), 577 ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf))); 578 579 printf (gettext (" ABI Version: %hhd\n"), 580 ehdr->e_ident[EI_ABIVERSION]); 581 582 fputs_unlocked (gettext (" Type: "), stdout); 583 print_file_type (ehdr->e_type); 584 585 printf (gettext (" Machine: %s\n"), ebl->name); 586 587 printf (gettext (" Version: %d %s\n"), 588 ehdr->e_version, 589 ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)"); 590 591 printf (gettext (" Entry point address: %#" PRIx64 "\n"), 592 ehdr->e_entry); 593 594 printf (gettext (" Start of program headers: %" PRId64 " %s\n"), 595 ehdr->e_phoff, gettext ("(bytes into file)")); 596 597 printf (gettext (" Start of section headers: %" PRId64 " %s\n"), 598 ehdr->e_shoff, gettext ("(bytes into file)")); 599 600 printf (gettext (" Flags: %s\n"), 601 ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf))); 602 603 printf (gettext (" Size of this header: %" PRId16 " %s\n"), 604 ehdr->e_ehsize, gettext ("(bytes)")); 605 606 printf (gettext (" Size of program header entries: %" PRId16 " %s\n"), 607 ehdr->e_phentsize, gettext ("(bytes)")); 608 609 printf (gettext (" Number of program headers entries: %" PRId16 "\n"), 610 ehdr->e_phnum); 611 612 printf (gettext (" Size of section header entries: %" PRId16 " %s\n"), 613 ehdr->e_shentsize, gettext ("(bytes)")); 614 615 printf (gettext (" Number of section headers entries: %" PRId16), 616 ehdr->e_shnum); 617 if (ehdr->e_shnum == 0) 618 { 619 GElf_Shdr shdr_mem; 620 GElf_Shdr *shdr; 621 622 shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 623 if (shdr != NULL) 624 printf (gettext (" (%" PRIu32 " in [0].sh_size)"), 625 (uint32_t) shdr->sh_size); 626 else 627 fputs_unlocked (gettext (" ([0] not available)"), stdout); 628 } 629 fputc_unlocked ('\n', stdout); 630 631 if (ehdr->e_shstrndx == SHN_XINDEX) 632 { 633 GElf_Shdr shdr_mem; 634 GElf_Shdr *shdr; 635 636 shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 637 if (shdr != NULL) 638 /* We managed to get the zeroth section. */ 639 snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"), 640 (uint32_t) shdr->sh_link); 641 else 642 { 643 strncpy (buf, gettext (" ([0] not available)"), sizeof (buf)); 644 buf[sizeof (buf) - 1] = '\0'; 645 } 646 647 printf (gettext (" Section header string table index: XINDEX%s\n\n"), 648 buf); 649 } 650 else 651 printf (gettext (" Section header string table index: %" PRId16 "\n\n"), 652 ehdr->e_shstrndx); 653 } 654 655 656 static const char * 657 get_visibility_type (int value) 658 { 659 switch (value) 660 { 661 case STV_DEFAULT: 662 return "DEFAULT"; 663 case STV_INTERNAL: 664 return "INTERNAL"; 665 case STV_HIDDEN: 666 return "HIDDEN"; 667 case STV_PROTECTED: 668 return "PROTECTED"; 669 default: 670 return "???"; 671 } 672 } 673 674 675 /* Print the section headers. */ 676 static void 677 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr) 678 { 679 size_t cnt; 680 size_t shstrndx; 681 682 if (! print_file_header) 683 printf (gettext ("\ 684 There are %d section headers, starting at offset %#" PRIx64 ":\n\ 685 \n"), 686 ehdr->e_shnum, ehdr->e_shoff); 687 688 /* Get the section header string table index. */ 689 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 690 error (EXIT_FAILURE, 0, 691 gettext ("cannot get section header string table index")); 692 693 puts (gettext ("Section Headers:")); 694 695 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 696 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al")); 697 else 698 puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al")); 699 700 for (cnt = 0; cnt < shnum; ++cnt) 701 { 702 char buf[128]; 703 char flagbuf[20]; 704 char *cp; 705 Elf_Scn *scn = elf_getscn (ebl->elf, cnt); 706 GElf_Shdr shdr_mem; 707 GElf_Shdr *shdr; 708 709 if (scn == NULL) 710 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"), 711 elf_errmsg (-1)); 712 713 /* Get the section header. */ 714 shdr = gelf_getshdr (scn, &shdr_mem); 715 if (shdr == NULL) 716 error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"), 717 elf_errmsg (-1)); 718 719 cp = flagbuf; 720 if (shdr->sh_flags & SHF_WRITE) 721 *cp++ = 'W'; 722 if (shdr->sh_flags & SHF_ALLOC) 723 *cp++ = 'A'; 724 if (shdr->sh_flags & SHF_EXECINSTR) 725 *cp++ = 'X'; 726 if (shdr->sh_flags & SHF_MERGE) 727 *cp++ = 'M'; 728 if (shdr->sh_flags & SHF_STRINGS) 729 *cp++ = 'S'; 730 if (shdr->sh_flags & SHF_INFO_LINK) 731 *cp++ = 'I'; 732 if (shdr->sh_flags & SHF_LINK_ORDER) 733 *cp++ = 'L'; 734 if (shdr->sh_flags & SHF_OS_NONCONFORMING) 735 *cp++ = 'N'; 736 if (shdr->sh_flags & SHF_GROUP) 737 *cp++ = 'G'; 738 if (shdr->sh_flags & SHF_TLS) 739 *cp++ = 'T'; 740 if (shdr->sh_flags & SHF_ORDERED) 741 *cp++ = 'O'; 742 if (shdr->sh_flags & SHF_EXCLUDE) 743 *cp++ = 'E'; 744 *cp = '\0'; 745 746 printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64 747 " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32 748 " %2" PRId64 "\n", 749 cnt, 750 elf_strptr (ebl->elf, shstrndx, shdr->sh_name) 751 ?: "<corrupt>", 752 ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)), 753 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr, 754 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset, 755 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size, 756 shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info, 757 shdr->sh_addralign); 758 } 759 760 fputc_unlocked ('\n', stdout); 761 } 762 763 764 /* Print the program header. */ 765 static void 766 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) 767 { 768 size_t cnt; 769 size_t shstrndx; 770 771 if (ehdr->e_phnum == 0) 772 /* No program header, this is OK in relocatable objects. */ 773 return; 774 775 puts (gettext ("Program Headers:")); 776 if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) 777 puts (gettext ("\ 778 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align")); 779 else 780 puts (gettext ("\ 781 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align")); 782 783 /* Process all program headers. */ 784 bool has_relro = false; 785 GElf_Addr relro_from = 0; 786 GElf_Addr relro_to = 0; 787 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) 788 { 789 char buf[128]; 790 GElf_Phdr mem; 791 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem); 792 793 /* If for some reason the header cannot be returned show this. */ 794 if (phdr == NULL) 795 { 796 puts (" ???"); 797 continue; 798 } 799 800 printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64 801 " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n", 802 ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)), 803 phdr->p_offset, 804 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr, 805 ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr, 806 phdr->p_filesz, 807 phdr->p_memsz, 808 phdr->p_flags & PF_R ? 'R' : ' ', 809 phdr->p_flags & PF_W ? 'W' : ' ', 810 phdr->p_flags & PF_X ? 'E' : ' ', 811 phdr->p_align); 812 813 if (phdr->p_type == PT_INTERP) 814 { 815 /* We can show the user the name of the interpreter. */ 816 size_t maxsize; 817 char *filedata = elf_rawfile (ebl->elf, &maxsize); 818 819 if (filedata != NULL && phdr->p_offset < maxsize) 820 printf (gettext ("\t[Requesting program interpreter: %s]\n"), 821 filedata + phdr->p_offset); 822 } 823 else if (phdr->p_type == PT_GNU_RELRO) 824 { 825 has_relro = true; 826 relro_from = phdr->p_vaddr; 827 relro_to = relro_from + phdr->p_memsz; 828 } 829 } 830 831 /* Get the section header string table index. */ 832 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 833 error (EXIT_FAILURE, 0, 834 gettext ("cannot get section header string table index")); 835 836 puts (gettext ("\n Section to Segment mapping:\n Segment Sections...")); 837 838 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) 839 { 840 GElf_Phdr phdr_mem; 841 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem); 842 size_t inner; 843 844 /* Print the segment number. */ 845 printf (" %2.2zu ", cnt); 846 847 /* This must not happen. */ 848 if (phdr == NULL) 849 error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"), 850 elf_errmsg (-1)); 851 852 /* Iterate over the sections. */ 853 bool in_relro = false; 854 for (inner = 1; inner < shnum; ++inner) 855 { 856 Elf_Scn *scn = elf_getscn (ebl->elf, inner); 857 GElf_Shdr shdr_mem; 858 GElf_Shdr *shdr; 859 860 /* It should not happen. */ 861 if (scn == NULL) 862 error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"), 863 elf_errmsg (-1)); 864 865 /* Get the section header. */ 866 shdr = gelf_getshdr (scn, &shdr_mem); 867 if (shdr == NULL) 868 error (EXIT_FAILURE, 0, 869 gettext ("cannot get section header: %s"), 870 elf_errmsg (-1)); 871 872 if (shdr->sh_size > 0 873 /* Compare allocated sections by VMA, unallocated 874 sections by file offset. */ 875 && (shdr->sh_flags & SHF_ALLOC 876 ? (shdr->sh_addr >= phdr->p_vaddr 877 && (shdr->sh_addr + shdr->sh_size 878 <= phdr->p_vaddr + phdr->p_memsz)) 879 : (shdr->sh_offset >= phdr->p_offset 880 && (shdr->sh_offset + shdr->sh_size 881 <= phdr->p_offset + phdr->p_filesz)))) 882 { 883 if (has_relro && !in_relro 884 && shdr->sh_addr >= relro_from 885 && shdr->sh_addr + shdr->sh_size <= relro_to) 886 { 887 fputs_unlocked (" [RELRO:", stdout); 888 in_relro = true; 889 } 890 else if (has_relro && in_relro && shdr->sh_addr >= relro_to) 891 { 892 fputs_unlocked ("]", stdout); 893 in_relro = false; 894 } 895 else if (has_relro && in_relro 896 && shdr->sh_addr + shdr->sh_size > relro_to) 897 fputs_unlocked ("] <RELRO:", stdout); 898 899 printf (" %s", 900 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 901 902 /* Signal that this sectin is only partially covered. */ 903 if (has_relro && in_relro 904 && shdr->sh_addr + shdr->sh_size > relro_to) 905 { 906 fputs_unlocked (">", stdout); 907 in_relro = false; 908 } 909 } 910 } 911 if (in_relro) 912 fputs_unlocked ("]", stdout); 913 914 /* Finish the line. */ 915 fputc_unlocked ('\n', stdout); 916 } 917 } 918 919 920 static void 921 handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 922 { 923 Elf_Data *data; 924 Elf32_Word *grpref; 925 Elf_Scn *symscn; 926 GElf_Shdr symshdr_mem; 927 GElf_Shdr *symshdr; 928 Elf_Data *symdata; 929 GElf_Sym sym_mem; 930 size_t cnt; 931 size_t shstrndx; 932 933 /* Get the data of the section. */ 934 data = elf_getdata (scn, NULL); 935 936 symscn = elf_getscn (ebl->elf, shdr->sh_link); 937 symshdr = gelf_getshdr (symscn, &symshdr_mem); 938 symdata = elf_getdata (symscn, NULL); 939 940 if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL 941 || symdata == NULL) 942 return; 943 944 /* Get the section header string table index. */ 945 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 946 error (EXIT_FAILURE, 0, 947 gettext ("cannot get section header string table index")); 948 949 grpref = (Elf32_Word *) data->d_buf; 950 951 printf ((grpref[0] & GRP_COMDAT) 952 ? ngettext ("\ 953 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n", 954 "\ 955 \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n", 956 data->d_size / sizeof (Elf32_Word) - 1) 957 : ngettext ("\ 958 \nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\ 959 \nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n", 960 data->d_size / sizeof (Elf32_Word) - 1), 961 elf_ndxscn (scn), 962 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 963 elf_strptr (ebl->elf, symshdr->sh_link, 964 gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name) 965 ?: gettext ("<INVALID SYMBOL>"), 966 data->d_size / sizeof (Elf32_Word) - 1); 967 968 for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt) 969 { 970 GElf_Shdr grpshdr_mem; 971 GElf_Shdr *grpshdr; 972 973 grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]), 974 &grpshdr_mem); 975 976 if (grpshdr == NULL) 977 printf (gettext (" [%2u] <INVALID SECTION>\n"), grpref[cnt]); 978 else 979 printf (" [%2u] %s\n", 980 grpref[cnt], 981 elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name) 982 ?: gettext ("<INVALID SECTION>")); 983 } 984 } 985 986 987 static void 988 print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr) 989 { 990 /* Find all relocation sections and handle them. */ 991 Elf_Scn *scn = NULL; 992 993 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 994 { 995 /* Handle the section if it is a symbol table. */ 996 GElf_Shdr shdr_mem; 997 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 998 999 if (shdr != NULL && shdr->sh_type == SHT_GROUP) 1000 handle_scngrp (ebl, ehdr, scn, shdr); 1001 } 1002 } 1003 1004 1005 static const struct flags 1006 { 1007 int mask; 1008 const char *str; 1009 } dt_flags[] = 1010 { 1011 { DF_ORIGIN, "ORIGIN" }, 1012 { DF_SYMBOLIC, "SYMBOLIC" }, 1013 { DF_TEXTREL, "TEXTREL" }, 1014 { DF_BIND_NOW, "BIND_NOW" }, 1015 { DF_STATIC_TLS, "STATIC_TLS" } 1016 }; 1017 static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]); 1018 1019 static const struct flags dt_flags_1[] = 1020 { 1021 { DF_1_NOW, "NOW" }, 1022 { DF_1_GLOBAL, "GLOBAL" }, 1023 { DF_1_GROUP, "GROUP" }, 1024 { DF_1_NODELETE, "NODELETE" }, 1025 { DF_1_LOADFLTR, "LOADFLTR" }, 1026 { DF_1_INITFIRST, "INITFIRST" }, 1027 { DF_1_NOOPEN, "NOOPEN" }, 1028 { DF_1_ORIGIN, "ORIGIN" }, 1029 { DF_1_DIRECT, "DIRECT" }, 1030 { DF_1_TRANS, "TRANS" }, 1031 { DF_1_INTERPOSE, "INTERPOSE" }, 1032 { DF_1_NODEFLIB, "NODEFLIB" }, 1033 { DF_1_NODUMP, "NODUMP" }, 1034 { DF_1_CONFALT, "CONFALT" }, 1035 { DF_1_ENDFILTEE, "ENDFILTEE" }, 1036 { DF_1_DISPRELDNE, "DISPRELDNE" }, 1037 { DF_1_DISPRELPND, "DISPRELPND" }, 1038 }; 1039 static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]); 1040 1041 static const struct flags dt_feature_1[] = 1042 { 1043 { DTF_1_PARINIT, "PARINIT" }, 1044 { DTF_1_CONFEXP, "CONFEXP" } 1045 }; 1046 static const int ndt_feature_1 = (sizeof (dt_feature_1) 1047 / sizeof (dt_feature_1[0])); 1048 1049 static const struct flags dt_posflag_1[] = 1050 { 1051 { DF_P1_LAZYLOAD, "LAZYLOAD" }, 1052 { DF_P1_GROUPPERM, "GROUPPERM" } 1053 }; 1054 static const int ndt_posflag_1 = (sizeof (dt_posflag_1) 1055 / sizeof (dt_posflag_1[0])); 1056 1057 1058 static void 1059 print_flags (int class, GElf_Xword d_val, const struct flags *flags, 1060 int nflags) 1061 { 1062 bool first = true; 1063 int cnt; 1064 1065 for (cnt = 0; cnt < nflags; ++cnt) 1066 if (d_val & flags[cnt].mask) 1067 { 1068 if (!first) 1069 putchar_unlocked (' '); 1070 fputs_unlocked (flags[cnt].str, stdout); 1071 d_val &= ~flags[cnt].mask; 1072 first = false; 1073 } 1074 1075 if (d_val != 0) 1076 { 1077 if (!first) 1078 putchar_unlocked (' '); 1079 printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val); 1080 } 1081 1082 putchar_unlocked ('\n'); 1083 } 1084 1085 1086 static void 1087 print_dt_flags (int class, GElf_Xword d_val) 1088 { 1089 print_flags (class, d_val, dt_flags, ndt_flags); 1090 } 1091 1092 1093 static void 1094 print_dt_flags_1 (int class, GElf_Xword d_val) 1095 { 1096 print_flags (class, d_val, dt_flags_1, ndt_flags_1); 1097 } 1098 1099 1100 static void 1101 print_dt_feature_1 (int class, GElf_Xword d_val) 1102 { 1103 print_flags (class, d_val, dt_feature_1, ndt_feature_1); 1104 } 1105 1106 1107 static void 1108 print_dt_posflag_1 (int class, GElf_Xword d_val) 1109 { 1110 print_flags (class, d_val, dt_posflag_1, ndt_posflag_1); 1111 } 1112 1113 1114 static void 1115 handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 1116 { 1117 int class = gelf_getclass (ebl->elf); 1118 GElf_Shdr glink; 1119 Elf_Data *data; 1120 size_t cnt; 1121 size_t shstrndx; 1122 1123 /* Get the data of the section. */ 1124 data = elf_getdata (scn, NULL); 1125 if (data == NULL) 1126 return; 1127 1128 /* Get the section header string table index. */ 1129 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 1130 error (EXIT_FAILURE, 0, 1131 gettext ("cannot get section header string table index")); 1132 1133 printf (ngettext ("\ 1134 \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 1135 "\ 1136 \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 1137 shdr->sh_size / shdr->sh_entsize), 1138 (unsigned long int) (shdr->sh_size / shdr->sh_entsize), 1139 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 1140 shdr->sh_offset, 1141 (int) shdr->sh_link, 1142 elf_strptr (ebl->elf, shstrndx, 1143 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 1144 &glink)->sh_name)); 1145 fputs_unlocked (gettext (" Type Value\n"), stdout); 1146 1147 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 1148 { 1149 char buf[64]; 1150 GElf_Dyn dynmem; 1151 GElf_Dyn *dyn; 1152 1153 dyn = gelf_getdyn (data, cnt, &dynmem); 1154 if (dyn == NULL) 1155 break; 1156 1157 printf (" %-17s ", 1158 ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf))); 1159 1160 switch (dyn->d_tag) 1161 { 1162 case DT_NULL: 1163 case DT_DEBUG: 1164 case DT_BIND_NOW: 1165 case DT_TEXTREL: 1166 /* No further output. */ 1167 fputc ('\n', stdout); 1168 break; 1169 1170 case DT_NEEDED: 1171 printf (gettext ("Shared library: [%s]\n"), 1172 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1173 break; 1174 1175 case DT_SONAME: 1176 printf (gettext ("Library soname: [%s]\n"), 1177 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1178 break; 1179 1180 case DT_RPATH: 1181 printf (gettext ("Library rpath: [%s]\n"), 1182 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1183 break; 1184 1185 case DT_RUNPATH: 1186 printf (gettext ("Library runpath: [%s]\n"), 1187 elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val)); 1188 break; 1189 1190 case DT_PLTRELSZ: 1191 case DT_RELASZ: 1192 case DT_STRSZ: 1193 case DT_RELSZ: 1194 case DT_RELAENT: 1195 case DT_SYMENT: 1196 case DT_RELENT: 1197 case DT_PLTPADSZ: 1198 case DT_MOVEENT: 1199 case DT_MOVESZ: 1200 case DT_INIT_ARRAYSZ: 1201 case DT_FINI_ARRAYSZ: 1202 case DT_SYMINSZ: 1203 case DT_SYMINENT: 1204 case DT_GNU_CONFLICTSZ: 1205 case DT_GNU_LIBLISTSZ: 1206 printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val); 1207 break; 1208 1209 case DT_VERDEFNUM: 1210 case DT_VERNEEDNUM: 1211 case DT_RELACOUNT: 1212 case DT_RELCOUNT: 1213 printf ("%" PRId64 "\n", dyn->d_un.d_val); 1214 break; 1215 1216 case DT_PLTREL: 1217 puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0)); 1218 break; 1219 1220 case DT_FLAGS: 1221 print_dt_flags (class, dyn->d_un.d_val); 1222 break; 1223 1224 case DT_FLAGS_1: 1225 print_dt_flags_1 (class, dyn->d_un.d_val); 1226 break; 1227 1228 case DT_FEATURE_1: 1229 print_dt_feature_1 (class, dyn->d_un.d_val); 1230 break; 1231 1232 case DT_POSFLAG_1: 1233 print_dt_posflag_1 (class, dyn->d_un.d_val); 1234 break; 1235 1236 default: 1237 printf ("%#0*" PRIx64 "\n", 1238 class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val); 1239 break; 1240 } 1241 } 1242 } 1243 1244 1245 /* Print the dynamic segment. */ 1246 static void 1247 print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr) 1248 { 1249 /* Find all relocation sections and handle them. */ 1250 Elf_Scn *scn = NULL; 1251 1252 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1253 { 1254 /* Handle the section if it is a symbol table. */ 1255 GElf_Shdr shdr_mem; 1256 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1257 1258 if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC) 1259 { 1260 handle_dynamic (ebl, ehdr, scn, shdr); 1261 break; 1262 } 1263 } 1264 } 1265 1266 1267 /* Print relocations. */ 1268 static void 1269 print_relocs (Ebl *ebl, GElf_Ehdr *ehdr) 1270 { 1271 /* Find all relocation sections and handle them. */ 1272 Elf_Scn *scn = NULL; 1273 1274 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1275 { 1276 /* Handle the section if it is a symbol table. */ 1277 GElf_Shdr shdr_mem; 1278 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1279 1280 if (shdr != NULL) 1281 { 1282 if (shdr->sh_type == SHT_REL) 1283 handle_relocs_rel (ebl, ehdr, scn, shdr); 1284 else if (shdr->sh_type == SHT_RELA) 1285 handle_relocs_rela (ebl, ehdr, scn, shdr); 1286 } 1287 } 1288 } 1289 1290 1291 /* Handle a relocation section. */ 1292 static void 1293 handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 1294 { 1295 int class = gelf_getclass (ebl->elf); 1296 int nentries = shdr->sh_size / shdr->sh_entsize; 1297 int cnt; 1298 Elf_Data *data; 1299 Elf_Scn *symscn; 1300 GElf_Shdr symshdr_mem; 1301 GElf_Shdr *symshdr; 1302 Elf_Data *symdata; 1303 GElf_Shdr destshdr_mem; 1304 GElf_Shdr *destshdr; 1305 Elf_Scn *xndxscn; 1306 Elf_Data *xndxdata = NULL; 1307 size_t shstrndx; 1308 1309 /* Get the data of the section. */ 1310 data = elf_getdata (scn, NULL); 1311 if (data == NULL) 1312 return; 1313 1314 /* Get the symbol table information. */ 1315 symscn = elf_getscn (ebl->elf, shdr->sh_link); 1316 symshdr = gelf_getshdr (symscn, &symshdr_mem); 1317 symdata = elf_getdata (symscn, NULL); 1318 1319 /* Get the section header of the section the relocations are for. */ 1320 destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), 1321 &destshdr_mem); 1322 1323 if (symshdr == NULL || symdata == NULL || destshdr == NULL) 1324 { 1325 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"), 1326 shdr->sh_offset); 1327 return; 1328 } 1329 1330 /* Search for the optional extended section index table. */ 1331 xndxscn = NULL; 1332 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL) 1333 { 1334 GElf_Shdr xndxshdr_mem; 1335 GElf_Shdr *xndxshdr; 1336 1337 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 1338 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX 1339 && xndxshdr->sh_link == elf_ndxscn (symscn)) 1340 { 1341 /* Found it. */ 1342 xndxdata = elf_getdata (xndxscn, NULL); 1343 break; 1344 } 1345 } 1346 1347 /* Get the section header string table index. */ 1348 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 1349 error (EXIT_FAILURE, 0, 1350 gettext ("cannot get section header string table index")); 1351 1352 if (shdr->sh_info != 0) 1353 printf (ngettext ("\ 1354 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 1355 "\ 1356 \nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 1357 nentries), 1358 (unsigned int) elf_ndxscn (scn), 1359 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1360 (unsigned int) shdr->sh_info, 1361 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 1362 shdr->sh_offset, 1363 nentries); 1364 else 1365 /* The .rel.dyn section does not refer to a specific section but 1366 instead of section index zero. Do not try to print a section 1367 name. */ 1368 printf (ngettext ("\ 1369 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 1370 "\ 1371 \nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 1372 nentries), 1373 (unsigned int) elf_ndxscn (scn), 1374 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1375 shdr->sh_offset, 1376 nentries); 1377 fputs_unlocked (class == ELFCLASS32 1378 ? gettext ("\ 1379 Offset Type Value Name\n") 1380 : gettext ("\ 1381 Offset Type Value Name\n"), 1382 stdout); 1383 1384 for (cnt = 0; cnt < nentries; ++cnt) 1385 { 1386 GElf_Rel relmem; 1387 GElf_Rel *rel; 1388 1389 rel = gelf_getrel (data, cnt, &relmem); 1390 if (rel != NULL) 1391 { 1392 char buf[128]; 1393 GElf_Sym symmem; 1394 GElf_Sym *sym; 1395 Elf32_Word xndx; 1396 1397 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info), 1398 &symmem, &xndx); 1399 if (sym == NULL) 1400 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", 1401 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1402 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1403 /* Avoid the leading R_ which isn't carrying any 1404 information. */ 1405 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1406 buf, sizeof (buf)) + 2 1407 : gettext ("<INVALID RELOC>"), 1408 gettext ("INVALID SYMBOL"), 1409 (long int) GELF_R_SYM (rel->r_info)); 1410 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 1411 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", 1412 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1413 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1414 /* Avoid the leading R_ which isn't carrying any 1415 information. */ 1416 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1417 buf, sizeof (buf)) + 2 1418 : gettext ("<INVALID RELOC>"), 1419 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1420 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); 1421 else 1422 { 1423 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 1424 sym->st_shndx == SHN_XINDEX 1425 ? xndx : sym->st_shndx), 1426 &destshdr_mem); 1427 1428 if (shdr == NULL) 1429 printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", 1430 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1431 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1432 /* Avoid the leading R_ which isn't carrying any 1433 information. */ 1434 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1435 buf, sizeof (buf)) + 2 1436 : gettext ("<INVALID RELOC>"), 1437 gettext ("INVALID SECTION"), 1438 (long int) (sym->st_shndx == SHN_XINDEX 1439 ? xndx : sym->st_shndx)); 1440 else 1441 printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", 1442 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1443 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1444 /* Avoid the leading R_ which isn't carrying any 1445 information. */ 1446 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1447 buf, sizeof (buf)) + 2 1448 : gettext ("<INVALID RELOC>"), 1449 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1450 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 1451 } 1452 } 1453 } 1454 } 1455 1456 1457 /* Handle a relocation section. */ 1458 static void 1459 handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 1460 { 1461 int class = gelf_getclass (ebl->elf); 1462 int nentries = shdr->sh_size / shdr->sh_entsize; 1463 1464 /* Get the data of the section. */ 1465 Elf_Data *data = elf_getdata (scn, NULL); 1466 if (data == NULL) 1467 return; 1468 1469 /* Get the symbol table information. */ 1470 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1471 GElf_Shdr symshdr_mem; 1472 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1473 Elf_Data *symdata = elf_getdata (symscn, NULL); 1474 1475 /* Get the section header of the section the relocations are for. */ 1476 GElf_Shdr destshdr_mem; 1477 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), 1478 &destshdr_mem); 1479 1480 if (symshdr == NULL || symdata == NULL || destshdr == NULL) 1481 { 1482 printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"), 1483 shdr->sh_offset); 1484 return; 1485 } 1486 1487 /* Search for the optional extended section index table. */ 1488 Elf_Data *xndxdata = NULL; 1489 Elf_Scn *xndxscn = NULL; 1490 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL) 1491 { 1492 GElf_Shdr xndxshdr_mem; 1493 GElf_Shdr *xndxshdr; 1494 1495 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 1496 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX 1497 && xndxshdr->sh_link == elf_ndxscn (symscn)) 1498 { 1499 /* Found it. */ 1500 xndxdata = elf_getdata (xndxscn, NULL); 1501 break; 1502 } 1503 } 1504 1505 /* Get the section header string table index. */ 1506 size_t shstrndx; 1507 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 1508 error (EXIT_FAILURE, 0, 1509 gettext ("cannot get section header string table index")); 1510 1511 printf (ngettext ("\ 1512 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 1513 "\ 1514 \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 1515 nentries), 1516 elf_ndxscn (scn), 1517 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 1518 (unsigned int) shdr->sh_info, 1519 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 1520 shdr->sh_offset, 1521 nentries); 1522 fputs_unlocked (class == ELFCLASS32 1523 ? gettext ("\ 1524 Offset Type Value Addend Name\n") 1525 : gettext ("\ 1526 Offset Type Value Addend Name\n"), 1527 stdout); 1528 1529 for (int cnt = 0; cnt < nentries; ++cnt) 1530 { 1531 GElf_Rela relmem; 1532 GElf_Rela *rel = gelf_getrela (data, cnt, &relmem); 1533 if (rel != NULL) 1534 { 1535 char buf[64]; 1536 GElf_Sym symmem; 1537 GElf_Sym *sym; 1538 Elf32_Word xndx; 1539 1540 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info), 1541 &symmem, &xndx); 1542 1543 if (sym == NULL) 1544 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", 1545 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1546 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1547 /* Avoid the leading R_ which isn't carrying any 1548 information. */ 1549 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1550 buf, sizeof (buf)) + 2 1551 : gettext ("<INVALID RELOC>"), 1552 gettext ("INVALID SYMBOL"), 1553 (long int) GELF_R_SYM (rel->r_info)); 1554 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 1555 printf ("\ 1556 %#0*" PRIx64 " %-15s %#0*" PRIx64 " +%5" PRId64 " %s\n", 1557 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1558 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1559 /* Avoid the leading R_ which isn't carrying any 1560 information. */ 1561 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1562 buf, sizeof (buf)) + 2 1563 : gettext ("<INVALID RELOC>"), 1564 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1565 rel->r_addend, 1566 elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); 1567 else 1568 { 1569 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 1570 sym->st_shndx == SHN_XINDEX 1571 ? xndx : sym->st_shndx), 1572 &destshdr_mem); 1573 1574 if (shdr == NULL) 1575 printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", 1576 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1577 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1578 /* Avoid the leading R_ which isn't carrying any 1579 information. */ 1580 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1581 buf, sizeof (buf)) + 2 1582 : gettext ("<INVALID RELOC>"), 1583 gettext ("INVALID SECTION"), 1584 (long int) (sym->st_shndx == SHN_XINDEX 1585 ? xndx : sym->st_shndx)); 1586 else 1587 printf ("\ 1588 %#0*" PRIx64 " %-15s %#0*" PRIx64 " +%5" PRId64 " %s\n", 1589 class == ELFCLASS32 ? 10 : 18, rel->r_offset, 1590 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 1591 /* Avoid the leading R_ which isn't carrying any 1592 information. */ 1593 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 1594 buf, sizeof (buf)) + 2 1595 : gettext ("<INVALID RELOC>"), 1596 class == ELFCLASS32 ? 10 : 18, sym->st_value, 1597 rel->r_addend, 1598 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 1599 } 1600 } 1601 } 1602 } 1603 1604 1605 /* Print the program header. */ 1606 static void 1607 print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type) 1608 { 1609 /* Find the symbol table(s). For this we have to search through the 1610 section table. */ 1611 Elf_Scn *scn = NULL; 1612 1613 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1614 { 1615 /* Handle the section if it is a symbol table. */ 1616 GElf_Shdr shdr_mem; 1617 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1618 1619 if (shdr != NULL && shdr->sh_type == (GElf_Word) type) 1620 handle_symtab (ebl, ehdr, scn, shdr); 1621 } 1622 } 1623 1624 1625 static void 1626 handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 1627 { 1628 Elf_Data *versym_data = NULL; 1629 Elf_Data *verneed_data = NULL; 1630 Elf_Data *verdef_data = NULL; 1631 Elf_Data *xndx_data = NULL; 1632 Elf_Scn *runscn; 1633 Elf_Data *data; 1634 int class = gelf_getclass (ebl->elf); 1635 unsigned int nsyms; 1636 unsigned int cnt; 1637 Elf32_Word verneed_stridx = 0; 1638 Elf32_Word verdef_stridx = 0; 1639 GElf_Shdr glink; 1640 size_t shstrndx; 1641 1642 /* Get the data of the section. */ 1643 data = elf_getdata (scn, NULL); 1644 if (data == NULL) 1645 return; 1646 1647 /* Find out whether we have other sections we might need. */ 1648 runscn = NULL; 1649 while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL) 1650 { 1651 GElf_Shdr runshdr_mem; 1652 GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem); 1653 1654 if (runshdr != NULL) 1655 { 1656 if (runshdr->sh_type == SHT_GNU_versym 1657 && runshdr->sh_link == elf_ndxscn (scn)) 1658 /* Bingo, found the version information. Now get the data. */ 1659 versym_data = elf_getdata (runscn, NULL); 1660 else if (runshdr->sh_type == SHT_GNU_verneed) 1661 { 1662 /* This is the information about the needed versions. */ 1663 verneed_data = elf_getdata (runscn, NULL); 1664 verneed_stridx = runshdr->sh_link; 1665 } 1666 else if (runshdr->sh_type == SHT_GNU_verdef) 1667 { 1668 /* This is the information about the defined versions. */ 1669 verdef_data = elf_getdata (runscn, NULL); 1670 verdef_stridx = runshdr->sh_link; 1671 } 1672 else if (runshdr->sh_type == SHT_SYMTAB_SHNDX 1673 && runshdr->sh_link == elf_ndxscn (scn)) 1674 /* Extended section index. */ 1675 xndx_data = elf_getdata (runscn, NULL); 1676 } 1677 } 1678 1679 /* Get the section header string table index. */ 1680 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 1681 error (EXIT_FAILURE, 0, 1682 gettext ("cannot get section header string table index")); 1683 1684 /* Now we can compute the number of entries in the section. */ 1685 nsyms = data->d_size / (class == ELFCLASS32 1686 ? sizeof (Elf32_Sym) : sizeof (Elf64_Sym)); 1687 1688 printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n", 1689 "\nSymbol table [%2u] '%s' contains %u entries:\n", 1690 nsyms), 1691 (unsigned int) elf_ndxscn (scn), 1692 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms); 1693 printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n", 1694 " %lu local symbols String table: [%2u] '%s'\n", 1695 shdr->sh_info), 1696 (unsigned long int) shdr->sh_info, 1697 (unsigned int) shdr->sh_link, 1698 elf_strptr (ebl->elf, shstrndx, 1699 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 1700 &glink)->sh_name)); 1701 1702 fputs_unlocked (class == ELFCLASS32 1703 ? gettext ("\ 1704 Num: Value Size Type Bind Vis Ndx Name\n") 1705 : gettext ("\ 1706 Num: Value Size Type Bind Vis Ndx Name\n"), 1707 stdout); 1708 1709 for (cnt = 0; cnt < nsyms; ++cnt) 1710 { 1711 char typebuf[64]; 1712 char bindbuf[64]; 1713 char scnbuf[64]; 1714 Elf32_Word xndx; 1715 GElf_Sym sym_mem; 1716 GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx); 1717 1718 if (sym == NULL) 1719 continue; 1720 1721 /* Determine the real section index. */ 1722 if (sym->st_shndx != SHN_XINDEX) 1723 xndx = sym->st_shndx; 1724 1725 printf (gettext ("\ 1726 %5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"), 1727 cnt, 1728 class == ELFCLASS32 ? 8 : 16, 1729 sym->st_value, 1730 sym->st_size, 1731 ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), 1732 typebuf, sizeof (typebuf)), 1733 ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), 1734 bindbuf, sizeof (bindbuf)), 1735 get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)), 1736 ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf, 1737 sizeof (scnbuf), NULL, shnum), 1738 elf_strptr (ebl->elf, shdr->sh_link, sym->st_name)); 1739 1740 if (versym_data != NULL) 1741 { 1742 /* Get the version information. */ 1743 GElf_Versym versym_mem; 1744 GElf_Versym *versym; 1745 1746 versym = gelf_getversym (versym_data, cnt, &versym_mem); 1747 1748 if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1)) 1749 { 1750 bool is_nobits = false; 1751 bool check_def = xndx != SHN_UNDEF; 1752 1753 if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX) 1754 { 1755 GElf_Shdr symshdr_mem; 1756 GElf_Shdr *symshdr = 1757 gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem); 1758 1759 is_nobits = (symshdr != NULL 1760 && symshdr->sh_type == SHT_NOBITS); 1761 } 1762 1763 if (is_nobits || ! check_def) 1764 { 1765 /* We must test both. */ 1766 GElf_Verneed verneed_mem; 1767 GElf_Verneed *verneed; 1768 GElf_Vernaux vernaux_mem; 1769 GElf_Vernaux *vernaux = NULL; 1770 size_t vn_offset = 0; 1771 1772 verneed = gelf_getverneed (verneed_data, 0, &verneed_mem); 1773 while (verneed != NULL) 1774 { 1775 size_t vna_offset = vn_offset; 1776 1777 vernaux = gelf_getvernaux (verneed_data, 1778 vna_offset += verneed->vn_aux, 1779 &vernaux_mem); 1780 while (vernaux != NULL 1781 && vernaux->vna_other != *versym 1782 && vernaux->vna_next != 0) 1783 { 1784 /* Update the offset. */ 1785 vna_offset += vernaux->vna_next; 1786 1787 vernaux = (vernaux->vna_next == 0 1788 ? NULL 1789 : gelf_getvernaux (verneed_data, 1790 vna_offset, 1791 &vernaux_mem)); 1792 } 1793 1794 /* Check whether we found the version. */ 1795 if (vernaux != NULL && vernaux->vna_other == *versym) 1796 /* Found it. */ 1797 break; 1798 1799 vn_offset += verneed->vn_next; 1800 verneed = (verneed->vn_next == 0 1801 ? NULL 1802 : gelf_getverneed (verneed_data, vn_offset, 1803 &verneed_mem)); 1804 } 1805 1806 if (vernaux != NULL && vernaux->vna_other == *versym) 1807 { 1808 printf ("@%s (%u)", 1809 elf_strptr (ebl->elf, verneed_stridx, 1810 vernaux->vna_name), 1811 (unsigned int) vernaux->vna_other); 1812 check_def = 0; 1813 } 1814 else if (! is_nobits) 1815 error (0, 0, gettext ("bad dynamic symbol")); 1816 else 1817 check_def = 1; 1818 } 1819 1820 if (check_def && *versym != 0x8001) 1821 { 1822 /* We must test both. */ 1823 GElf_Verdef verdef_mem; 1824 GElf_Verdef *verdef; 1825 size_t vd_offset = 0; 1826 1827 verdef = gelf_getverdef (verdef_data, 0, &verdef_mem); 1828 while (verdef != NULL) 1829 { 1830 if (verdef->vd_ndx == (*versym & 0x7fff)) 1831 /* Found the definition. */ 1832 break; 1833 1834 vd_offset += verdef->vd_next; 1835 verdef = (verdef->vd_next == 0 1836 ? NULL 1837 : gelf_getverdef (verdef_data, vd_offset, 1838 &verdef_mem)); 1839 } 1840 1841 if (verdef != NULL) 1842 { 1843 GElf_Verdaux verdaux_mem; 1844 GElf_Verdaux *verdaux; 1845 1846 verdaux = gelf_getverdaux (verdef_data, 1847 vd_offset + verdef->vd_aux, 1848 &verdaux_mem); 1849 1850 if (verdaux != NULL) 1851 printf ((*versym & 0x8000) ? "@%s" : "@@%s", 1852 elf_strptr (ebl->elf, verdef_stridx, 1853 verdaux->vda_name)); 1854 } 1855 } 1856 } 1857 } 1858 1859 putchar ('\n'); 1860 } 1861 } 1862 1863 1864 /* Print version information. */ 1865 static void 1866 print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr) 1867 { 1868 /* Find the version information sections. For this we have to 1869 search through the section table. */ 1870 Elf_Scn *scn = NULL; 1871 1872 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1873 { 1874 /* Handle the section if it is part of the versioning handling. */ 1875 GElf_Shdr shdr_mem; 1876 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1877 1878 if (shdr != NULL) 1879 { 1880 if (shdr->sh_type == SHT_GNU_verneed) 1881 handle_verneed (ebl, ehdr, scn, shdr); 1882 else if (shdr->sh_type == SHT_GNU_verdef) 1883 handle_verdef (ebl, ehdr, scn, shdr); 1884 else if (shdr->sh_type == SHT_GNU_versym) 1885 handle_versym (ebl, ehdr, scn, shdr); 1886 } 1887 } 1888 } 1889 1890 1891 static const char * 1892 get_ver_flags (unsigned int flags) 1893 { 1894 static char buf[32]; 1895 char *endp; 1896 1897 if (flags == 0) 1898 return gettext ("none"); 1899 1900 if (flags & VER_FLG_BASE) 1901 endp = stpcpy (buf, "BASE "); 1902 else 1903 endp = buf; 1904 1905 if (flags & VER_FLG_WEAK) 1906 { 1907 if (endp != buf) 1908 endp = stpcpy (endp, "| "); 1909 1910 endp = stpcpy (endp, "WEAK "); 1911 } 1912 1913 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)) 1914 { 1915 strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp); 1916 buf[sizeof (buf) - 1] = '\0'; 1917 } 1918 1919 return buf; 1920 } 1921 1922 1923 static void 1924 handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 1925 { 1926 Elf_Data *data; 1927 int class = gelf_getclass (ebl->elf); 1928 GElf_Shdr glink; 1929 int cnt; 1930 unsigned int offset; 1931 size_t shstrndx; 1932 1933 /* Get the data of the section. */ 1934 data = elf_getdata (scn, NULL); 1935 if (data == NULL) 1936 return; 1937 1938 /* Get the section header string table index. */ 1939 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 1940 error (EXIT_FAILURE, 0, 1941 gettext ("cannot get section header string table index")); 1942 1943 printf (ngettext ("\ 1944 \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 1945 "\ 1946 \nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 1947 shdr->sh_info), 1948 (unsigned int) elf_ndxscn (scn), 1949 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info, 1950 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 1951 shdr->sh_offset, 1952 (unsigned int) shdr->sh_link, 1953 elf_strptr (ebl->elf, shstrndx, 1954 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 1955 &glink)->sh_name)); 1956 1957 offset = 0; 1958 for (cnt = shdr->sh_info; --cnt >= 0; ) 1959 { 1960 GElf_Verneed needmem; 1961 GElf_Verneed *need; 1962 unsigned int auxoffset; 1963 int cnt2; 1964 1965 /* Get the data at the next offset. */ 1966 need = gelf_getverneed (data, offset, &needmem); 1967 if (need == NULL) 1968 break; 1969 1970 printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"), 1971 offset, (unsigned short int) need->vn_version, 1972 elf_strptr (ebl->elf, shdr->sh_link, need->vn_file), 1973 (unsigned short int) need->vn_cnt); 1974 1975 auxoffset = offset + need->vn_aux; 1976 for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) 1977 { 1978 GElf_Vernaux auxmem; 1979 GElf_Vernaux *aux; 1980 1981 aux = gelf_getvernaux (data, auxoffset, &auxmem); 1982 if (aux == NULL) 1983 break; 1984 1985 printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"), 1986 auxoffset, 1987 elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name), 1988 get_ver_flags (aux->vna_flags), 1989 (unsigned short int) aux->vna_other); 1990 1991 auxoffset += aux->vna_next; 1992 } 1993 1994 /* Find the next offset. */ 1995 offset += need->vn_next; 1996 } 1997 } 1998 1999 2000 static void 2001 handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 2002 { 2003 Elf_Data *data; 2004 int class = gelf_getclass (ebl->elf); 2005 GElf_Shdr glink; 2006 int cnt; 2007 unsigned int offset; 2008 size_t shstrndx; 2009 2010 /* Get the data of the section. */ 2011 data = elf_getdata (scn, NULL); 2012 if (data == NULL) 2013 return; 2014 2015 /* Get the section header string table index. */ 2016 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 2017 error (EXIT_FAILURE, 0, 2018 gettext ("cannot get section header string table index")); 2019 2020 printf (ngettext ("\ 2021 \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2022 "\ 2023 \nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", 2024 shdr->sh_info), 2025 (unsigned int) elf_ndxscn (scn), 2026 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2027 shdr->sh_info, 2028 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 2029 shdr->sh_offset, 2030 (unsigned int) shdr->sh_link, 2031 elf_strptr (ebl->elf, shstrndx, 2032 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2033 &glink)->sh_name)); 2034 2035 offset = 0; 2036 for (cnt = shdr->sh_info; --cnt >= 0; ) 2037 { 2038 GElf_Verdef defmem; 2039 GElf_Verdef *def; 2040 GElf_Verdaux auxmem; 2041 GElf_Verdaux *aux; 2042 unsigned int auxoffset; 2043 int cnt2; 2044 2045 /* Get the data at the next offset. */ 2046 def = gelf_getverdef (data, offset, &defmem); 2047 if (def == NULL) 2048 break; 2049 2050 auxoffset = offset + def->vd_aux; 2051 aux = gelf_getverdaux (data, auxoffset, &auxmem); 2052 if (aux == NULL) 2053 break; 2054 2055 printf (gettext ("\ 2056 %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"), 2057 offset, def->vd_version, 2058 get_ver_flags (def->vd_flags), 2059 def->vd_ndx, 2060 def->vd_cnt, 2061 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name)); 2062 2063 auxoffset += aux->vda_next; 2064 for (cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2) 2065 { 2066 aux = gelf_getverdaux (data, auxoffset, &auxmem); 2067 if (aux == NULL) 2068 break; 2069 2070 printf (gettext (" %#06x: Parent %d: %s\n"), 2071 auxoffset, cnt2, 2072 elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name)); 2073 2074 auxoffset += aux->vda_next; 2075 } 2076 2077 /* Find the next offset. */ 2078 offset += def->vd_next; 2079 } 2080 } 2081 2082 2083 static void 2084 handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) 2085 { 2086 Elf_Data *data; 2087 int class = gelf_getclass (ebl->elf); 2088 Elf_Scn *verscn; 2089 GElf_Shdr glink; 2090 Elf_Scn *defscn; 2091 Elf_Scn *needscn; 2092 const char **vername; 2093 const char **filename; 2094 size_t nvername; 2095 unsigned int cnt; 2096 size_t shstrndx; 2097 2098 /* Get the data of the section. */ 2099 data = elf_getdata (scn, NULL); 2100 if (data == NULL) 2101 return; 2102 2103 /* Get the section header string table index. */ 2104 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 2105 error (EXIT_FAILURE, 0, 2106 gettext ("cannot get section header string table index")); 2107 2108 /* We have to find the version definition section and extract the 2109 version names. */ 2110 defscn = NULL; 2111 needscn = NULL; 2112 2113 verscn = NULL; 2114 while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL) 2115 { 2116 GElf_Shdr vershdr_mem; 2117 GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem); 2118 2119 if (vershdr != NULL) 2120 { 2121 if (vershdr->sh_type == SHT_GNU_verdef) 2122 defscn = verscn; 2123 else if (vershdr->sh_type == SHT_GNU_verneed) 2124 needscn = verscn; 2125 } 2126 } 2127 2128 if (defscn != NULL || needscn != NULL) 2129 { 2130 /* We have a version information (better should have). Now get 2131 the version names. First find the maximum version number. */ 2132 nvername = 0; 2133 if (defscn != NULL) 2134 { 2135 /* Run through the version definitions and find the highest 2136 index. */ 2137 unsigned int offset = 0; 2138 Elf_Data *defdata; 2139 GElf_Shdr defshdrmem; 2140 GElf_Shdr *defshdr; 2141 2142 defdata = elf_getdata (defscn, NULL); 2143 if (defdata == NULL) 2144 return; 2145 2146 defshdr = gelf_getshdr (defscn, &defshdrmem); 2147 if (defshdr == NULL) 2148 return; 2149 2150 for (cnt = 0; cnt < defshdr->sh_info; ++cnt) 2151 { 2152 GElf_Verdef defmem; 2153 GElf_Verdef *def; 2154 2155 /* Get the data at the next offset. */ 2156 def = gelf_getverdef (defdata, offset, &defmem); 2157 if (def == NULL) 2158 break; 2159 2160 nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff)); 2161 2162 offset += def->vd_next; 2163 } 2164 } 2165 if (needscn != NULL) 2166 { 2167 unsigned int offset = 0; 2168 Elf_Data *needdata; 2169 GElf_Shdr needshdrmem; 2170 GElf_Shdr *needshdr; 2171 2172 needdata = elf_getdata (needscn, NULL); 2173 if (needdata == NULL) 2174 return; 2175 2176 needshdr = gelf_getshdr (needscn, &needshdrmem); 2177 if (needshdr == NULL) 2178 return; 2179 2180 for (cnt = 0; cnt < needshdr->sh_info; ++cnt) 2181 { 2182 GElf_Verneed needmem; 2183 GElf_Verneed *need; 2184 unsigned int auxoffset; 2185 int cnt2; 2186 2187 /* Get the data at the next offset. */ 2188 need = gelf_getverneed (needdata, offset, &needmem); 2189 if (need == NULL) 2190 break; 2191 2192 /* Run through the auxiliary entries. */ 2193 auxoffset = offset + need->vn_aux; 2194 for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) 2195 { 2196 GElf_Vernaux auxmem; 2197 GElf_Vernaux *aux; 2198 2199 aux = gelf_getvernaux (needdata, auxoffset, &auxmem); 2200 if (aux == NULL) 2201 break; 2202 2203 nvername = MAX (nvername, 2204 (size_t) (aux->vna_other & 0x7fff)); 2205 2206 auxoffset += aux->vna_next; 2207 } 2208 2209 offset += need->vn_next; 2210 } 2211 } 2212 2213 /* This is the number of versions we know about. */ 2214 ++nvername; 2215 2216 /* Allocate the array. */ 2217 vername = (const char **) alloca (nvername * sizeof (const char *)); 2218 filename = (const char **) alloca (nvername * sizeof (const char *)); 2219 2220 /* Run through the data structures again and collect the strings. */ 2221 if (defscn != NULL) 2222 { 2223 /* Run through the version definitions and find the highest 2224 index. */ 2225 unsigned int offset = 0; 2226 Elf_Data *defdata; 2227 GElf_Shdr defshdrmem; 2228 GElf_Shdr *defshdr; 2229 2230 defdata = elf_getdata (defscn, NULL); 2231 if (defdata == NULL) 2232 return; 2233 2234 defshdr = gelf_getshdr (defscn, &defshdrmem); 2235 if (defshdr == NULL) 2236 return; 2237 2238 for (cnt = 0; cnt < defshdr->sh_info; ++cnt) 2239 { 2240 GElf_Verdef defmem; 2241 GElf_Verdef *def; 2242 GElf_Verdaux auxmem; 2243 GElf_Verdaux *aux; 2244 2245 /* Get the data at the next offset. */ 2246 def = gelf_getverdef (defdata, offset, &defmem); 2247 if (def == NULL) 2248 break; 2249 2250 aux = gelf_getverdaux (defdata, offset + def->vd_aux, &auxmem); 2251 if (aux == NULL) 2252 break; 2253 2254 vername[def->vd_ndx & 0x7fff] 2255 = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name); 2256 filename[def->vd_ndx & 0x7fff] = NULL; 2257 2258 offset += def->vd_next; 2259 } 2260 } 2261 if (needscn != NULL) 2262 { 2263 unsigned int offset = 0; 2264 Elf_Data *needdata; 2265 GElf_Shdr needshdrmem; 2266 GElf_Shdr *needshdr; 2267 2268 needdata = elf_getdata (needscn, NULL); 2269 if (needdata == NULL) 2270 return; 2271 2272 needshdr = gelf_getshdr (needscn, &needshdrmem); 2273 if (needshdr == NULL) 2274 return; 2275 2276 for (cnt = 0; cnt < needshdr->sh_info; ++cnt) 2277 { 2278 GElf_Verneed needmem; 2279 GElf_Verneed *need; 2280 unsigned int auxoffset; 2281 int cnt2; 2282 2283 /* Get the data at the next offset. */ 2284 need = gelf_getverneed (needdata, offset, &needmem); 2285 if (need == NULL) 2286 break; 2287 2288 /* Run through the auxiliary entries. */ 2289 auxoffset = offset + need->vn_aux; 2290 for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) 2291 { 2292 GElf_Vernaux auxmem; 2293 GElf_Vernaux *aux; 2294 2295 aux = gelf_getvernaux (needdata, auxoffset, &auxmem); 2296 if (aux == NULL) 2297 break; 2298 2299 vername[aux->vna_other & 0x7fff] 2300 = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name); 2301 filename[aux->vna_other & 0x7fff] 2302 = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file); 2303 2304 auxoffset += aux->vna_next; 2305 } 2306 2307 offset += need->vn_next; 2308 } 2309 } 2310 } 2311 else 2312 { 2313 vername = NULL; 2314 nvername = 1; 2315 filename = NULL; 2316 } 2317 2318 /* Print the header. */ 2319 printf (ngettext ("\ 2320 \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", 2321 "\ 2322 \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", 2323 shdr->sh_size / shdr->sh_entsize), 2324 (unsigned int) elf_ndxscn (scn), 2325 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2326 (int) (shdr->sh_size / shdr->sh_entsize), 2327 class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, 2328 shdr->sh_offset, 2329 (unsigned int) shdr->sh_link, 2330 elf_strptr (ebl->elf, shstrndx, 2331 gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2332 &glink)->sh_name)); 2333 2334 /* Now we can finally look at the actual contents of this section. */ 2335 for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 2336 { 2337 GElf_Versym symmem; 2338 GElf_Versym *sym; 2339 ssize_t n; 2340 2341 if (cnt % 2 == 0) 2342 printf ("\n %4d:", cnt); 2343 2344 sym = gelf_getversym (data, cnt, &symmem); 2345 if (sym == NULL) 2346 break; 2347 2348 switch (*sym) 2349 { 2350 case 0: 2351 fputs_unlocked (gettext (" 0 *local* "), 2352 stdout); 2353 break; 2354 2355 case 1: 2356 fputs_unlocked (gettext (" 1 *global* "), 2357 stdout); 2358 break; 2359 2360 default: 2361 n = printf ("%4d%c%s", 2362 *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ', 2363 (unsigned int) (*sym & 0x7fff) < nvername 2364 ? vername[*sym & 0x7fff] : "???"); 2365 if ((unsigned int) (*sym & 0x7fff) < nvername 2366 && filename[*sym & 0x7fff] != NULL) 2367 n += printf ("(%s)", filename[*sym & 0x7fff]); 2368 printf ("%*s", MAX (0, 33 - (int) n), " "); 2369 break; 2370 } 2371 } 2372 putchar ('\n'); 2373 } 2374 2375 2376 static void 2377 handle_hash (Ebl *ebl, GElf_Ehdr *ehdr) 2378 { 2379 /* Find the symbol table(s). For this we have to search through the 2380 section table. */ 2381 Elf_Scn *scn = NULL; 2382 size_t shstrndx; 2383 2384 /* Get the section header string table index. */ 2385 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 2386 error (EXIT_FAILURE, 0, 2387 gettext ("cannot get section header string table index")); 2388 2389 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 2390 { 2391 /* Handle the section if it is a symbol table. */ 2392 GElf_Shdr shdr_mem; 2393 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2394 2395 if (shdr != NULL && shdr->sh_type == SHT_HASH) 2396 { 2397 Elf_Data *data = elf_getdata (scn, NULL); 2398 Elf32_Word nbucket; 2399 Elf32_Word nchain; 2400 Elf32_Word *bucket; 2401 Elf32_Word *chain; 2402 uint32_t *lengths; 2403 uint32_t *counts; 2404 Elf32_Word cnt; 2405 Elf32_Word maxlength = 0; 2406 Elf32_Word nsyms = 0; 2407 uint64_t nzero_counts = 0; 2408 GElf_Shdr glink; 2409 2410 if (data == NULL) 2411 { 2412 error (0, 0, gettext ("cannot get data for section %d: %s"), 2413 (int) elf_ndxscn (scn), elf_errmsg (-1)); 2414 continue; 2415 } 2416 2417 nbucket = ((Elf32_Word *) data->d_buf)[0]; 2418 nchain = ((Elf32_Word *) data->d_buf)[1]; 2419 bucket = &((Elf32_Word *) data->d_buf)[2]; 2420 chain = &((Elf32_Word *) data->d_buf)[2 + nbucket]; 2421 2422 printf (ngettext ("\ 2423 \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", 2424 "\ 2425 \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", 2426 nbucket), 2427 (unsigned int) elf_ndxscn (scn), 2428 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2429 (int) nbucket, 2430 gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18, 2431 shdr->sh_addr, 2432 shdr->sh_offset, 2433 (unsigned int) shdr->sh_link, 2434 elf_strptr (ebl->elf, shstrndx, 2435 gelf_getshdr (elf_getscn (ebl->elf, 2436 shdr->sh_link), 2437 &glink)->sh_name)); 2438 2439 lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t)); 2440 2441 for (cnt = 0; cnt < nbucket; ++cnt) 2442 if (bucket[cnt] != 0) 2443 { 2444 Elf32_Word inner; 2445 2446 inner = bucket[cnt]; 2447 while (inner > 0 && inner < nchain) 2448 { 2449 ++nsyms; 2450 if (maxlength < ++lengths[cnt]) 2451 ++maxlength; 2452 2453 inner = chain[inner]; 2454 } 2455 } 2456 2457 counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t)); 2458 2459 for (cnt = 0; cnt < nbucket; ++cnt) 2460 ++counts[lengths[cnt]]; 2461 2462 if (nbucket > 0) 2463 { 2464 uint64_t success = 0; 2465 Elf32_Word acc; 2466 2467 puts (gettext (" Length Number % of total Coverage")); 2468 printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"), 2469 counts[0], (counts[0] * 100.0) / nbucket); 2470 2471 for (cnt = 1; cnt <= maxlength; ++cnt) 2472 { 2473 nzero_counts += counts[cnt] * cnt; 2474 printf (gettext ("\ 2475 %7d %6" PRIu32 " %5.1f%% %5.1f%%\n"), 2476 (int) cnt, 2477 counts[cnt], (counts[cnt] * 100.0) / nbucket, 2478 (nzero_counts * 100.0) / nsyms); 2479 } 2480 2481 acc = 0; 2482 for (cnt = 1; cnt <= maxlength; ++cnt) 2483 { 2484 acc += cnt; 2485 success += counts[cnt] * acc; 2486 } 2487 2488 printf (gettext ("\ 2489 Average number of tests: successful lookup: %f\n\ 2490 unsuccessful lookup: %f\n"), 2491 (double) success / (double) nzero_counts, 2492 (double) nzero_counts / (double) nbucket); 2493 } 2494 2495 free (counts); 2496 free (lengths); 2497 } 2498 } 2499 } 2500 2501 2502 static void 2503 print_liblist (Ebl *ebl, GElf_Ehdr *ehdr) 2504 { 2505 /* Find the library list sections. For this we have to search 2506 through the section table. */ 2507 Elf_Scn *scn = NULL; 2508 2509 /* Get the section header string table index. */ 2510 size_t shstrndx; 2511 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 2512 error (EXIT_FAILURE, 0, 2513 gettext ("cannot get section header string table index")); 2514 2515 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 2516 { 2517 GElf_Shdr shdr_mem; 2518 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2519 2520 if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST) 2521 { 2522 int nentries = shdr->sh_size / shdr->sh_entsize; 2523 printf (ngettext ("\ 2524 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n", 2525 "\ 2526 \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n", 2527 nentries), 2528 elf_ndxscn (scn), 2529 elf_strptr (ebl->elf, shstrndx, shdr->sh_name), 2530 shdr->sh_offset, 2531 nentries); 2532 2533 Elf_Data *data = elf_getdata (scn, NULL); 2534 if (data == NULL) 2535 return; 2536 2537 puts (gettext ("\ 2538 Library Time Stamp Checksum Version Flags")); 2539 2540 for (int cnt = 0; cnt < nentries; ++cnt) 2541 { 2542 GElf_Lib lib_mem; 2543 GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem); 2544 if (lib == NULL) 2545 continue; 2546 2547 time_t t = (time_t) lib->l_time_stamp; 2548 struct tm *tm = gmtime (&t); 2549 if (tm == NULL) 2550 continue; 2551 2552 printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n", 2553 cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name), 2554 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 2555 tm->tm_hour, tm->tm_min, tm->tm_sec, 2556 (unsigned int) lib->l_checksum, 2557 (unsigned int) lib->l_version, 2558 (unsigned int) lib->l_flags); 2559 } 2560 } 2561 } 2562 } 2563 2564 2565 static const char * 2566 dwarf_tag_string (unsigned int tag) 2567 { 2568 static const char *known_tags[] = 2569 { 2570 [DW_TAG_array_type] = "array_type", 2571 [DW_TAG_class_type] = "class_type", 2572 [DW_TAG_entry_point] = "entry_point", 2573 [DW_TAG_enumeration_type] = "enumeration_type", 2574 [DW_TAG_formal_parameter] = "formal_parameter", 2575 [DW_TAG_imported_declaration] = "imported_declaration", 2576 [DW_TAG_label] = "label", 2577 [DW_TAG_lexical_block] = "lexical_block", 2578 [DW_TAG_member] = "member", 2579 [DW_TAG_pointer_type] = "pointer_type", 2580 [DW_TAG_reference_type] = "reference_type", 2581 [DW_TAG_compile_unit] = "compile_unit", 2582 [DW_TAG_string_type] = "string_type", 2583 [DW_TAG_structure_type] = "structure_type", 2584 [DW_TAG_subroutine_type] = "subroutine_type", 2585 [DW_TAG_typedef] = "typedef", 2586 [DW_TAG_union_type] = "union_type", 2587 [DW_TAG_unspecified_parameters] = "unspecified_parameters", 2588 [DW_TAG_variant] = "variant", 2589 [DW_TAG_common_block] = "common_block", 2590 [DW_TAG_common_inclusion] = "common_inclusion", 2591 [DW_TAG_inheritance] = "inheritance", 2592 [DW_TAG_inlined_subroutine] = "inlined_subroutine", 2593 [DW_TAG_module] = "module", 2594 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type", 2595 [DW_TAG_set_type] = "set_type", 2596 [DW_TAG_subrange_type] = "subrange_type", 2597 [DW_TAG_with_stmt] = "with_stmt", 2598 [DW_TAG_access_declaration] = "access_declaration", 2599 [DW_TAG_base_type] = "base_type", 2600 [DW_TAG_catch_block] = "catch_block", 2601 [DW_TAG_const_type] = "const_type", 2602 [DW_TAG_constant] = "constant", 2603 [DW_TAG_enumerator] = "enumerator", 2604 [DW_TAG_file_type] = "file_type", 2605 [DW_TAG_friend] = "friend", 2606 [DW_TAG_namelist] = "namelist", 2607 [DW_TAG_namelist_item] = "namelist_item", 2608 [DW_TAG_packed_type] = "packed_type", 2609 [DW_TAG_subprogram] = "subprogram", 2610 [DW_TAG_template_type_param] = "template_type_param", 2611 [DW_TAG_template_value_param] = "template_value_param", 2612 [DW_TAG_thrown_type] = "thrown_type", 2613 [DW_TAG_try_block] = "try_block", 2614 [DW_TAG_variant_part] = "variant_part", 2615 [DW_TAG_variable] = "variable", 2616 [DW_TAG_volatile_type] = "volatile_type", 2617 }; 2618 const unsigned int nknown_tags = (sizeof (known_tags) 2619 / sizeof (known_tags[0])); 2620 static char buf[40]; 2621 const char *result = NULL; 2622 2623 if (tag < nknown_tags) 2624 result = known_tags[tag]; 2625 2626 if (result == NULL) 2627 /* There are a few known extensions. */ 2628 switch (tag) 2629 { 2630 case DW_TAG_MIPS_loop: 2631 result = "MIPS_loop"; 2632 break; 2633 2634 case DW_TAG_format_label: 2635 result = "format_label"; 2636 break; 2637 2638 case DW_TAG_function_template: 2639 result = "function_template"; 2640 break; 2641 2642 case DW_TAG_class_template: 2643 result = "class_template"; 2644 break; 2645 2646 default: 2647 if (tag < DW_TAG_lo_user) 2648 snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag); 2649 else 2650 snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag); 2651 result = buf; 2652 break; 2653 } 2654 2655 return result; 2656 } 2657 2658 2659 static const char * 2660 dwarf_attr_string (unsigned int attrnum) 2661 { 2662 static const char *known_attrs[] = 2663 { 2664 [DW_AT_sibling] = "sibling", 2665 [DW_AT_location] = "location", 2666 [DW_AT_name] = "name", 2667 [DW_AT_ordering] = "ordering", 2668 [DW_AT_subscr_data] = "subscr_data", 2669 [DW_AT_byte_size] = "byte_size", 2670 [DW_AT_bit_offset] = "bit_offset", 2671 [DW_AT_bit_size] = "bit_size", 2672 [DW_AT_element_list] = "element_list", 2673 [DW_AT_stmt_list] = "stmt_list", 2674 [DW_AT_low_pc] = "low_pc", 2675 [DW_AT_high_pc] = "high_pc", 2676 [DW_AT_language] = "language", 2677 [DW_AT_member] = "member", 2678 [DW_AT_discr] = "discr", 2679 [DW_AT_discr_value] = "discr_value", 2680 [DW_AT_visibility] = "visibility", 2681 [DW_AT_import] = "import", 2682 [DW_AT_string_length] = "string_length", 2683 [DW_AT_common_reference] = "common_reference", 2684 [DW_AT_comp_dir] = "comp_dir", 2685 [DW_AT_const_value] = "const_value", 2686 [DW_AT_containing_type] = "containing_type", 2687 [DW_AT_default_value] = "default_value", 2688 [DW_AT_inline] = "inline", 2689 [DW_AT_is_optional] = "is_optional", 2690 [DW_AT_lower_bound] = "lower_bound", 2691 [DW_AT_producer] = "producer", 2692 [DW_AT_prototyped] = "prototyped", 2693 [DW_AT_return_addr] = "return_addr", 2694 [DW_AT_start_scope] = "start_scope", 2695 [DW_AT_stride_size] = "stride_size", 2696 [DW_AT_upper_bound] = "upper_bound", 2697 [DW_AT_abstract_origin] = "abstract_origin", 2698 [DW_AT_accessibility] = "accessibility", 2699 [DW_AT_address_class] = "address_class", 2700 [DW_AT_artificial] = "artificial", 2701 [DW_AT_base_types] = "base_types", 2702 [DW_AT_calling_convention] = "calling_convention", 2703 [DW_AT_count] = "count", 2704 [DW_AT_data_member_location] = "data_member_location", 2705 [DW_AT_decl_column] = "decl_column", 2706 [DW_AT_decl_file] = "decl_file", 2707 [DW_AT_decl_line] = "decl_line", 2708 [DW_AT_declaration] = "declaration", 2709 [DW_AT_discr_list] = "discr_list", 2710 [DW_AT_encoding] = "encoding", 2711 [DW_AT_external] = "external", 2712 [DW_AT_frame_base] = "frame_base", 2713 [DW_AT_friend] = "friend", 2714 [DW_AT_identifier_case] = "identifier_case", 2715 [DW_AT_macro_info] = "macro_info", 2716 [DW_AT_namelist_items] = "namelist_items", 2717 [DW_AT_priority] = "priority", 2718 [DW_AT_segment] = "segment", 2719 [DW_AT_specification] = "specification", 2720 [DW_AT_static_link] = "static_link", 2721 [DW_AT_type] = "type", 2722 [DW_AT_use_location] = "use_location", 2723 [DW_AT_variable_parameter] = "variable_parameter", 2724 [DW_AT_virtuality] = "virtuality", 2725 [DW_AT_vtable_elem_location] = "vtable_elem_location" 2726 }; 2727 const unsigned int nknown_attrs = (sizeof (known_attrs) 2728 / sizeof (known_attrs[0])); 2729 static char buf[40]; 2730 const char *result = NULL; 2731 2732 if (attrnum < nknown_attrs) 2733 result = known_attrs[attrnum]; 2734 2735 if (result == NULL) 2736 /* There are a few known extensions. */ 2737 switch (attrnum) 2738 { 2739 case DW_AT_MIPS_fde: 2740 result = "MIPS_fde"; 2741 break; 2742 2743 case DW_AT_MIPS_loop_begin: 2744 result = "MIPS_loop_begin"; 2745 break; 2746 2747 case DW_AT_MIPS_tail_loop_begin: 2748 result = "MIPS_tail_loop_begin"; 2749 break; 2750 2751 case DW_AT_MIPS_epilog_begin: 2752 result = "MIPS_epilog_begin"; 2753 break; 2754 2755 case DW_AT_MIPS_loop_unroll_factor: 2756 result = "MIPS_loop_unroll_factor"; 2757 break; 2758 2759 case DW_AT_MIPS_software_pipeline_depth: 2760 result = "MIPS_software_pipeline_depth"; 2761 break; 2762 2763 case DW_AT_MIPS_linkage_name: 2764 result = "MIPS_linkage_name"; 2765 break; 2766 2767 case DW_AT_MIPS_stride: 2768 result = "MIPS_stride"; 2769 break; 2770 2771 case DW_AT_MIPS_abstract_name: 2772 result = "MIPS_abstract_name"; 2773 break; 2774 2775 case DW_AT_MIPS_clone_origin: 2776 result = "MIPS_clone_origin"; 2777 break; 2778 2779 case DW_AT_MIPS_has_inlines: 2780 result = "MIPS_has_inlines"; 2781 break; 2782 2783 case DW_AT_MIPS_stride_byte: 2784 result = "MIPS_stride_byte"; 2785 break; 2786 2787 case DW_AT_MIPS_stride_elem: 2788 result = "MIPS_stride_elem"; 2789 break; 2790 2791 case DW_AT_MIPS_ptr_dopetype: 2792 result = "MIPS_ptr_dopetype"; 2793 break; 2794 2795 case DW_AT_MIPS_allocatable_dopetype: 2796 result = "MIPS_allocatable_dopetype"; 2797 break; 2798 2799 case DW_AT_MIPS_assumed_shape_dopetype: 2800 result = "MIPS_assumed_shape_dopetype"; 2801 break; 2802 2803 case DW_AT_MIPS_assumed_size: 2804 result = "MIPS_assumed_size"; 2805 break; 2806 2807 case DW_AT_sf_names: 2808 result = "sf_names"; 2809 break; 2810 2811 case DW_AT_src_info: 2812 result = "src_info"; 2813 break; 2814 2815 case DW_AT_mac_info: 2816 result = "mac_info"; 2817 break; 2818 2819 case DW_AT_src_coords: 2820 result = "src_coords"; 2821 break; 2822 2823 case DW_AT_body_begin: 2824 result = "body_begin"; 2825 break; 2826 2827 case DW_AT_body_end: 2828 result = "body_end"; 2829 break; 2830 2831 default: 2832 if (attrnum < DW_AT_lo_user) 2833 snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"), 2834 attrnum); 2835 else 2836 snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"), 2837 attrnum); 2838 result = buf; 2839 break; 2840 } 2841 2842 return result; 2843 } 2844 2845 2846 static const char * 2847 dwarf_form_string (unsigned int form) 2848 { 2849 static const char *known_forms[] = 2850 { 2851 [DW_FORM_addr] = "addr", 2852 [DW_FORM_block2] = "block2", 2853 [DW_FORM_block4] = "block4", 2854 [DW_FORM_data2] = "data2", 2855 [DW_FORM_data4] = "data4", 2856 [DW_FORM_data8] = "data8", 2857 [DW_FORM_string] = "string", 2858 [DW_FORM_block] = "block", 2859 [DW_FORM_block1] = "block1", 2860 [DW_FORM_data1] = "data1", 2861 [DW_FORM_flag] = "flag", 2862 [DW_FORM_sdata] = "sdata", 2863 [DW_FORM_strp] = "strp", 2864 [DW_FORM_udata] = "udata", 2865 [DW_FORM_ref_addr] = "ref_addr", 2866 [DW_FORM_ref1] = "ref1", 2867 [DW_FORM_ref2] = "ref2", 2868 [DW_FORM_ref4] = "ref4", 2869 [DW_FORM_ref8] = "ref8", 2870 [DW_FORM_ref_udata] = "ref_udata", 2871 [DW_FORM_indirect] = "indirect" 2872 }; 2873 const unsigned int nknown_forms = (sizeof (known_forms) 2874 / sizeof (known_forms[0])); 2875 static char buf[40]; 2876 const char *result = NULL; 2877 2878 if (form < nknown_forms) 2879 result = known_forms[form]; 2880 2881 if (result == NULL) 2882 snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64), 2883 (uint64_t) form); 2884 2885 return result; 2886 } 2887 2888 2889 static const char * 2890 dwarf_lang_string (unsigned int lang) 2891 { 2892 static const char *known[] = 2893 { 2894 [DW_LANG_C89] = "ISO C89", 2895 [DW_LANG_C] = "C", 2896 [DW_LANG_Ada83] = "Ada83", 2897 [DW_LANG_C_plus_plus ] = "C++", 2898 [DW_LANG_Cobol74] = "Cobol74", 2899 [DW_LANG_Cobol85] = "Cobol85", 2900 [DW_LANG_Fortran77] = "Fortran77", 2901 [DW_LANG_Fortran90] = "Fortran90", 2902 [DW_LANG_Pascal83] = "Pascal83", 2903 [DW_LANG_Modula2] = "Modula2", 2904 [DW_LANG_Java] = "Java", 2905 [DW_LANG_C99] = "ISO C99", 2906 [DW_LANG_Ada95] = "Ada95", 2907 [DW_LANG_Fortran95] = "Fortran95", 2908 [DW_LANG_PL1] = "PL1" 2909 }; 2910 2911 if (lang < sizeof (known) / sizeof (known[0])) 2912 return known[lang]; 2913 else if (lang == DW_LANG_Mips_Assembler) 2914 /* This language tag is used for assembler in general. */ 2915 return "Assembler"; 2916 2917 if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user) 2918 { 2919 static char buf[100]; 2920 snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user); 2921 return buf; 2922 } 2923 2924 return "???"; 2925 } 2926 2927 2928 static void 2929 print_ops (Dwarf *dbg, int level, unsigned int addrsize, Dwarf_Word len, 2930 unsigned char *data) 2931 { 2932 static const char *known[] = 2933 { 2934 [DW_OP_addr] = "addr", 2935 [DW_OP_deref] = "deref", 2936 [DW_OP_const1u] = "const1u", 2937 [DW_OP_const1s] = "const1s", 2938 [DW_OP_const2u] = "const2u", 2939 [DW_OP_const2s] = "const2s", 2940 [DW_OP_const4u] = "const4u", 2941 [DW_OP_const4s] = "const4s", 2942 [DW_OP_const8u] = "const8u", 2943 [DW_OP_const8s] = "const8s", 2944 [DW_OP_constu] = "constu", 2945 [DW_OP_consts] = "consts", 2946 [DW_OP_dup] = "dup", 2947 [DW_OP_drop] = "drop", 2948 [DW_OP_over] = "over", 2949 [DW_OP_pick] = "pick", 2950 [DW_OP_swap] = "swap", 2951 [DW_OP_rot] = "rot", 2952 [DW_OP_xderef] = "xderef", 2953 [DW_OP_abs] = "abs", 2954 [DW_OP_and] = "and", 2955 [DW_OP_div] = "div", 2956 [DW_OP_minus] = "minus", 2957 [DW_OP_mod] = "mod", 2958 [DW_OP_mul] = "mul", 2959 [DW_OP_neg] = "neg", 2960 [DW_OP_not] = "not", 2961 [DW_OP_or] = "or", 2962 [DW_OP_plus] = "plus", 2963 [DW_OP_plus_uconst] = "plus_uconst", 2964 [DW_OP_shl] = "shl", 2965 [DW_OP_shr] = "shr", 2966 [DW_OP_shra] = "shra", 2967 [DW_OP_xor] = "xor", 2968 [DW_OP_bra] = "bra", 2969 [DW_OP_eq] = "eq", 2970 [DW_OP_ge] = "ge", 2971 [DW_OP_gt] = "gt", 2972 [DW_OP_le] = "le", 2973 [DW_OP_lt] = "lt", 2974 [DW_OP_ne] = "ne", 2975 [DW_OP_skip] = "skip", 2976 [DW_OP_lit0] = "lit0", 2977 [DW_OP_lit1] = "lit1", 2978 [DW_OP_lit2] = "lit2", 2979 [DW_OP_lit3] = "lit3", 2980 [DW_OP_lit4] = "lit4", 2981 [DW_OP_lit5] = "lit5", 2982 [DW_OP_lit6] = "lit6", 2983 [DW_OP_lit7] = "lit7", 2984 [DW_OP_lit8] = "lit8", 2985 [DW_OP_lit9] = "lit9", 2986 [DW_OP_lit10] = "lit10", 2987 [DW_OP_lit11] = "lit11", 2988 [DW_OP_lit12] = "lit12", 2989 [DW_OP_lit13] = "lit13", 2990 [DW_OP_lit14] = "lit14", 2991 [DW_OP_lit15] = "lit15", 2992 [DW_OP_lit16] = "lit16", 2993 [DW_OP_lit17] = "lit17", 2994 [DW_OP_lit18] = "lit18", 2995 [DW_OP_lit19] = "lit19", 2996 [DW_OP_lit20] = "lit20", 2997 [DW_OP_lit21] = "lit21", 2998 [DW_OP_lit22] = "lit22", 2999 [DW_OP_lit23] = "lit23", 3000 [DW_OP_lit24] = "lit24", 3001 [DW_OP_lit25] = "lit25", 3002 [DW_OP_lit26] = "lit26", 3003 [DW_OP_lit27] = "lit27", 3004 [DW_OP_lit28] = "lit28", 3005 [DW_OP_lit29] = "lit29", 3006 [DW_OP_lit30] = "lit30", 3007 [DW_OP_lit31] = "lit31", 3008 [DW_OP_reg0] = "reg0", 3009 [DW_OP_reg1] = "reg1", 3010 [DW_OP_reg2] = "reg2", 3011 [DW_OP_reg3] = "reg3", 3012 [DW_OP_reg4] = "reg4", 3013 [DW_OP_reg5] = "reg5", 3014 [DW_OP_reg6] = "reg6", 3015 [DW_OP_reg7] = "reg7", 3016 [DW_OP_reg8] = "reg8", 3017 [DW_OP_reg9] = "reg9", 3018 [DW_OP_reg10] = "reg10", 3019 [DW_OP_reg11] = "reg11", 3020 [DW_OP_reg12] = "reg12", 3021 [DW_OP_reg13] = "reg13", 3022 [DW_OP_reg14] = "reg14", 3023 [DW_OP_reg15] = "reg15", 3024 [DW_OP_reg16] = "reg16", 3025 [DW_OP_reg17] = "reg17", 3026 [DW_OP_reg18] = "reg18", 3027 [DW_OP_reg19] = "reg19", 3028 [DW_OP_reg20] = "reg20", 3029 [DW_OP_reg21] = "reg21", 3030 [DW_OP_reg22] = "reg22", 3031 [DW_OP_reg23] = "reg23", 3032 [DW_OP_reg24] = "reg24", 3033 [DW_OP_reg25] = "reg25", 3034 [DW_OP_reg26] = "reg26", 3035 [DW_OP_reg27] = "reg27", 3036 [DW_OP_reg28] = "reg28", 3037 [DW_OP_reg29] = "reg29", 3038 [DW_OP_reg30] = "reg30", 3039 [DW_OP_reg31] = "reg31", 3040 [DW_OP_breg0] = "breg0", 3041 [DW_OP_breg1] = "breg1", 3042 [DW_OP_breg2] = "breg2", 3043 [DW_OP_breg3] = "breg3", 3044 [DW_OP_breg4] = "breg4", 3045 [DW_OP_breg5] = "breg5", 3046 [DW_OP_breg6] = "breg6", 3047 [DW_OP_breg7] = "breg7", 3048 [DW_OP_breg8] = "breg8", 3049 [DW_OP_breg9] = "breg9", 3050 [DW_OP_breg10] = "breg10", 3051 [DW_OP_breg11] = "breg11", 3052 [DW_OP_breg12] = "breg12", 3053 [DW_OP_breg13] = "breg13", 3054 [DW_OP_breg14] = "breg14", 3055 [DW_OP_breg15] = "breg15", 3056 [DW_OP_breg16] = "breg16", 3057 [DW_OP_breg17] = "breg17", 3058 [DW_OP_breg18] = "breg18", 3059 [DW_OP_breg19] = "breg19", 3060 [DW_OP_breg20] = "breg20", 3061 [DW_OP_breg21] = "breg21", 3062 [DW_OP_breg22] = "breg22", 3063 [DW_OP_breg23] = "breg23", 3064 [DW_OP_breg24] = "breg24", 3065 [DW_OP_breg25] = "breg25", 3066 [DW_OP_breg26] = "breg26", 3067 [DW_OP_breg27] = "breg27", 3068 [DW_OP_breg28] = "breg28", 3069 [DW_OP_breg29] = "breg29", 3070 [DW_OP_breg30] = "breg30", 3071 [DW_OP_breg31] = "breg31", 3072 [DW_OP_regx] = "regx", 3073 [DW_OP_fbreg] = "fbreg", 3074 [DW_OP_bregx] = "bregx", 3075 [DW_OP_piece] = "piece", 3076 [DW_OP_deref_size] = "deref_size", 3077 [DW_OP_xderef_size] = "xderef_size", 3078 [DW_OP_nop] = "nop", 3079 [DW_OP_push_object_address] = "push_object_address", 3080 [DW_OP_call2] = "call2", 3081 [DW_OP_call4] = "call4", 3082 [DW_OP_call_ref] = "call_ref", 3083 }; 3084 3085 Dwarf_Word offset = 0; 3086 while (len-- > 0) 3087 { 3088 size_t op = *((unsigned char *) data); 3089 ++data; 3090 3091 switch (op) 3092 { 3093 case DW_OP_call_ref: 3094 case DW_OP_addr:; 3095 /* Address operand. */ 3096 Dwarf_Word addr; 3097 if (addrsize == 4) 3098 addr = read_4ubyte_unaligned (dbg, data); 3099 else 3100 { 3101 assert (addrsize == 8); 3102 addr = read_8ubyte_unaligned (dbg, data); 3103 } 3104 data += addrsize; 3105 len -= addrsize; 3106 3107 printf (" %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n", 3108 (int) (20 + level * 2), "", (uintmax_t) offset, 3109 known[op] ?: "???", (uintmax_t) addr); 3110 offset += 1 + addrsize; 3111 break; 3112 3113 case DW_OP_deref_size: /* XXX Correct? */ 3114 case DW_OP_xderef_size: /* XXX Correct? */ 3115 case DW_OP_pick: 3116 case DW_OP_const1u: 3117 printf (" %*s [%4" PRIuMAX "] %s %" PRIu8 "\n", 3118 (int) (20 + level * 2), "", (uintmax_t) offset, 3119 known[op] ?: "???", *((uint8_t *) data)); 3120 ++data; 3121 --len; 3122 offset += 2; 3123 break; 3124 3125 case DW_OP_const2u: 3126 printf (" %*s [%4" PRIuMAX "] %s %" PRIu16 "\n", 3127 (int) (20 + level * 2), "", (uintmax_t) offset, 3128 known[op] ?: "???", read_2ubyte_unaligned (dbg, data)); 3129 len -= 2; 3130 data += 2; 3131 offset += 3; 3132 break; 3133 3134 case DW_OP_const4u: 3135 printf (" %*s [%4" PRIuMAX "] %s %" PRIu32 "\n", 3136 (int) (20 + level * 2), "", (uintmax_t) offset, 3137 known[op] ?: "???", read_4ubyte_unaligned (dbg, data)); 3138 len -= 4; 3139 data += 4; 3140 offset += 5; 3141 break; 3142 3143 case DW_OP_const8u: 3144 printf (" %*s [%4" PRIuMAX "] %s %" PRIu64 "\n", 3145 (int) (20 + level * 2), "", (uintmax_t) offset, 3146 known[op] ?: "???", read_8ubyte_unaligned (dbg, data)); 3147 len -= 8; 3148 data += 8; 3149 offset += 9; 3150 break; 3151 3152 case DW_OP_const1s: 3153 printf (" %*s [%4" PRIuMAX "] %s %" PRId8 "\n", 3154 (int) (20 + level * 2), "", (uintmax_t) offset, 3155 known[op] ?: "???", *((int8_t *) data)); 3156 ++data; 3157 --len; 3158 offset += 2; 3159 break; 3160 3161 case DW_OP_const2s: 3162 printf (" %*s [%4" PRIuMAX "] %s %" PRId16 "\n", 3163 (int) (20 + level * 2), "", (uintmax_t) offset, 3164 known[op] ?: "???", read_2sbyte_unaligned (dbg, data)); 3165 len -= 2; 3166 data += 2; 3167 offset += 3; 3168 break; 3169 3170 case DW_OP_const4s: 3171 printf (" %*s [%4" PRIuMAX "] %s %" PRId32 "\n", 3172 (int) (20 + level * 2), "", (uintmax_t) offset, 3173 known[op] ?: "???", read_4sbyte_unaligned (dbg, data)); 3174 len -= 4; 3175 data += 4; 3176 offset += 5; 3177 break; 3178 3179 case DW_OP_const8s: 3180 printf (" %*s [%4" PRIuMAX "] %s %" PRId64 "\n", 3181 (int) (20 + level * 2), "", (uintmax_t) offset, 3182 known[op] ?: "???", read_8sbyte_unaligned (dbg, data)); 3183 len -= 8; 3184 data += 8; 3185 offset += 9; 3186 break; 3187 3188 case DW_OP_piece: /* XXX Correct? */ 3189 case DW_OP_regx: 3190 case DW_OP_plus_uconst: 3191 case DW_OP_constu:; 3192 unsigned char *start = data; 3193 unsigned int uleb; 3194 get_uleb128 (uleb, data); 3195 printf (" %*s [%4" PRIuMAX "] %s %u\n", 3196 (int) (20 + level * 2), "", (uintmax_t) offset, 3197 known[op] ?: "???", uleb); 3198 len -= data - start; 3199 offset += 1 + (data - start); 3200 break; 3201 3202 case DW_OP_fbreg: 3203 case DW_OP_breg0 ... DW_OP_breg31: 3204 case DW_OP_consts: 3205 start = data; 3206 unsigned int sleb; 3207 get_sleb128 (sleb, data); 3208 printf (" %*s [%4" PRIuMAX "] %s %d\n", 3209 (int) (20 + level * 2), "", (uintmax_t) offset, 3210 known[op] ?: "???", sleb); 3211 len -= data - start; 3212 offset += 1 + (data - start); 3213 break; 3214 3215 case DW_OP_bregx: 3216 start = data; 3217 get_uleb128 (uleb, data); 3218 get_sleb128 (sleb, data); 3219 printf (" %*s [%4" PRIuMAX "] %s %u %d\n", 3220 (int) (20 + level * 2), "", (uintmax_t) offset, 3221 known[op] ?: "???", uleb, sleb); 3222 len -= data - start; 3223 offset += 1 + (data - start); 3224 break; 3225 3226 case DW_OP_call2: 3227 case DW_OP_call4: 3228 case DW_OP_skip: 3229 case DW_OP_bra: 3230 printf (" %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n", 3231 (int) (20 + level * 2), "", (uintmax_t) offset, 3232 known[op] ?: "???", 3233 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data))); 3234 len -= 2; 3235 data += 2; 3236 offset += 3; 3237 break; 3238 3239 default: 3240 /* No Operand. */ 3241 printf (" %*s [%4" PRIuMAX "] %s\n", 3242 (int) (20 + level * 2), "", (uintmax_t) offset, 3243 known[op] ?: "???"); 3244 ++offset; 3245 break; 3246 } 3247 } 3248 } 3249 3250 3251 static void 3252 print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 3253 GElf_Shdr *shdr, Dwarf *dbg) 3254 { 3255 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n" 3256 " [ Code]\n"), 3257 ".debug_abbrev", (uint64_t) shdr->sh_offset); 3258 3259 Dwarf_Off offset = 0; 3260 while (1) 3261 { 3262 size_t length; 3263 Dwarf_Abbrev abbrev; 3264 3265 if (dwarf_offabbrev (dbg, offset, &length, &abbrev) != 0) 3266 { 3267 printf (gettext (" *** error while reading abbreviation: %s\n"), 3268 dwarf_errmsg (-1)); 3269 break; 3270 } 3271 3272 if (length == 1) 3273 /* This is the NUL byte at the end of the section. */ 3274 break; 3275 3276 /* We know these calls can never fail. */ 3277 unsigned int code = dwarf_getabbrevcode (&abbrev); 3278 unsigned int tag = dwarf_getabbrevtag (&abbrev); 3279 int has_children = dwarf_abbrevhaschildren (&abbrev); 3280 3281 printf (gettext (" [%5u] offset: %" PRId64 3282 ", children: %s, tag: %s\n"), 3283 code, (int64_t) offset, 3284 has_children ? gettext ("yes") : gettext ("no"), 3285 dwarf_tag_string (tag)); 3286 3287 size_t cnt = 0; 3288 unsigned int name; 3289 unsigned int form; 3290 Dwarf_Off enoffset; 3291 while (dwarf_getabbrevattr (&abbrev, cnt, &name, &form, &enoffset) == 0) 3292 { 3293 printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n", 3294 dwarf_attr_string (name), dwarf_form_string (form), 3295 (uint64_t) enoffset); 3296 3297 ++cnt; 3298 } 3299 3300 offset += length; 3301 } 3302 } 3303 3304 3305 /* Print content of DWARF .debug_aranges section. We fortunately do 3306 not have to know a bit about the structure of the section, libdwarf 3307 takes care of it. */ 3308 static void 3309 print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 3310 GElf_Shdr *shdr, Dwarf *dbg) 3311 { 3312 Dwarf_Aranges *aranges; 3313 size_t cnt; 3314 if (dwarf_getaranges (dbg, &aranges, &cnt) != 0) 3315 { 3316 error (0, 0, gettext ("cannot get .debug_aranges content: %s"), 3317 dwarf_errmsg (-1)); 3318 return; 3319 } 3320 3321 printf (ngettext ("\ 3322 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n", 3323 "\ 3324 \nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n", 3325 cnt), 3326 ".debug_aranges", (uint64_t) shdr->sh_offset, cnt); 3327 3328 /* Compute floor(log16(cnt)). */ 3329 size_t tmp = cnt; 3330 int digits = 1; 3331 while (tmp >= 16) 3332 { 3333 ++digits; 3334 tmp >>= 4; 3335 } 3336 3337 for (size_t n = 0; n < cnt; ++n) 3338 { 3339 Dwarf_Arange *runp = dwarf_onearange (aranges, n); 3340 if (runp == NULL) 3341 { 3342 printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1)); 3343 return; 3344 } 3345 3346 Dwarf_Addr start; 3347 Dwarf_Word length; 3348 Dwarf_Off offset; 3349 3350 if (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0) 3351 printf (gettext (" [%*zu] ???\n"), digits, n); 3352 else 3353 printf (gettext (" [%*zu] start: %0#*" PRIx64 3354 ", length: %5" PRIu64 ", CU DIE offset: %6" 3355 PRId64 "\n"), 3356 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18, 3357 (uint64_t) start, (uint64_t) length, (int64_t) offset); 3358 } 3359 } 3360 3361 3362 static void 3363 print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 3364 GElf_Shdr *shdr, Dwarf *dbg) 3365 { 3366 } 3367 3368 3369 struct attrcb_args 3370 { 3371 Dwarf *dbg; 3372 int level; 3373 unsigned int addrsize; 3374 Dwarf_Off cu_offset; 3375 }; 3376 3377 3378 static int 3379 attr_callback (Dwarf_Attribute *attrp, void *arg) 3380 { 3381 struct attrcb_args *cbargs = (struct attrcb_args *) arg; 3382 const int level = cbargs->level; 3383 3384 unsigned int attr = dwarf_whatattr (attrp); 3385 if (unlikely (attr == 0)) 3386 { 3387 error (0, 0, gettext ("cannot get attribute code: %s"), 3388 dwarf_errmsg (-1)); 3389 return DWARF_CB_ABORT; 3390 } 3391 3392 unsigned int form = dwarf_whatform (attrp); 3393 if (unlikely (form == 0)) 3394 { 3395 error (0, 0, gettext ("cannot get attribute form: %s"), 3396 dwarf_errmsg (-1)); 3397 return DWARF_CB_ABORT; 3398 } 3399 3400 switch (form) 3401 { 3402 case DW_FORM_addr:; 3403 Dwarf_Addr addr; 3404 if (unlikely (dwarf_formaddr (attrp, &addr) != 0)) 3405 { 3406 attrval_out: 3407 error (0, 0, gettext ("cannot get attribute value: %s"), 3408 dwarf_errmsg (-1)); 3409 return DWARF_CB_ABORT; 3410 } 3411 printf (" %*s%-20s %#0*" PRIxMAX "\n", 3412 (int) (level * 2), "", dwarf_attr_string (attr), 3413 (int) (cbargs->addrsize * 2), (uintmax_t) addr); 3414 break; 3415 3416 case DW_FORM_indirect: 3417 case DW_FORM_strp: 3418 case DW_FORM_string:; 3419 const char *str = dwarf_formstring (attrp); 3420 if (unlikely (str == NULL)) 3421 goto attrval_out; 3422 printf (" %*s%-20s \"%s\"\n", 3423 (int) (level * 2), "", dwarf_attr_string (attr), str); 3424 break; 3425 3426 case DW_FORM_ref_addr: 3427 case DW_FORM_ref_udata: 3428 case DW_FORM_ref8: 3429 case DW_FORM_ref4: 3430 case DW_FORM_ref2: 3431 case DW_FORM_ref1:; 3432 Dwarf_Off ref; 3433 if (unlikely (dwarf_formref (attrp, &ref) != 0)) 3434 goto attrval_out; 3435 3436 printf (" %*s%-20s [%6" PRIxMAX "]\n", 3437 (int) (level * 2), "", dwarf_attr_string (attr), 3438 (uintmax_t) (ref + cbargs->cu_offset)); 3439 break; 3440 3441 case DW_FORM_udata: 3442 case DW_FORM_sdata: 3443 case DW_FORM_data8: 3444 case DW_FORM_data4: 3445 case DW_FORM_data2: 3446 case DW_FORM_data1:; 3447 Dwarf_Word num; 3448 if (unlikely (dwarf_formudata (attrp, &num) != 0)) 3449 goto attrval_out; 3450 3451 if (attr == DW_AT_language) 3452 { 3453 printf (" %*s%-20s %s (%d)\n", 3454 (int) (level * 2), "", dwarf_attr_string (attr), 3455 dwarf_lang_string (num), (int) num); 3456 break; 3457 } 3458 3459 printf (" %*s%-20s %" PRIuMAX "\n", 3460 (int) (level * 2), "", dwarf_attr_string (attr), 3461 (uintmax_t) num); 3462 break; 3463 3464 case DW_FORM_flag:; 3465 bool flag; 3466 if (unlikely (dwarf_formflag (attrp, &flag) != 0)) 3467 goto attrval_out; 3468 3469 printf (" %*s%-20s %s\n", 3470 (int) (level * 2), "", dwarf_attr_string (attr), 3471 nl_langinfo (flag ? YESSTR : NOSTR)); 3472 break; 3473 3474 case DW_FORM_block4: 3475 case DW_FORM_block2: 3476 case DW_FORM_block1: 3477 case DW_FORM_block:; 3478 Dwarf_Block block; 3479 if (unlikely (dwarf_formblock (attrp, &block) != 0)) 3480 goto attrval_out; 3481 3482 printf (" %*s%-20s %" PRIxMAX " byte block\n", 3483 (int) (level * 2), "", dwarf_attr_string (attr), 3484 (uintmax_t) block.length); 3485 3486 if (attr == DW_AT_data_member_location) 3487 print_ops (cbargs->dbg, level, cbargs->addrsize, block.length, 3488 block.data); 3489 break; 3490 3491 default: 3492 printf (" %*s%-20s [form: %d] ???\n", 3493 (int) (level * 2), "", dwarf_attr_string (attr), 3494 (int) form); 3495 break; 3496 } 3497 3498 return DWARF_CB_OK; 3499 } 3500 3501 3502 static void 3503 print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 3504 GElf_Shdr *shdr, Dwarf *dbg) 3505 { 3506 printf (gettext ("\ 3507 \nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"), 3508 ".debug_info", (uint64_t) shdr->sh_offset); 3509 3510 /* If the section is empty we don't have to do anything. */ 3511 if (shdr->sh_size == 0) 3512 return; 3513 3514 size_t maxdies = 20; 3515 Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die)); 3516 3517 Dwarf_Off offset = 0; 3518 3519 /* New compilation unit. */ 3520 size_t cuhl; 3521 //Dwarf_Half version; 3522 Dwarf_Off abbroffset; 3523 uint8_t addrsize; 3524 uint8_t offsize; 3525 Dwarf_Off nextcu; 3526 next_cu: 3527 if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize, 3528 &offsize) != 0) 3529 goto do_return; 3530 3531 printf (gettext (" Compilation unit at offset %" PRIu64 ":\n" 3532 " Version: %" PRIu16 ", Abbreviation section offset: %" 3533 PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"), 3534 (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize); 3535 3536 3537 struct attrcb_args args; 3538 args.dbg = dbg; 3539 args.addrsize = addrsize; 3540 args.cu_offset = offset; 3541 3542 offset += cuhl; 3543 3544 int level = 0; 3545 3546 if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL)) 3547 { 3548 error (0, 0, gettext ("cannot get DIE at offset %" PRIu64 3549 " in section '%s': %s"), 3550 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1)); 3551 goto do_return; 3552 } 3553 3554 do 3555 { 3556 offset = dwarf_dieoffset (&dies[level]); 3557 if (offset == -1l) 3558 { 3559 error (0, 0, gettext ("cannot get DIE offset: %s"), 3560 dwarf_errmsg (-1)); 3561 goto do_return; 3562 } 3563 3564 int tag = dwarf_tag (&dies[level]); 3565 if (tag == DW_TAG_invalid) 3566 { 3567 error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64 3568 " in section '%s': %s"), 3569 (uint64_t) offset, ".debug_info", dwarf_errmsg (-1)); 3570 goto do_return; 3571 } 3572 3573 static const char *const lowtags[] = 3574 { 3575 [DW_TAG_array_type] = "array_type", 3576 [DW_TAG_class_type] = "class_type", 3577 [DW_TAG_entry_point] = "entry_point", 3578 [DW_TAG_enumeration_type] = "enumeration_type", 3579 [DW_TAG_formal_parameter] = "formal_parameter", 3580 [DW_TAG_imported_declaration] = "imported_declaration", 3581 [DW_TAG_label] = "label", 3582 [DW_TAG_lexical_block] = "lexical_block", 3583 [DW_TAG_member] = "member", 3584 [DW_TAG_pointer_type] = "pointer_type", 3585 [DW_TAG_reference_type] = "reference_type", 3586 [DW_TAG_compile_unit] = "compile_unit", 3587 [DW_TAG_string_type] = "string_type", 3588 [DW_TAG_structure_type] = "structure_type", 3589 [DW_TAG_subroutine_type] = "subroutine_type", 3590 [DW_TAG_typedef] = "typedef", 3591 [DW_TAG_union_type] = "union_type", 3592 [DW_TAG_unspecified_parameters] = "unspecified_parameters", 3593 [DW_TAG_variant] = "variant", 3594 [DW_TAG_common_block] = "common_block", 3595 [DW_TAG_common_inclusion] = "common_inclusion", 3596 [DW_TAG_inheritance] = "inheritance", 3597 [DW_TAG_inlined_subroutine] = "inlined_subroutine", 3598 [DW_TAG_module] = "module", 3599 [DW_TAG_ptr_to_member_type] = "ptr_to_member_type", 3600 [DW_TAG_set_type] = "set_type", 3601 [DW_TAG_subrange_type] = "subrange_type", 3602 [DW_TAG_with_stmt] = "with_stmt", 3603 [DW_TAG_access_declaration] = "access_declaration", 3604 [DW_TAG_base_type] = "base_type", 3605 [DW_TAG_catch_block] = "catch_block", 3606 [DW_TAG_const_type] = "const_type", 3607 [DW_TAG_constant] = "constant", 3608 [DW_TAG_enumerator] = "enumerator", 3609 [DW_TAG_file_type] = "file_type", 3610 [DW_TAG_friend] = "friend", 3611 [DW_TAG_namelist] = "namelist", 3612 [DW_TAG_namelist_item] = "namelist_item", 3613 [DW_TAG_packed_type] = "packed_type", 3614 [DW_TAG_subprogram] = "subprogram", 3615 [DW_TAG_template_type_param] = "template_type_param", 3616 [DW_TAG_template_value_param] = "template_value_param", 3617 [DW_TAG_thrown_type] = "thrown_type", 3618 [DW_TAG_try_block] = "try_block", 3619 [DW_TAG_variant_part] = "variant_part", 3620 [DW_TAG_variable] = "variable", 3621 [DW_TAG_volatile_type] = "volatile_type" 3622 }; 3623 3624 const char *tagstr; 3625 switch (tag) 3626 { 3627 case DW_TAG_lo_user: 3628 tagstr = "lo_user"; 3629 break; 3630 3631 case DW_TAG_MIPS_loop: 3632 tagstr = "MIPS_loop"; 3633 break; 3634 3635 case DW_TAG_format_label: 3636 tagstr = "format_label"; 3637 break; 3638 3639 case DW_TAG_function_template: 3640 tagstr = "function_template"; 3641 break; 3642 3643 case DW_TAG_class_template: 3644 tagstr = "class_template"; 3645 break; 3646 case DW_TAG_hi_user: 3647 tagstr = "hi_user"; 3648 break; 3649 3650 default: 3651 if (tag < sizeof (lowtags) / sizeof (lowtags[0])) 3652 tagstr = lowtags[tag]; 3653 else 3654 tagstr = "???"; 3655 break; 3656 } 3657 3658 printf (" [%6" PRIx64 "] %*s%s\n", 3659 (uint64_t) offset, (int) (level * 2), "", tagstr); 3660 3661 /* Print the attribute values. */ 3662 args.level = level; 3663 (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0); 3664 3665 /* Make room for the next level's DIE. */ 3666 if (level + 1 == maxdies) 3667 dies = (Dwarf_Die *) xrealloc (dies, 3668 (maxdies += 10) 3669 * sizeof (Dwarf_Die)); 3670 3671 int res = dwarf_child (&dies[level], &dies[level + 1]); 3672 if (res > 0) 3673 { 3674 while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1) 3675 if (level-- == 0) 3676 break; 3677 3678 if (res == -1) 3679 { 3680 error (0, 0, gettext ("cannot get next DIE: %s\n"), 3681 dwarf_errmsg (-1)); 3682 goto do_return; 3683 } 3684 } 3685 else if (unlikely (res < 0)) 3686 { 3687 error (0, 0, gettext ("cannot get next DIE: %s"), 3688 dwarf_errmsg (-1)); 3689 goto do_return; 3690 } 3691 else 3692 ++level; 3693 } 3694 while (level >= 0); 3695 3696 offset = nextcu; 3697 if (offset != 0) 3698 goto next_cu; 3699 3700 do_return: 3701 free (dies); 3702 } 3703 3704 3705 static void 3706 print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 3707 GElf_Shdr *shdr, Dwarf *dbg) 3708 { 3709 printf (gettext ("\ 3710 \nDWARF section '%s' at offset %#" PRIx64 ":\n"), 3711 ".debug_line", (uint64_t) shdr->sh_offset); 3712 3713 if (shdr->sh_size == 0) 3714 return; 3715 3716 /* There is no functionality in libdw to read the information in the 3717 way it is represented here. Hardcode the decoder. */ 3718 Elf_Data *data = elf_getdata (scn, NULL); 3719 if (data == NULL || data->d_buf == NULL) 3720 { 3721 error (0, 0, gettext ("cannot get line data section data: %s"), 3722 elf_errmsg (-1)); 3723 return; 3724 } 3725 3726 const unsigned char *linep = (const unsigned char *) data->d_buf; 3727 const unsigned char *lineendp; 3728 3729 while (linep 3730 < (lineendp = (const unsigned char *) data->d_buf + data->d_size)) 3731 { 3732 size_t start_offset = linep - (const unsigned char *) data->d_buf; 3733 3734 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); 3735 unsigned int length = 4; 3736 if (unlikely (unit_length == 0xffffffff)) 3737 { 3738 if (unlikely (linep + 8 > lineendp)) 3739 { 3740 invalid_data: 3741 error (0, 0, gettext ("invalid data in section [%zu] '%s'"), 3742 elf_ndxscn (scn), ".debug_line"); 3743 return; 3744 } 3745 unit_length = read_8ubyte_unaligned_inc (dbg, linep); 3746 length = 8; 3747 } 3748 3749 /* Check whether we have enough room in the section. */ 3750 if (unit_length < 2 + length + 5 * 1 3751 || unlikely (linep + unit_length > lineendp)) 3752 goto invalid_data; 3753 lineendp = linep + unit_length; 3754 3755 /* The next element of the header is the version identifier. */ 3756 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); 3757 3758 /* Next comes the header length. */ 3759 Dwarf_Word header_length; 3760 if (length == 4) 3761 header_length = read_4ubyte_unaligned_inc (dbg, linep); 3762 else 3763 header_length = read_8ubyte_unaligned_inc (dbg, linep); 3764 //const unsigned char *header_start = linep; 3765 3766 /* Next the minimum instruction length. */ 3767 uint_fast8_t minimum_instr_len = *linep++; 3768 3769 /* Then the flag determining the default value of the is_stmt 3770 register. */ 3771 uint_fast8_t default_is_stmt = *linep++; 3772 3773 /* Now the line base. */ 3774 int_fast8_t line_base = *((const int_fast8_t *) linep); 3775 ++linep; 3776 3777 /* And the line range. */ 3778 uint_fast8_t line_range = *linep++; 3779 3780 /* The opcode base. */ 3781 uint_fast8_t opcode_base = *linep++; 3782 3783 /* Print what we got so far. */ 3784 printf (gettext ("\n" 3785 " Length: %" PRIu64 "\n" 3786 " DWARF version: %" PRIuFAST16 "\n" 3787 " Prologue length: %" PRIu64 "\n" 3788 " Minimum instruction length: %" PRIuFAST8 "\n" 3789 " Initial value if '%s': %" PRIuFAST8 "\n" 3790 " Line base: %" PRIdFAST8 "\n" 3791 " Line range: %" PRIuFAST8 "\n" 3792 " Opcode base: %" PRIuFAST8 "\n" 3793 "\n" 3794 "Opcodes:\n"), 3795 (uint64_t) unit_length, version, (uint64_t) header_length, 3796 minimum_instr_len, "is_stmt", default_is_stmt, line_base, 3797 line_range, opcode_base); 3798 3799 if (unlikely (linep + opcode_base - 1 >= lineendp)) 3800 goto invalid_data; 3801 int opcode_base_l10 = 1; 3802 unsigned int tmp = opcode_base; 3803 while (tmp > 10) 3804 { 3805 tmp /= 10; 3806 ++opcode_base_l10; 3807 } 3808 const uint8_t *standard_opcode_lengths = linep - 1; 3809 for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt) 3810 printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n", 3811 " [%*" PRIuFAST8 "] %hhu arguments\n", 3812 (int) linep[cnt - 1]), 3813 opcode_base_l10, cnt, linep[cnt - 1]); 3814 linep += opcode_base - 1; 3815 if (unlikely (linep >= lineendp)) 3816 goto invalid_data; 3817 3818 puts (gettext ("\nDirectory table:")); 3819 while (*linep != 0) 3820 { 3821 unsigned char *endp = memchr (linep, '\0', lineendp - linep); 3822 if (endp == NULL) 3823 goto invalid_data; 3824 3825 printf (" %s\n", (char *) linep); 3826 3827 linep = endp + 1; 3828 } 3829 /* Skip the final NUL byte. */ 3830 ++linep; 3831 3832 if (unlikely (linep >= lineendp)) 3833 goto invalid_data; 3834 puts (gettext ("\nFile name table:\n" 3835 " Entry Dir Time Size Name")); 3836 for (unsigned int cnt = 1; *linep != 0; ++cnt) 3837 { 3838 /* First comes the file name. */ 3839 char *fname = (char *) linep; 3840 unsigned char *endp = memchr (fname, '\0', lineendp - linep); 3841 if (endp == NULL) 3842 goto invalid_data; 3843 linep = endp + 1; 3844 3845 /* Then the index. */ 3846 unsigned int diridx; 3847 get_uleb128 (diridx, linep); 3848 3849 /* Next comes the modification time. */ 3850 unsigned int mtime; 3851 get_uleb128 (mtime, linep); 3852 3853 /* Finally the length of the file. */ 3854 unsigned int fsize; 3855 get_uleb128 (fsize, linep); 3856 3857 printf (" %-5u %-5u %-9u %-9u %s\n", 3858 cnt, diridx, mtime, fsize, fname); 3859 } 3860 /* Skip the final NUL byte. */ 3861 ++linep; 3862 3863 puts (gettext ("\nLine number statements:")); 3864 Dwarf_Word address = 0; 3865 size_t line = 1; 3866 uint_fast8_t is_stmt = default_is_stmt; 3867 3868 /* Default address value, in case we do not find the CU. */ 3869 size_t address_size 3870 = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8; 3871 3872 /* Determine the CU this block is for. */ 3873 Dwarf_Off cuoffset; 3874 Dwarf_Off ncuoffset = 0; 3875 size_t hsize; 3876 while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize, 3877 NULL, NULL, NULL) == 0) 3878 { 3879 Dwarf_Die cudie; 3880 if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL) 3881 continue; 3882 Dwarf_Attribute stmt_list; 3883 if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL) 3884 continue; 3885 Dwarf_Word lineoff; 3886 if (dwarf_formudata (&stmt_list, &lineoff) != 0) 3887 continue; 3888 if (lineoff == start_offset) 3889 { 3890 /* Found the CU. */ 3891 address_size = cudie.cu->address_size; 3892 break; 3893 } 3894 } 3895 3896 while (linep < lineendp) 3897 { 3898 unsigned int u128; 3899 int s128; 3900 3901 /* Read the opcode. */ 3902 unsigned int opcode = *linep++; 3903 3904 /* Is this a special opcode? */ 3905 if (likely (opcode >= opcode_base)) 3906 { 3907 /* Yes. Handling this is quite easy since the opcode value 3908 is computed with 3909 3910 opcode = (desired line increment - line_base) 3911 + (line_range * address advance) + opcode_base 3912 */ 3913 int line_increment = (line_base 3914 + (opcode - opcode_base) % line_range); 3915 unsigned int address_increment = (minimum_instr_len 3916 * ((opcode - opcode_base) 3917 / line_range)); 3918 3919 /* Perform the increments. */ 3920 line += line_increment; 3921 address += address_increment; 3922 3923 printf (gettext ("\ 3924 special opcode %u: address+%u = %#" PRIx64 ", line%+d = %zu\n"), 3925 opcode, address_increment, (uint64_t) address, 3926 line_increment, line); 3927 } 3928 else if (opcode == 0) 3929 { 3930 /* This an extended opcode. */ 3931 if (unlikely (linep + 2 > lineendp)) 3932 goto invalid_data; 3933 3934 /* The length. */ 3935 unsigned int len = *linep++; 3936 3937 if (unlikely (linep + len > lineendp)) 3938 goto invalid_data; 3939 3940 /* The sub-opcode. */ 3941 opcode = *linep++; 3942 3943 printf (gettext (" extended opcode %u: "), opcode); 3944 3945 switch (opcode) 3946 { 3947 case DW_LNE_end_sequence: 3948 puts (gettext ("end of sequence")); 3949 3950 /* Reset the registers we care about. */ 3951 address = 0; 3952 line = 1; 3953 is_stmt = default_is_stmt; 3954 break; 3955 3956 case DW_LNE_set_address: 3957 if (address_size == 4) 3958 address = read_4ubyte_unaligned_inc (dbg, linep); 3959 else 3960 address = read_8ubyte_unaligned_inc (dbg, linep); 3961 printf (gettext ("set address to %#" PRIx64 "\n"), 3962 (uint64_t) address); 3963 break; 3964 3965 case DW_LNE_define_file: 3966 { 3967 char *fname = (char *) linep; 3968 unsigned char *endp = memchr (linep, '\0', 3969 lineendp - linep); 3970 if (endp == NULL) 3971 goto invalid_data; 3972 linep = endp + 1; 3973 3974 unsigned int diridx; 3975 get_uleb128 (diridx, linep); 3976 Dwarf_Word mtime; 3977 get_uleb128 (mtime, linep); 3978 Dwarf_Word filelength; 3979 get_uleb128 (filelength, linep); 3980 3981 printf (gettext ("\ 3982 define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"), 3983 diridx, (uint64_t) mtime, (uint64_t) filelength, 3984 fname); 3985 } 3986 break; 3987 3988 default: 3989 /* Unknown, ignore it. */ 3990 puts (gettext ("unknown opcode")); 3991 linep += len - 1; 3992 break; 3993 } 3994 } 3995 else if (opcode <= DW_LNS_set_epilog_begin) 3996 { 3997 /* This is a known standard opcode. */ 3998 switch (opcode) 3999 { 4000 case DW_LNS_copy: 4001 /* Takes no argument. */ 4002 puts (gettext (" copy")); 4003 break; 4004 4005 case DW_LNS_advance_pc: 4006 /* Takes one uleb128 parameter which is added to the 4007 address. */ 4008 get_uleb128 (u128, linep); 4009 address += minimum_instr_len * u128; 4010 printf (gettext ("\ 4011 advance address by %u to %#" PRIx64 "\n"), 4012 u128, (uint64_t) address); 4013 break; 4014 4015 case DW_LNS_advance_line: 4016 /* Takes one sleb128 parameter which is added to the 4017 line. */ 4018 get_sleb128 (s128, linep); 4019 line += s128; 4020 printf (gettext ("\ 4021 advance line by constant %d to %" PRId64 "\n"), 4022 s128, (int64_t) line); 4023 break; 4024 4025 case DW_LNS_set_file: 4026 /* Takes one uleb128 parameter which is stored in file. */ 4027 get_uleb128 (u128, linep); 4028 printf (gettext (" set file to %" PRIu64 "\n"), 4029 (uint64_t) u128); 4030 break; 4031 4032 case DW_LNS_set_column: 4033 /* Takes one uleb128 parameter which is stored in column. */ 4034 if (unlikely (standard_opcode_lengths[opcode] != 1)) 4035 goto invalid_data; 4036 4037 get_uleb128 (u128, linep); 4038 printf (gettext (" set column to %" PRIu64 "\n"), 4039 (uint64_t) u128); 4040 break; 4041 4042 case DW_LNS_negate_stmt: 4043 /* Takes no argument. */ 4044 is_stmt = 1 - is_stmt; 4045 printf (gettext (" set '%s' to %" PRIuFAST8 "\n"), 4046 "is_stmt", is_stmt); 4047 break; 4048 4049 case DW_LNS_set_basic_block: 4050 /* Takes no argument. */ 4051 puts (gettext (" set basic block flag")); 4052 break; 4053 4054 case DW_LNS_const_add_pc: 4055 /* Takes no argument. */ 4056 u128 = (minimum_instr_len 4057 * ((255 - opcode_base) / line_range)); 4058 address += u128; 4059 printf (gettext ("\ 4060 advance address by constant %u to %#" PRIx64 "\n"), 4061 u128, (uint64_t) address); 4062 break; 4063 4064 case DW_LNS_fixed_advance_pc: 4065 /* Takes one 16 bit parameter which is added to the 4066 address. */ 4067 if (unlikely (standard_opcode_lengths[opcode] != 1)) 4068 goto invalid_data; 4069 4070 u128 = read_2ubyte_unaligned_inc (dbg, linep); 4071 address += u128; 4072 printf (gettext ("\ 4073 advance address by fixed value %u to %#" PRIx64 "\n"), 4074 u128, (uint64_t) address); 4075 break; 4076 4077 case DW_LNS_set_prologue_end: 4078 /* Takes no argument. */ 4079 puts (gettext (" set prologue end flag")); 4080 break; 4081 4082 case DW_LNS_set_epilog_begin: 4083 /* Takes no argument. */ 4084 puts (gettext (" set epilogue begin flag")); 4085 break; 4086 } 4087 } 4088 else 4089 { 4090 /* This is a new opcode the generator but not we know about. 4091 Read the parameters associated with it but then discard 4092 everything. Read all the parameters for this opcode. */ 4093 printf (ngettext (" unknown opcode with %" PRIu8 " parameter:", 4094 " unknown opcode with %" PRIu8 " parameters:", 4095 standard_opcode_lengths[opcode]), 4096 standard_opcode_lengths[opcode]); 4097 for (int n = standard_opcode_lengths[opcode]; n > 0; --n) 4098 { 4099 get_uleb128 (u128, linep); 4100 if (n != standard_opcode_lengths[opcode]) 4101 putc_unlocked (',', stdout); 4102 printf (" %u", u128); 4103 } 4104 4105 /* Next round, ignore this opcode. */ 4106 continue; 4107 } 4108 } 4109 } 4110 4111 /* There must only be one data block. */ 4112 assert (elf_getdata (scn, data) == NULL); 4113 } 4114 4115 4116 static void 4117 print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 4118 GElf_Shdr *shdr, Dwarf *dbg) 4119 { 4120 printf (gettext ("\ 4121 \nDWARF section '%s' at offset %#" PRIx64 ":\n"), 4122 ".debug_loc", (uint64_t) shdr->sh_offset); 4123 4124 // XXX add something 4125 } 4126 4127 4128 struct mac_culist 4129 { 4130 Dwarf_Die die; 4131 Dwarf_Off offset; 4132 Dwarf_Files *files; 4133 struct mac_culist *next; 4134 }; 4135 4136 4137 static int 4138 mac_compare (const void *p1, const void *p2) 4139 { 4140 struct mac_culist *m1 = (struct mac_culist *) p1; 4141 struct mac_culist *m2 = (struct mac_culist *) p2; 4142 4143 if (m1->offset < m2->offset) 4144 return -1; 4145 if (m1->offset > m2->offset) 4146 return 1; 4147 return 0; 4148 } 4149 4150 4151 static void 4152 print_debug_macinfo_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 4153 GElf_Shdr *shdr, Dwarf *dbg) 4154 { 4155 printf (gettext ("\ 4156 \nDWARF section '%s' at offset %#" PRIx64 ":\n"), 4157 ".debug_macinfo", (uint64_t) shdr->sh_offset); 4158 putc_unlocked ('\n', stdout); 4159 4160 /* There is no function in libdw to iterate over the raw content of 4161 the section but it is easy enough to do. */ 4162 Elf_Data *data = elf_getdata (scn, NULL); 4163 if (data == NULL || data->d_buf == NULL) 4164 { 4165 error (0, 0, gettext ("cannot get macro information section data: %s"), 4166 elf_errmsg (-1)); 4167 return; 4168 } 4169 4170 /* Get the source file information for all CUs. */ 4171 Dwarf_Off offset; 4172 Dwarf_Off ncu = 0; 4173 size_t hsize; 4174 struct mac_culist *culist = NULL; 4175 size_t nculist = 0; 4176 while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0) 4177 { 4178 Dwarf_Die cudie; 4179 if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL) 4180 continue; 4181 4182 Dwarf_Attribute attr; 4183 if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL) 4184 continue; 4185 4186 Dwarf_Word macoff; 4187 if (dwarf_formudata (&attr, &macoff) != 0) 4188 continue; 4189 4190 struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp)); 4191 newp->die = cudie; 4192 newp->offset = macoff; 4193 newp->files = NULL; 4194 newp->next = culist; 4195 culist = newp; 4196 ++nculist; 4197 } 4198 4199 /* Convert the list into an array for easier consumption. */ 4200 struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1) 4201 * sizeof (*cus)); 4202 /* Add sentinel. */ 4203 cus[nculist].offset = data->d_size; 4204 if (nculist > 0) 4205 { 4206 for (size_t cnt = nculist - 1; culist != NULL; --cnt) 4207 { 4208 assert (cnt < nculist); 4209 cus[cnt] = *culist; 4210 culist = culist->next; 4211 } 4212 4213 /* Sort the array according to the offset in the .debug_macinfo 4214 section. Note we keep the sentinel at the end. */ 4215 qsort (cus, nculist, sizeof (*cus), mac_compare); 4216 } 4217 4218 const unsigned char *readp = (const unsigned char *) data->d_buf; 4219 const unsigned char *readendp = readp + data->d_size; 4220 int level = 1; 4221 4222 while (readp < readendp) 4223 { 4224 unsigned int opcode = *readp++; 4225 unsigned int u128; 4226 unsigned int u128_2; 4227 const unsigned char *endp; 4228 4229 switch (opcode) 4230 { 4231 case DW_MACINFO_define: 4232 case DW_MACINFO_undef: 4233 case DW_MACINFO_vendor_ext: 4234 /* For the first two opcodes the parameters are 4235 line, string 4236 For the latter 4237 number, string. 4238 We can treat these cases together. */ 4239 get_uleb128 (u128, readp); 4240 4241 endp = memchr (readp, '\0', readendp - readp); 4242 if (endp == NULL) 4243 { 4244 printf (gettext ("\ 4245 %*s*** non-terminated string at end of section"), 4246 level, ""); 4247 return; 4248 } 4249 4250 if (opcode == DW_MACINFO_define) 4251 printf ("%*s#define %s, line %u\n", 4252 level, "", (char *) readp, u128); 4253 else if (opcode == DW_MACINFO_undef) 4254 printf ("%*s#undef %s, line %u\n", 4255 level, "", (char *) readp, u128); 4256 else 4257 printf (" #vendor-ext %s, number %u\n", (char *) readp, u128); 4258 4259 readp = endp + 1; 4260 break; 4261 4262 case DW_MACINFO_start_file: 4263 /* The two parameters are line and file index, in this order. */ 4264 get_uleb128 (u128, readp); 4265 get_uleb128 (u128_2, readp); 4266 4267 /* Find the CU DIE for this file. */ 4268 ptrdiff_t macoff = readp - (const unsigned char *) data->d_buf; 4269 const char *fname = "???"; 4270 if (macoff >= cus[0].offset) 4271 { 4272 while (macoff >= cus[1].offset) 4273 ++cus; 4274 4275 if (cus[0].files == NULL 4276 && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0) 4277 cus[0].files = (Dwarf_Files *) -1l; 4278 4279 if (cus[0].files != (Dwarf_Files *) -1l) 4280 fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL) 4281 ?: "???"); 4282 } 4283 4284 printf ("%*sstart_file %u, [%u] %s\n", 4285 level, "", u128, u128_2, fname); 4286 ++level; 4287 break; 4288 4289 case DW_MACINFO_end_file: 4290 --level; 4291 printf ("%*send_file\n", level, ""); 4292 /* Nothing more to do. */ 4293 break; 4294 4295 default: 4296 // XXX gcc seems to generate files with a trailing zero. 4297 if (opcode != 0 || readp != readendp) 4298 printf ("%*s*** invalid opcode %u\n", level, "", opcode); 4299 break; 4300 } 4301 } 4302 } 4303 4304 4305 /* Callback for printing global names. */ 4306 static int 4307 print_pubnames (Dwarf *dbg, Dwarf_Global *global, void *arg) 4308 { 4309 int *np = (int *) arg; 4310 4311 printf (gettext (" [%5d] DIE offset: %6" PRId64 4312 ", CU DIE offset: %6" PRId64 ", name: %s\n"), 4313 (*np)++, global->die_offset, global->cu_offset, global->name); 4314 4315 return 0; 4316 } 4317 4318 4319 /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */ 4320 static void 4321 print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 4322 GElf_Shdr *shdr, Dwarf *dbg) 4323 { 4324 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"), 4325 ".debug_pubnames", (uint64_t) shdr->sh_offset); 4326 4327 int n = 0; 4328 (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0); 4329 } 4330 4331 /* Print the content of the DWARF string section '.debug_str'. */ 4332 static void 4333 print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, 4334 GElf_Shdr *shdr, Dwarf *dbg) 4335 { 4336 /* Compute floor(log16(shdr->sh_size)). */ 4337 GElf_Addr tmp = shdr->sh_size; 4338 int digits = 1; 4339 while (tmp >= 16) 4340 { 4341 ++digits; 4342 tmp >>= 4; 4343 } 4344 digits = MAX (4, digits); 4345 4346 printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n" 4347 " %*s String\n"), 4348 ".debug_str", (uint64_t) shdr->sh_offset, 4349 /* TRANS: the debugstr| prefix makes the string unique. */ 4350 digits + 2, sgettext ("debugstr|Offset")); 4351 4352 Dwarf_Off offset = 0; 4353 while (offset < shdr->sh_size) 4354 { 4355 size_t len; 4356 const char *str = dwarf_getstring (dbg, offset, &len); 4357 if (str == NULL) 4358 { 4359 printf (gettext (" *** error while reading strings: %s\n"), 4360 dwarf_errmsg (-1)); 4361 break; 4362 } 4363 4364 printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str); 4365 4366 offset += len + 1; 4367 } 4368 } 4369 4370 4371 static void 4372 print_debug (Ebl *ebl, GElf_Ehdr *ehdr) 4373 { 4374 /* Find the version information sections. For this we have to 4375 search through the section table. */ 4376 Dwarf *dbg; 4377 Elf_Scn *scn; 4378 size_t shstrndx; 4379 4380 /* Before we start the real work get a debug context descriptor. */ 4381 dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL); 4382 if (dbg == NULL) 4383 { 4384 error (0, 0, gettext ("cannot get debug context descriptor: %s"), 4385 dwarf_errmsg (-1)); 4386 return; 4387 } 4388 4389 /* Get the section header string table index. */ 4390 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 4391 error (EXIT_FAILURE, 0, 4392 gettext ("cannot get section header string table index")); 4393 4394 scn = NULL; 4395 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 4396 { 4397 /* Handle the section if it is part of the versioning handling. */ 4398 GElf_Shdr shdr_mem; 4399 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 4400 4401 if (shdr != NULL || shdr->sh_type != SHT_PROGBITS) 4402 { 4403 static const struct 4404 { 4405 const char *name; 4406 enum section_e bitmask; 4407 void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *); 4408 } debug_sections[] = 4409 { 4410 #define NEW_SECTION(name) \ 4411 { ".debug_" #name, section_##name, print_debug_##name##_section } 4412 NEW_SECTION (abbrev), 4413 NEW_SECTION (aranges), 4414 NEW_SECTION (frame), 4415 NEW_SECTION (info), 4416 NEW_SECTION (line), 4417 NEW_SECTION (loc), 4418 NEW_SECTION (pubnames), 4419 NEW_SECTION (str), 4420 NEW_SECTION (macinfo), 4421 { ".eh_frame", section_frame, print_debug_frame_section } 4422 }; 4423 const int ndebug_sections = (sizeof (debug_sections) 4424 / sizeof (debug_sections[0])); 4425 const char *name = elf_strptr (ebl->elf, shstrndx, 4426 shdr->sh_name); 4427 int n; 4428 4429 for (n = 0; n < ndebug_sections; ++n) 4430 if (strcmp (name, debug_sections[n].name) == 0) 4431 { 4432 if (print_debug_sections & debug_sections[n].bitmask) 4433 debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg); 4434 break; 4435 } 4436 } 4437 } 4438 4439 /* We are done with the DWARF handling. */ 4440 dwarf_end (dbg); 4441 } 4442 4443 4444 static void 4445 handle_notes (Ebl *ebl, GElf_Ehdr *ehdr) 4446 { 4447 int class = gelf_getclass (ebl->elf); 4448 size_t cnt; 4449 4450 /* We have to look through the program header to find the note 4451 sections. There can be more than one. */ 4452 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) 4453 { 4454 GElf_Phdr mem; 4455 GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem); 4456 4457 if (phdr == NULL || phdr->p_type != PT_NOTE) 4458 /* Not what we are looking for. */ 4459 continue; 4460 4461 printf (gettext ("\ 4462 \nNote segment of %" PRId64 " bytes at offset %#0" PRIx64 ":\n"), 4463 phdr->p_filesz, phdr->p_offset); 4464 4465 char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz); 4466 if (notemem == NULL) 4467 error (EXIT_FAILURE, 0, 4468 gettext ("cannot get content of note section: %s"), 4469 elf_errmsg (-1)); 4470 4471 fputs_unlocked (gettext (" Owner Data size Type\n"), stdout); 4472 4473 4474 /* Handle the note section content. It consists of one or more 4475 entries each of which consists of five parts: 4476 4477 - a 32-bit name length 4478 - a 32-bit descriptor length 4479 - a 32-bit type field 4480 - the NUL-terminated name, length as specified in the first field 4481 - the descriptor, length as specified in the second field 4482 4483 The variable sized fields are padded to 32- or 64-bits 4484 depending on whether the file is a 32- or 64-bit ELF file. 4485 */ 4486 size_t align = class == ELFCLASS32 ? 4 : 8; 4487 #define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1)) 4488 4489 size_t idx = 0; 4490 while (idx < phdr->p_filesz) 4491 { 4492 /* XXX Handle 64-bit note section entries correctly. */ 4493 struct 4494 { 4495 uint32_t namesz; 4496 uint32_t descsz; 4497 uint32_t type; 4498 char name[0]; 4499 } *noteentry = (__typeof (noteentry)) (notemem + idx); 4500 4501 if (idx + 12 > phdr->p_filesz 4502 || (idx + 12 + ALIGNED_LEN (noteentry->namesz) 4503 + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz)) 4504 /* This entry isn't completely contained in the note 4505 section. Ignore it. */ 4506 break; 4507 4508 char buf[100]; 4509 char buf2[100]; 4510 printf (gettext (" %-13.*s %9" PRId32 " %s\n"), 4511 (int) noteentry->namesz, noteentry->name, 4512 noteentry->descsz, 4513 ehdr->e_type == ET_CORE 4514 ? ebl_core_note_type_name (ebl, noteentry->type, 4515 buf, sizeof (buf)) 4516 : ebl_object_note_type_name (ebl, noteentry->type, 4517 buf2, sizeof (buf2))); 4518 4519 /* Filter out invalid entries. */ 4520 if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL 4521 /* XXX For now help broken Linux kernels. */ 4522 || 1) 4523 { 4524 if (ehdr->e_type == ET_CORE) 4525 ebl_core_note (ebl, noteentry->name, noteentry->type, 4526 noteentry->descsz, 4527 ¬eentry->name[ALIGNED_LEN (noteentry->namesz)]); 4528 else 4529 ebl_object_note (ebl, noteentry->name, noteentry->type, 4530 noteentry->descsz, 4531 ¬eentry->name[ALIGNED_LEN (noteentry->namesz)]); 4532 } 4533 4534 /* Move to the next entry. */ 4535 idx += (12 + ALIGNED_LEN (noteentry->namesz) 4536 + ALIGNED_LEN (noteentry->descsz)); 4537 } 4538 4539 gelf_freechunk (ebl->elf, notemem); 4540 } 4541 } 4542