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