1/* Print information from ELF file in human-readable form. 2 Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper@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 <mcheck.h> 30#include <stdbool.h> 31#include <stdio.h> 32#include <stdio_ext.h> 33#include <stdlib.h> 34#include <string.h> 35#include <unistd.h> 36#include <sys/param.h> 37 38#include <system.h> 39#include "../libebl/libeblP.h" 40 41 42/* Name and version of program. */ 43static void print_version (FILE *stream, struct argp_state *state); 44ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 45 46/* Bug report address. */ 47ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 48 49 50/* Definitions of arguments for argp functions. */ 51static const struct argp_option options[] = 52{ 53 { NULL, 0, NULL, 0, N_("Mode selection:"), 0 }, 54 { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 }, 55 { "full-contents", 's', NULL, 0, 56 N_("Display the full contents of all sections requested"), 0 }, 57 { "disassemble", 'd', NULL, 0, 58 N_("Display assembler code of executable sections"), 0 }, 59 60 { NULL, 0, NULL, 0, N_("Output content selection:"), 0 }, 61 { "section", 'j', "NAME", 0, 62 N_("Only display information for section NAME."), 0 }, 63 64 { NULL, 0, NULL, 0, NULL, 0 } 65}; 66 67/* Short description of program. */ 68static const char doc[] = N_("\ 69Show information from FILEs (a.out by default)."); 70 71/* Strings for arguments in help texts. */ 72static const char args_doc[] = N_("[FILE...]"); 73 74/* Prototype for option handler. */ 75static error_t parse_opt (int key, char *arg, struct argp_state *state); 76 77/* Parser children. */ 78static struct argp_child argp_children[] = 79 { 80 { &color_argp, 0, N_("Output formatting"), 2 }, 81 { NULL, 0, NULL, 0} 82 }; 83 84/* Data structure to communicate with argp functions. */ 85static const struct argp argp = 86{ 87 options, parse_opt, args_doc, doc, argp_children, NULL, NULL 88}; 89 90 91/* Print symbols in file named FNAME. */ 92static int process_file (const char *fname, bool more_than_one); 93 94/* Handle content of archive. */ 95static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname, 96 const char *suffix); 97 98/* Handle ELF file. */ 99static int handle_elf (Elf *elf, const char *prefix, const char *fname, 100 const char *suffix); 101 102 103#define INTERNAL_ERROR(fname) \ 104 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \ 105 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1)) 106 107 108/* List of sections which should be used. */ 109static struct section_list 110{ 111 bool is_name; 112 union 113 { 114 const char *name; 115 uint32_t scnndx; 116 }; 117 struct section_list *next; 118} *section_list; 119 120 121/* If true print archive index. */ 122static bool print_relocs; 123 124/* If true print full contents of requested sections. */ 125static bool print_full_content; 126 127/* If true print disassembled output.. */ 128static bool print_disasm; 129 130 131int 132main (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. */ 177static void 178print_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 ("\ 182Copyright (C) %s Red Hat, Inc.\n\ 183This is free software; see the source for copying conditions. There is NO\n\ 184warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 185"), "2012"); 186 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 187} 188 189 190/* Handle program arguments. */ 191static error_t 192parse_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, 238 program_invocation_short_name); 239 exit (EXIT_FAILURE); 240 } 241 242 default: 243 return ARGP_ERR_UNKNOWN; 244 } 245 return 0; 246} 247 248 249/* Open the file and determine the type. */ 250static int 251process_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 302static int 303handle_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 360static void 361show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata, 362 Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx, 363 GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend) 364{ 365 int elfclass = gelf_getclass (ebl->elf); 366 char buf[128]; 367 368 printf ("%0*" PRIx64 " %-20s ", 369 elfclass == ELFCLASS32 ? 8 : 16, r_offset, 370 ebl_reloc_type_name (ebl, GELF_R_TYPE (r_info), buf, sizeof (buf))); 371 372 Elf32_Word xndx; 373 GElf_Sym symmem; 374 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info), 375 &symmem, &xndx); 376 377 if (sym == NULL) 378 printf ("<%s %ld>", 379 gettext ("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info)); 380 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 381 printf ("%s", 382 elf_strptr (ebl->elf, symstrndx, sym->st_name)); 383 else 384 { 385 GElf_Shdr destshdr_mem; 386 GElf_Shdr *destshdr; 387 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 388 sym->st_shndx == SHN_XINDEX 389 ? xndx : sym->st_shndx), 390 &destshdr_mem); 391 392 if (shdr == NULL || destshdr == NULL) 393 printf ("<%s %ld>", 394 gettext ("INVALID SECTION"), 395 (long int) (sym->st_shndx == SHN_XINDEX 396 ? xndx : sym->st_shndx)); 397 else 398 printf ("%s", 399 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 400 } 401 402 if (r_addend != 0) 403 { 404 char sign = '+'; 405 if (r_addend < 0) 406 { 407 sign = '-'; 408 r_addend = -r_addend; 409 } 410 printf ("%c%#" PRIx64, sign, r_addend); 411 } 412 putchar ('\n'); 413} 414 415 416static void 417show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, 418 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, 419 size_t shstrndx) 420{ 421 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT); 422 int nentries = shdr->sh_size / sh_entsize; 423 424 for (int cnt = 0; cnt < nentries; ++cnt) 425 { 426 GElf_Rel relmem; 427 GElf_Rel *rel; 428 429 rel = gelf_getrel (data, cnt, &relmem); 430 if (rel != NULL) 431 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx, 432 rel->r_offset, rel->r_info, 0); 433 } 434} 435 436 437static void 438show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, 439 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, 440 size_t shstrndx) 441{ 442 size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT); 443 int nentries = shdr->sh_size / sh_entsize; 444 445 for (int cnt = 0; cnt < nentries; ++cnt) 446 { 447 GElf_Rela relmem; 448 GElf_Rela *rel; 449 450 rel = gelf_getrela (data, cnt, &relmem); 451 if (rel != NULL) 452 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx, 453 rel->r_offset, rel->r_info, rel->r_addend); 454 } 455} 456 457 458static bool 459section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx) 460{ 461 if (section_list == NULL) 462 return true; 463 464 struct section_list *runp = section_list; 465 const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); 466 467 do 468 { 469 if (runp->is_name) 470 { 471 if (name && strcmp (runp->name, name) == 0) 472 return true; 473 } 474 else 475 { 476 if (runp->scnndx == scnndx) 477 return true; 478 } 479 480 runp = runp->next; 481 } 482 while (runp != NULL); 483 484 return false; 485} 486 487 488static int 489show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx) 490{ 491 int elfclass = gelf_getclass (ebl->elf); 492 493 Elf_Scn *scn = NULL; 494 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 495 { 496 GElf_Shdr shdr_mem; 497 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 498 499 if (shdr == NULL) 500 INTERNAL_ERROR (fname); 501 502 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 503 { 504 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 505 continue; 506 507 GElf_Shdr destshdr_mem; 508 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, 509 shdr->sh_info), 510 &destshdr_mem); 511 if (unlikely (destshdr == NULL)) 512 continue; 513 514 printf (gettext ("\nRELOCATION RECORDS FOR [%s]:\n" 515 "%-*s TYPE VALUE\n"), 516 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 517 elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET")); 518 519 /* Get the data of the section. */ 520 Elf_Data *data = elf_getdata (scn, NULL); 521 if (data == NULL) 522 continue; 523 524 /* Get the symbol table information. */ 525 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 526 GElf_Shdr symshdr_mem; 527 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 528 Elf_Data *symdata = elf_getdata (symscn, NULL); 529 if (unlikely (symshdr == NULL || symdata == NULL)) 530 continue; 531 532 /* Search for the optional extended section index table. */ 533 Elf_Data *xndxdata = NULL; 534 Elf_Scn *xndxscn = NULL; 535 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL) 536 { 537 GElf_Shdr xndxshdr_mem; 538 GElf_Shdr *xndxshdr; 539 540 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 541 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX 542 && xndxshdr->sh_link == elf_ndxscn (symscn)) 543 { 544 /* Found it. */ 545 xndxdata = elf_getdata (xndxscn, NULL); 546 break; 547 } 548 } 549 550 if (shdr->sh_type == SHT_REL) 551 show_relocs_rel (ebl, shdr, data, symdata, xndxdata, 552 symshdr->sh_link, shstrndx); 553 else 554 show_relocs_rela (ebl, shdr, data, symdata, xndxdata, 555 symshdr->sh_link, shstrndx); 556 557 putchar ('\n'); 558 } 559 } 560 561 return 0; 562} 563 564 565static int 566show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx) 567{ 568 Elf_Scn *scn = NULL; 569 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 570 { 571 GElf_Shdr shdr_mem; 572 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 573 574 if (shdr == NULL) 575 INTERNAL_ERROR (fname); 576 577 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0) 578 { 579 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 580 continue; 581 582 printf (gettext ("Contents of section %s:\n"), 583 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 584 585 /* Get the data of the section. */ 586 Elf_Data *data = elf_getdata (scn, NULL); 587 if (data == NULL) 588 continue; 589 590 unsigned char *cp = data->d_buf; 591 size_t cnt; 592 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16) 593 { 594 printf (" %04zx ", cnt); 595 596 for (size_t inner = 0; inner < 16; inner += 4) 597 printf ("%02hhx%02hhx%02hhx%02hhx ", 598 cp[inner], cp[inner + 1], cp[inner + 2], 599 cp[inner + 3]); 600 fputc_unlocked (' ', stdout); 601 602 for (size_t inner = 0; inner < 16; ++inner) 603 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) 604 ? cp[inner] : '.', stdout); 605 fputc_unlocked ('\n', stdout); 606 } 607 608 printf (" %04zx ", cnt); 609 610 size_t remaining = data->d_size - cnt; 611 size_t inner; 612 for (inner = 0; inner + 4 <= remaining; inner += 4) 613 printf ("%02hhx%02hhx%02hhx%02hhx ", 614 cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]); 615 616 for (; inner < remaining; ++inner) 617 printf ("%02hhx", cp[inner]); 618 619 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0; 620 --inner) 621 fputc_unlocked (' ', stdout); 622 623 for (inner = 0; inner < remaining; ++inner) 624 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) 625 ? cp[inner] : '.', stdout); 626 fputc_unlocked ('\n', stdout); 627 628 fputc_unlocked ('\n', stdout); 629 } 630 } 631 632 return 0; 633} 634 635 636struct disasm_info 637{ 638 GElf_Addr addr; 639 const uint8_t *cur; 640 const uint8_t *last_end; 641 const char *address_color; 642 const char *bytes_color; 643}; 644 645 646// XXX This is not the preferred output for all architectures. Needs 647// XXX customization, too. 648static int 649disasm_output (char *buf, size_t buflen, void *arg) 650{ 651 struct disasm_info *info = (struct disasm_info *) arg; 652 653 if (info->address_color != NULL) 654 printf ("%s%8" PRIx64 "%s: ", 655 info->address_color, (uint64_t) info->addr, color_off); 656 else 657 printf ("%8" PRIx64 ": ", (uint64_t) info->addr); 658 659 if (info->bytes_color != NULL) 660 fputs_unlocked (info->bytes_color, stdout); 661 size_t cnt; 662 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt) 663 printf (" %02" PRIx8, info->last_end[cnt]); 664 if (info->bytes_color != NULL) 665 fputs_unlocked (color_off, stdout); 666 667 printf ("%*s %.*s\n", 668 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf); 669 670 info->addr += cnt; 671 672 /* We limit the number of bytes printed before the mnemonic to 8. 673 Print the rest on a separate, following line. */ 674 if (info->cur - info->last_end > 8) 675 { 676 if (info->address_color != NULL) 677 printf ("%s%8" PRIx64 "%s: ", 678 info->address_color, (uint64_t) info->addr, color_off); 679 else 680 printf ("%8" PRIx64 ": ", (uint64_t) info->addr); 681 682 if (info->bytes_color != NULL) 683 fputs_unlocked (info->bytes_color, stdout); 684 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt) 685 printf (" %02" PRIx8, info->last_end[cnt]); 686 if (info->bytes_color != NULL) 687 fputs_unlocked (color_off, stdout); 688 putchar_unlocked ('\n'); 689 info->addr += info->cur - info->last_end - 8; 690 } 691 692 info->last_end = info->cur; 693 694 return 0; 695} 696 697 698static int 699show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx) 700{ 701 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */); 702 if (ctx == NULL) 703 error (EXIT_FAILURE, 0, gettext ("cannot disassemble")); 704 705 Elf_Scn *scn = NULL; 706 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 707 { 708 GElf_Shdr shdr_mem; 709 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 710 711 if (shdr == NULL) 712 INTERNAL_ERROR (fname); 713 714 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0 715 && (shdr->sh_flags & SHF_EXECINSTR) != 0) 716 { 717 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 718 continue; 719 720 Elf_Data *data = elf_getdata (scn, NULL); 721 if (data == NULL) 722 continue; 723 724 printf ("Disassembly of section %s:\n\n", 725 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 726 727 struct disasm_info info; 728 info.addr = shdr->sh_addr; 729 info.last_end = info.cur = data->d_buf; 730 char *fmt; 731 if (color_mode) 732 { 733 info.address_color = color_address; 734 info.bytes_color = color_bytes; 735 736 if (asprintf (&fmt, "%s%%7m %s%%.1o,%s%%.2o,%s%%.3o%%34a %s%%l", 737 color_mnemonic ?: "", 738 color_operand1 ?: "", 739 color_operand2 ?: "", 740 color_operand3 ?: "", 741 color_label ?: "") < 0) 742 error (EXIT_FAILURE, errno, _("cannot allocate memory")); 743 } 744 else 745 { 746 info.address_color = info.bytes_color = NULL; 747 748 fmt = "%7m %.1o,%.2o,%.3o%34a %l"; 749 } 750 751 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr, 752 fmt, disasm_output, &info, NULL /* XXX */); 753 754 if (color_mode) 755 free (fmt); 756 } 757 } 758 759 (void) disasm_end (ctx); 760 761 return 0; 762} 763 764 765static int 766handle_elf (Elf *elf, const char *prefix, const char *fname, 767 const char *suffix) 768{ 769 770 /* Get the backend for this object file type. */ 771 Ebl *ebl = ebl_openbackend (elf); 772 773 printf ("%s: elf%d-%s\n\n", 774 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64, 775 ebl_backend_name (ebl)); 776 777 /* Create the full name of the file. */ 778 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 779 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix); 780 size_t fname_len = strlen (fname) + 1; 781 char fullname[prefix_len + 1 + fname_len + suffix_len]; 782 char *cp = fullname; 783 if (prefix != NULL) 784 cp = mempcpy (cp, prefix, prefix_len); 785 cp = mempcpy (cp, fname, fname_len); 786 if (suffix != NULL) 787 memcpy (cp - 1, suffix, suffix_len + 1); 788 789 /* Get the section header string table index. */ 790 size_t shstrndx; 791 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0) 792 error (EXIT_FAILURE, 0, 793 gettext ("cannot get section header string table index")); 794 795 int result = 0; 796 if (print_disasm) 797 result = show_disasm (ebl, fullname, shstrndx); 798 if (print_relocs && !print_disasm) 799 result = show_relocs (ebl, fullname, shstrndx); 800 if (print_full_content) 801 result = show_full_content (ebl, fullname, shstrndx); 802 803 /* Close the ELF backend library descriptor. */ 804 ebl_closebackend (ebl); 805 806 return result; 807} 808 809 810#include "debugpred.h" 811