1 /* Print information from ELF file in human-readable form. 2 Copyright (C) 2005, 2006, 2007 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 2005. 5 6 Red Hat elfutils is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by the 8 Free Software Foundation; version 2 of the License. 9 10 Red Hat elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with Red Hat elfutils; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18 19 Red Hat elfutils is an included package of the Open Invention Network. 20 An included package of the Open Invention Network is a package for which 21 Open Invention Network licensees cross-license their patents. No patent 22 license is granted, either expressly or impliedly, by designation as an 23 included package. Should you wish to participate in the Open Invention 24 Network licensing program, please visit www.openinventionnetwork.com 25 <http://www.openinventionnetwork.com>. */ 26 27 #ifdef HAVE_CONFIG_H 28 # include <config.h> 29 #endif 30 31 #include <argp.h> 32 #include <error.h> 33 #include <fcntl.h> 34 #include <inttypes.h> 35 #include <libintl.h> 36 #include <locale.h> 37 #include <mcheck.h> 38 #include <stdbool.h> 39 #include <stdio.h> 40 #include <stdio_ext.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 #include <sys/param.h> 45 46 #include <system.h> 47 #include "../libebl/libeblP.h" 48 49 50 /* Name and version of program. */ 51 static void print_version (FILE *stream, struct argp_state *state); 52 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; 53 54 /* Bug report address. */ 55 const char *argp_program_bug_address = PACKAGE_BUGREPORT; 56 57 58 /* Definitions of arguments for argp functions. */ 59 static const struct argp_option options[] = 60 { 61 { NULL, 0, NULL, 0, N_("Mode selection:"), 0 }, 62 { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 }, 63 { "full-contents", 's', NULL, 0, 64 N_("Display the full contents of all sections requested"), 0 }, 65 { "disassemble", 'd', NULL, 0, 66 N_("Display assembler code of executable sections"), 0 }, 67 68 { NULL, 0, NULL, 0, N_("Output option selection:"), 0 }, 69 { "section", 'j', "NAME", 0, 70 N_("Only display information for section NAME."), 0 }, 71 72 { NULL, 0, NULL, 0, NULL, 0 } 73 }; 74 75 /* Short description of program. */ 76 static const char doc[] = N_("\ 77 Show information from FILEs (a.out by default)."); 78 79 /* Strings for arguments in help texts. */ 80 static const char args_doc[] = N_("[FILE...]"); 81 82 /* Prototype for option handler. */ 83 static error_t parse_opt (int key, char *arg, struct argp_state *state); 84 85 /* Data structure to communicate with argp functions. */ 86 static struct argp argp = 87 { 88 options, parse_opt, args_doc, doc, NULL, NULL, NULL 89 }; 90 91 92 /* Print symbols in file named FNAME. */ 93 static int process_file (const char *fname, bool more_than_one); 94 95 /* Handle content of archive. */ 96 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname, 97 const char *suffix); 98 99 /* Handle ELF file. */ 100 static int handle_elf (Elf *elf, const char *prefix, const char *fname, 101 const char *suffix); 102 103 104 #define INTERNAL_ERROR(fname) \ 105 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \ 106 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1)) 107 108 109 /* List of sections which should be used. */ 110 static struct section_list 111 { 112 bool is_name; 113 union 114 { 115 const char *name; 116 uint32_t scnndx; 117 }; 118 struct section_list *next; 119 } *section_list; 120 121 122 /* If true print archive index. */ 123 static bool print_relocs; 124 125 /* If true print full contents of requested sections. */ 126 static bool print_full_content; 127 128 /* If true print disassembled output.. */ 129 static bool print_disasm; 130 131 int 132 main (int argc, char *argv[]) 133 { 134 /* Make memory leak detection possible. */ 135 mtrace (); 136 137 /* We use no threads here which can interfere with handling a stream. */ 138 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER); 139 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); 140 (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER); 141 142 /* Set locale. */ 143 (void) setlocale (LC_ALL, ""); 144 145 /* Make sure the message catalog can be found. */ 146 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); 147 148 /* Initialize the message catalog. */ 149 (void) textdomain (PACKAGE_TARNAME); 150 151 /* Parse and process arguments. */ 152 int remaining; 153 (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL); 154 155 /* Tell the library which version we are expecting. */ 156 (void) elf_version (EV_CURRENT); 157 158 int result = 0; 159 if (remaining == argc) 160 /* The user didn't specify a name so we use a.out. */ 161 result = process_file ("a.out", false); 162 else 163 { 164 /* Process all the remaining files. */ 165 const bool more_than_one = remaining + 1 < argc; 166 167 do 168 result |= process_file (argv[remaining], more_than_one); 169 while (++remaining < argc); 170 } 171 172 return result; 173 } 174 175 176 /* Print the version information. */ 177 static void 178 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 179 { 180 fprintf (stream, "objdump (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 181 fprintf (stream, gettext ("\ 182 Copyright (C) %s Red Hat, Inc.\n\ 183 This is free software; see the source for copying conditions. There is NO\n\ 184 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 185 "), "2008"); 186 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 187 } 188 189 190 /* Handle program arguments. */ 191 static error_t 192 parse_opt (int key, char *arg, 193 struct argp_state *state __attribute__ ((unused))) 194 { 195 /* True if any of the control options is set. */ 196 static bool any_control_option; 197 198 switch (key) 199 { 200 case 'j': 201 { 202 struct section_list *newp = xmalloc (sizeof (*newp)); 203 char *endp; 204 newp->scnndx = strtoul (arg, &endp, 0); 205 if (*endp == 0) 206 newp->is_name = false; 207 else 208 { 209 newp->name = arg; 210 newp->is_name = true; 211 } 212 newp->next = section_list; 213 section_list = newp; 214 } 215 any_control_option = true; 216 break; 217 218 case 'd': 219 print_disasm = true; 220 any_control_option = true; 221 break; 222 223 case 'r': 224 print_relocs = true; 225 any_control_option = true; 226 break; 227 228 case 's': 229 print_full_content = true; 230 any_control_option = true; 231 break; 232 233 case ARGP_KEY_FINI: 234 if (! any_control_option) 235 { 236 fputs (gettext ("No operation specified.\n"), stderr); 237 argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, 238 program_invocation_short_name); 239 exit (1); 240 } 241 242 default: 243 return ARGP_ERR_UNKNOWN; 244 } 245 return 0; 246 } 247 248 249 /* Open the file and determine the type. */ 250 static int 251 process_file (const char *fname, bool more_than_one) 252 { 253 /* Open the file. */ 254 int fd = open (fname, O_RDONLY); 255 if (fd == -1) 256 { 257 error (0, errno, gettext ("cannot open %s"), fname); 258 return 1; 259 } 260 261 /* Now get the ELF descriptor. */ 262 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 263 if (elf != NULL) 264 { 265 if (elf_kind (elf) == ELF_K_ELF) 266 { 267 int result = handle_elf (elf, more_than_one ? "" : NULL, 268 fname, NULL); 269 270 if (elf_end (elf) != 0) 271 INTERNAL_ERROR (fname); 272 273 if (close (fd) != 0) 274 error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname); 275 276 return result; 277 } 278 else if (elf_kind (elf) == ELF_K_AR) 279 { 280 int result = handle_ar (fd, elf, NULL, fname, NULL); 281 282 if (elf_end (elf) != 0) 283 INTERNAL_ERROR (fname); 284 285 if (close (fd) != 0) 286 error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname); 287 288 return result; 289 } 290 291 /* We cannot handle this type. Close the descriptor anyway. */ 292 if (elf_end (elf) != 0) 293 INTERNAL_ERROR (fname); 294 } 295 296 error (0, 0, gettext ("%s: File format not recognized"), fname); 297 298 return 1; 299 } 300 301 302 static int 303 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname, 304 const char *suffix) 305 { 306 size_t fname_len = strlen (fname) + 1; 307 size_t prefix_len = prefix != NULL ? strlen (prefix) : 0; 308 char new_prefix[prefix_len + fname_len + 2]; 309 size_t suffix_len = suffix != NULL ? strlen (suffix) : 0; 310 char new_suffix[suffix_len + 2]; 311 Elf *subelf; 312 Elf_Cmd cmd = ELF_C_READ_MMAP; 313 int result = 0; 314 315 char *cp = new_prefix; 316 if (prefix != NULL) 317 cp = stpcpy (cp, prefix); 318 cp = stpcpy (cp, fname); 319 stpcpy (cp, "["); 320 321 cp = new_suffix; 322 if (suffix != NULL) 323 cp = stpcpy (cp, suffix); 324 stpcpy (cp, "]"); 325 326 /* Process all the files contained in the archive. */ 327 while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 328 { 329 /* The the header for this element. */ 330 Elf_Arhdr *arhdr = elf_getarhdr (subelf); 331 332 /* Skip over the index entries. */ 333 if (strcmp (arhdr->ar_name, "/") != 0 334 && strcmp (arhdr->ar_name, "//") != 0) 335 { 336 if (elf_kind (subelf) == ELF_K_ELF) 337 result |= handle_elf (subelf, new_prefix, arhdr->ar_name, 338 new_suffix); 339 else if (elf_kind (subelf) == ELF_K_AR) 340 result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, 341 new_suffix); 342 else 343 { 344 error (0, 0, gettext ("%s%s%s: file format not recognized"), 345 new_prefix, arhdr->ar_name, new_suffix); 346 result = 1; 347 } 348 } 349 350 /* Get next archive element. */ 351 cmd = elf_next (subelf); 352 if (elf_end (subelf) != 0) 353 INTERNAL_ERROR (fname); 354 } 355 356 return result; 357 } 358 359 360 static void 361 show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, 362 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, 363 size_t shstrndx) 364 { 365 int elfclass = gelf_getclass (ebl->elf); 366 int nentries = shdr->sh_size / shdr->sh_entsize; 367 368 for (int cnt = 0; cnt < nentries; ++cnt) 369 { 370 GElf_Rel relmem; 371 GElf_Rel *rel; 372 373 rel = gelf_getrel (data, cnt, &relmem); 374 if (rel != NULL) 375 { 376 char buf[128]; 377 GElf_Sym symmem; 378 GElf_Sym *sym; 379 Elf32_Word xndx; 380 381 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info), 382 &symmem, &xndx); 383 if (sym == NULL) 384 printf ("%0*" PRIx64 " %-20s <%s %ld>\n", 385 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 386 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 387 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 388 buf, sizeof (buf)) 389 : gettext ("<INVALID RELOC>"), 390 gettext ("INVALID SYMBOL"), 391 (long int) GELF_R_SYM (rel->r_info)); 392 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 393 printf ("%0*" PRIx64 " %-20s %s\n", 394 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 395 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 396 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 397 buf, sizeof (buf)) 398 : gettext ("<INVALID RELOC>"), 399 elf_strptr (ebl->elf, symstrndx, sym->st_name)); 400 else 401 { 402 GElf_Shdr destshdr_mem; 403 GElf_Shdr *destshdr; 404 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 405 sym->st_shndx == SHN_XINDEX 406 ? xndx : sym->st_shndx), 407 &destshdr_mem); 408 409 if (shdr == NULL) 410 printf ("%0*" PRIx64 " %-20s <%s %ld>\n", 411 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 412 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 413 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 414 buf, sizeof (buf)) 415 : gettext ("<INVALID RELOC>"), 416 gettext ("INVALID SECTION"), 417 (long int) (sym->st_shndx == SHN_XINDEX 418 ? xndx : sym->st_shndx)); 419 else 420 printf ("%0*" PRIx64 " %-20s %s\n", 421 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 422 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 423 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 424 buf, sizeof (buf)) 425 : gettext ("<INVALID RELOC>"), 426 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 427 } 428 } 429 } 430 } 431 432 433 static void 434 show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, 435 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, 436 size_t shstrndx) 437 { 438 int elfclass = gelf_getclass (ebl->elf); 439 int nentries = shdr->sh_size / shdr->sh_entsize; 440 441 for (int cnt = 0; cnt < nentries; ++cnt) 442 { 443 GElf_Rela relmem; 444 GElf_Rela *rel; 445 446 rel = gelf_getrela (data, cnt, &relmem); 447 if (rel != NULL) 448 { 449 char buf[128]; 450 GElf_Sym symmem; 451 GElf_Sym *sym; 452 Elf32_Word xndx; 453 454 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info), 455 &symmem, &xndx); 456 if (sym == NULL) 457 printf ("%0*" PRIx64 " %-20s <%s %ld>", 458 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 459 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 460 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 461 buf, sizeof (buf)) 462 : gettext ("<INVALID RELOC>"), 463 gettext ("INVALID SYMBOL"), 464 (long int) GELF_R_SYM (rel->r_info)); 465 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 466 printf ("%0*" PRIx64 " %-20s %s", 467 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 468 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 469 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 470 buf, sizeof (buf)) 471 : gettext ("<INVALID RELOC>"), 472 elf_strptr (ebl->elf, symstrndx, sym->st_name)); 473 else 474 { 475 GElf_Shdr destshdr_mem; 476 GElf_Shdr *destshdr; 477 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 478 sym->st_shndx == SHN_XINDEX 479 ? xndx : sym->st_shndx), 480 &destshdr_mem); 481 482 if (shdr == NULL) 483 printf ("%0*" PRIx64 " %-20s <%s %ld>", 484 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 485 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 486 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 487 buf, sizeof (buf)) 488 : gettext ("<INVALID RELOC>"), 489 gettext ("INVALID SECTION"), 490 (long int) (sym->st_shndx == SHN_XINDEX 491 ? xndx : sym->st_shndx)); 492 else 493 printf ("%0*" PRIx64 " %-20s %s", 494 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 495 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 496 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 497 buf, sizeof (buf)) 498 : gettext ("<INVALID RELOC>"), 499 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 500 } 501 502 if (rel->r_addend != 0) 503 printf ("+%#" PRIx64, rel->r_addend); 504 putchar ('\n'); 505 } 506 } 507 } 508 509 510 static bool 511 section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx) 512 { 513 if (section_list == NULL) 514 return true; 515 516 struct section_list *runp = section_list; 517 518 do 519 { 520 if (runp->is_name) 521 { 522 if (strcmp (runp->name, 523 elf_strptr (elf, shstrndx, shdr->sh_name)) == 0) 524 return true; 525 } 526 else 527 { 528 if (runp->scnndx == scnndx) 529 return true; 530 } 531 532 runp = runp->next; 533 } 534 while (runp != NULL); 535 536 return false; 537 } 538 539 540 static int 541 show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx) 542 { 543 int elfclass = gelf_getclass (ebl->elf); 544 545 Elf_Scn *scn = NULL; 546 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 547 { 548 GElf_Shdr shdr_mem; 549 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 550 551 if (shdr == NULL) 552 INTERNAL_ERROR (fname); 553 554 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 555 { 556 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 557 continue; 558 559 GElf_Shdr destshdr_mem; 560 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, 561 shdr->sh_info), 562 &destshdr_mem); 563 564 printf (gettext ("RELOCATION RECORDS FOR [%s]:\n" 565 "%-*s TYPE VALUE\n"), 566 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 567 elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET")); 568 569 /* Get the data of the section. */ 570 Elf_Data *data = elf_getdata (scn, NULL); 571 if (data == NULL) 572 continue; 573 574 /* Get the symbol table information. */ 575 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 576 GElf_Shdr symshdr_mem; 577 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 578 Elf_Data *symdata = elf_getdata (symscn, NULL); 579 580 /* Search for the optional extended section index table. */ 581 Elf_Data *xndxdata = NULL; 582 Elf_Scn *xndxscn = NULL; 583 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL) 584 { 585 GElf_Shdr xndxshdr_mem; 586 GElf_Shdr *xndxshdr; 587 588 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 589 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX 590 && xndxshdr->sh_link == elf_ndxscn (symscn)) 591 { 592 /* Found it. */ 593 xndxdata = elf_getdata (xndxscn, NULL); 594 break; 595 } 596 } 597 598 if (shdr->sh_type == SHT_REL) 599 show_relocs_rel (ebl, shdr, data, symdata, xndxdata, 600 symshdr->sh_link, shstrndx); 601 else 602 show_relocs_rela (ebl, shdr, data, symdata, xndxdata, 603 symshdr->sh_link, shstrndx); 604 } 605 } 606 607 fputs_unlocked ("\n\n", stdout); 608 609 return 0; 610 } 611 612 613 static int 614 show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx) 615 { 616 Elf_Scn *scn = NULL; 617 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 618 { 619 GElf_Shdr shdr_mem; 620 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 621 622 if (shdr == NULL) 623 INTERNAL_ERROR (fname); 624 625 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0) 626 { 627 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 628 continue; 629 630 printf (gettext ("Contents of section %s:\n"), 631 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 632 633 /* Get the data of the section. */ 634 Elf_Data *data = elf_getdata (scn, NULL); 635 if (data == NULL) 636 continue; 637 638 unsigned char *cp = data->d_buf; 639 size_t cnt; 640 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16) 641 { 642 printf (" %04zx ", cnt); 643 644 for (size_t inner = 0; inner < 16; inner += 4) 645 printf ("%02hhx%02hhx%02hhx%02hhx ", 646 cp[inner], cp[inner + 1], cp[inner + 2], 647 cp[inner + 3]); 648 fputc_unlocked (' ', stdout); 649 650 for (size_t inner = 0; inner < 16; ++inner) 651 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) 652 ? cp[inner] : '.', stdout); 653 fputc_unlocked ('\n', stdout); 654 } 655 656 printf (" %04zx ", cnt); 657 658 size_t remaining = data->d_size - cnt; 659 size_t inner; 660 for (inner = 0; inner + 4 <= remaining; inner += 4) 661 printf ("%02hhx%02hhx%02hhx%02hhx ", 662 cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]); 663 664 for (; inner < remaining; ++inner) 665 printf ("%02hhx", cp[inner]); 666 667 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0; 668 --inner) 669 fputc_unlocked (' ', stdout); 670 671 for (inner = 0; inner < remaining; ++inner) 672 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) 673 ? cp[inner] : '.', stdout); 674 fputc_unlocked ('\n', stdout); 675 676 fputc_unlocked ('\n', stdout); 677 } 678 } 679 680 return 0; 681 } 682 683 684 struct disasm_info 685 { 686 GElf_Addr addr; 687 const uint8_t *cur; 688 const uint8_t *last_end; 689 }; 690 691 692 // XXX This is not the preferred output for all architectures. Needs 693 // XXX customization, too. 694 static int 695 disasm_output (char *buf, size_t buflen, void *arg) 696 { 697 struct disasm_info *info = (struct disasm_info *) arg; 698 699 printf ("%8" PRIx64 ": ", (uint64_t) info->addr); 700 size_t cnt; 701 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt) 702 printf (" %02" PRIx8, info->last_end[cnt]); 703 printf ("%*s %.*s\n", 704 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf); 705 706 info->addr += cnt; 707 708 /* We limit the number of bytes printed before the mnemonic to 8. 709 Print the rest on a separate, following line. */ 710 if (info->cur - info->last_end > 8) 711 { 712 printf ("%8" PRIx64 ": ", (uint64_t) info->addr); 713 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt) 714 printf (" %02" PRIx8, info->last_end[cnt]); 715 putchar_unlocked ('\n'); 716 info->addr += info->cur - info->last_end - 8; 717 } 718 719 info->last_end = info->cur; 720 721 return 0; 722 } 723 724 725 static int 726 show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx) 727 { 728 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */); 729 if (ctx == NULL) 730 error (EXIT_FAILURE, 0, gettext ("cannot disassemble")); 731 732 Elf_Scn *scn = NULL; 733 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 734 { 735 GElf_Shdr shdr_mem; 736 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 737 738 if (shdr == NULL) 739 INTERNAL_ERROR (fname); 740 741 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0 742 && (shdr->sh_flags & SHF_EXECINSTR) != 0) 743 { 744 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 745 continue; 746 747 Elf_Data *data = elf_getdata (scn, NULL); 748 if (data == NULL) 749 continue; 750 751 printf ("Disassembly of section %s:\n\n", 752 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 753 754 struct disasm_info info; 755 info.addr = shdr->sh_addr; 756 info.last_end = info.cur = data->d_buf; 757 758 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr, 759 "%7m %.1o,%.2o,%.3o%34a %l", disasm_output, &info, 760 NULL /* XXX */); 761 } 762 } 763 764 (void) disasm_end (ctx); 765 766 return 0; 767 } 768 769 770 static int 771 handle_elf (Elf *elf, const char *prefix, const char *fname, 772 const char *suffix) 773 { 774 775 /* Get the backend for this object file type. */ 776 Ebl *ebl = ebl_openbackend (elf); 777 778 printf ("%s: elf%d-%s\n\n", 779 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64, 780 ebl_backend_name (ebl)); 781 782 /* Create the full name of the file. */ 783 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 784 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix); 785 size_t fname_len = strlen (fname) + 1; 786 char fullname[prefix_len + 1 + fname_len + suffix_len]; 787 char *cp = fullname; 788 if (prefix != NULL) 789 cp = mempcpy (cp, prefix, prefix_len); 790 cp = mempcpy (cp, fname, fname_len); 791 if (suffix != NULL) 792 memcpy (cp - 1, suffix, suffix_len + 1); 793 794 /* Get the section header string table index. */ 795 size_t shstrndx; 796 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 797 error (EXIT_FAILURE, 0, 798 gettext ("cannot get section header string table index")); 799 800 int result = 0; 801 if (print_disasm) 802 result = show_disasm (ebl, fullname, shstrndx); 803 if (print_relocs && !print_disasm) 804 result = show_relocs (ebl, fullname, shstrndx); 805 if (print_full_content) 806 result = show_full_content (ebl, fullname, shstrndx); 807 808 /* Close the ELF backend library descriptor. */ 809 ebl_closebackend (ebl); 810 811 return result; 812 } 813 814 815 #include "debugpred.h" 816