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