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