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