objdump.c revision cbb422eb102660d97209ec632e3b6572f0b0c7a6
1/* Print information from ELF file in human-readable form. 2 Copyright (C) 2005, 2006, 2007, 2009 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 option 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/* Data structure to communicate with argp functions. */ 86static struct argp argp = 87{ 88 options, parse_opt, args_doc, doc, NULL, NULL, NULL 89}; 90 91 92/* Print symbols in file named FNAME. */ 93static int process_file (const char *fname, bool more_than_one); 94 95/* Handle content of archive. */ 96static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname, 97 const char *suffix); 98 99/* Handle ELF file. */ 100static int handle_elf (Elf *elf, const char *prefix, const char *fname, 101 const char *suffix); 102 103 104#define INTERNAL_ERROR(fname) \ 105 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \ 106 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1)) 107 108 109/* List of sections which should be used. */ 110static struct section_list 111{ 112 bool is_name; 113 union 114 { 115 const char *name; 116 uint32_t scnndx; 117 }; 118 struct section_list *next; 119} *section_list; 120 121 122/* If true print archive index. */ 123static bool print_relocs; 124 125/* If true print full contents of requested sections. */ 126static bool print_full_content; 127 128/* If true print disassembled output.. */ 129static bool print_disasm; 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"), "20089"); 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_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, 362 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, 363 size_t shstrndx) 364{ 365 int elfclass = gelf_getclass (ebl->elf); 366 int nentries = shdr->sh_size / shdr->sh_entsize; 367 368 for (int cnt = 0; cnt < nentries; ++cnt) 369 { 370 GElf_Rel relmem; 371 GElf_Rel *rel; 372 373 rel = gelf_getrel (data, cnt, &relmem); 374 if (rel != NULL) 375 { 376 char buf[128]; 377 GElf_Sym symmem; 378 GElf_Sym *sym; 379 Elf32_Word xndx; 380 381 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info), 382 &symmem, &xndx); 383 if (sym == NULL) 384 printf ("%0*" PRIx64 " %-20s <%s %ld>\n", 385 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 386 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 387 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 388 buf, sizeof (buf)) 389 : gettext ("<INVALID RELOC>"), 390 gettext ("INVALID SYMBOL"), 391 (long int) GELF_R_SYM (rel->r_info)); 392 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 393 printf ("%0*" PRIx64 " %-20s %s\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 elf_strptr (ebl->elf, symstrndx, sym->st_name)); 400 else 401 { 402 GElf_Shdr destshdr_mem; 403 GElf_Shdr *destshdr; 404 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 405 sym->st_shndx == SHN_XINDEX 406 ? xndx : sym->st_shndx), 407 &destshdr_mem); 408 409 if (shdr == NULL) 410 printf ("%0*" PRIx64 " %-20s <%s %ld>\n", 411 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 412 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 413 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 414 buf, sizeof (buf)) 415 : gettext ("<INVALID RELOC>"), 416 gettext ("INVALID SECTION"), 417 (long int) (sym->st_shndx == SHN_XINDEX 418 ? xndx : sym->st_shndx)); 419 else 420 printf ("%0*" PRIx64 " %-20s %s\n", 421 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 422 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 423 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 424 buf, sizeof (buf)) 425 : gettext ("<INVALID RELOC>"), 426 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 427 } 428 } 429 } 430} 431 432 433static void 434show_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 int elfclass = gelf_getclass (ebl->elf); 439 int nentries = shdr->sh_size / shdr->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 { 449 char buf[128]; 450 GElf_Sym symmem; 451 GElf_Sym *sym; 452 Elf32_Word xndx; 453 454 sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info), 455 &symmem, &xndx); 456 if (sym == NULL) 457 printf ("%0*" PRIx64 " %-20s <%s %ld>", 458 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 459 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 460 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 461 buf, sizeof (buf)) 462 : gettext ("<INVALID RELOC>"), 463 gettext ("INVALID SYMBOL"), 464 (long int) GELF_R_SYM (rel->r_info)); 465 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) 466 printf ("%0*" PRIx64 " %-20s %s", 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 elf_strptr (ebl->elf, symstrndx, sym->st_name)); 473 else 474 { 475 GElf_Shdr destshdr_mem; 476 GElf_Shdr *destshdr; 477 destshdr = gelf_getshdr (elf_getscn (ebl->elf, 478 sym->st_shndx == SHN_XINDEX 479 ? xndx : sym->st_shndx), 480 &destshdr_mem); 481 482 if (shdr == NULL) 483 printf ("%0*" PRIx64 " %-20s <%s %ld>", 484 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 485 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 486 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 487 buf, sizeof (buf)) 488 : gettext ("<INVALID RELOC>"), 489 gettext ("INVALID SECTION"), 490 (long int) (sym->st_shndx == SHN_XINDEX 491 ? xndx : sym->st_shndx)); 492 else 493 printf ("%0*" PRIx64 " %-20s %s", 494 elfclass == ELFCLASS32 ? 8 : 16, rel->r_offset, 495 ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) 496 ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), 497 buf, sizeof (buf)) 498 : gettext ("<INVALID RELOC>"), 499 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); 500 } 501 502 if (rel->r_addend != 0) 503 { 504 char sign = '+'; 505 if (rel->r_addend < 0) 506 { 507 sign = '-'; 508 rel->r_addend = -rel->r_addend; 509 } 510 printf ("%c%#" PRIx64, sign, rel->r_addend); 511 } 512 putchar ('\n'); 513 } 514 } 515} 516 517 518static bool 519section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx) 520{ 521 if (section_list == NULL) 522 return true; 523 524 struct section_list *runp = section_list; 525 526 do 527 { 528 if (runp->is_name) 529 { 530 if (strcmp (runp->name, 531 elf_strptr (elf, shstrndx, shdr->sh_name)) == 0) 532 return true; 533 } 534 else 535 { 536 if (runp->scnndx == scnndx) 537 return true; 538 } 539 540 runp = runp->next; 541 } 542 while (runp != NULL); 543 544 return false; 545} 546 547 548static int 549show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx) 550{ 551 int elfclass = gelf_getclass (ebl->elf); 552 553 Elf_Scn *scn = NULL; 554 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 555 { 556 GElf_Shdr shdr_mem; 557 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 558 559 if (shdr == NULL) 560 INTERNAL_ERROR (fname); 561 562 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 563 { 564 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 565 continue; 566 567 GElf_Shdr destshdr_mem; 568 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, 569 shdr->sh_info), 570 &destshdr_mem); 571 572 printf (gettext ("\n\nRELOCATION RECORDS FOR [%s]:\n" 573 "%-*s TYPE VALUE\n"), 574 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), 575 elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET")); 576 577 /* Get the data of the section. */ 578 Elf_Data *data = elf_getdata (scn, NULL); 579 if (data == NULL) 580 continue; 581 582 /* Get the symbol table information. */ 583 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 584 GElf_Shdr symshdr_mem; 585 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 586 Elf_Data *symdata = elf_getdata (symscn, NULL); 587 588 /* Search for the optional extended section index table. */ 589 Elf_Data *xndxdata = NULL; 590 Elf_Scn *xndxscn = NULL; 591 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL) 592 { 593 GElf_Shdr xndxshdr_mem; 594 GElf_Shdr *xndxshdr; 595 596 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 597 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX 598 && xndxshdr->sh_link == elf_ndxscn (symscn)) 599 { 600 /* Found it. */ 601 xndxdata = elf_getdata (xndxscn, NULL); 602 break; 603 } 604 } 605 606 if (shdr->sh_type == SHT_REL) 607 show_relocs_rel (ebl, shdr, data, symdata, xndxdata, 608 symshdr->sh_link, shstrndx); 609 else 610 show_relocs_rela (ebl, shdr, data, symdata, xndxdata, 611 symshdr->sh_link, shstrndx); 612 } 613 } 614 615 fputs_unlocked ("\n\n", stdout); 616 617 return 0; 618} 619 620 621static int 622show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx) 623{ 624 Elf_Scn *scn = NULL; 625 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 626 { 627 GElf_Shdr shdr_mem; 628 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 629 630 if (shdr == NULL) 631 INTERNAL_ERROR (fname); 632 633 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0) 634 { 635 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 636 continue; 637 638 printf (gettext ("Contents of section %s:\n"), 639 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 640 641 /* Get the data of the section. */ 642 Elf_Data *data = elf_getdata (scn, NULL); 643 if (data == NULL) 644 continue; 645 646 unsigned char *cp = data->d_buf; 647 size_t cnt; 648 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16) 649 { 650 printf (" %04zx ", cnt); 651 652 for (size_t inner = 0; inner < 16; inner += 4) 653 printf ("%02hhx%02hhx%02hhx%02hhx ", 654 cp[inner], cp[inner + 1], cp[inner + 2], 655 cp[inner + 3]); 656 fputc_unlocked (' ', stdout); 657 658 for (size_t inner = 0; inner < 16; ++inner) 659 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) 660 ? cp[inner] : '.', stdout); 661 fputc_unlocked ('\n', stdout); 662 } 663 664 printf (" %04zx ", cnt); 665 666 size_t remaining = data->d_size - cnt; 667 size_t inner; 668 for (inner = 0; inner + 4 <= remaining; inner += 4) 669 printf ("%02hhx%02hhx%02hhx%02hhx ", 670 cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]); 671 672 for (; inner < remaining; ++inner) 673 printf ("%02hhx", cp[inner]); 674 675 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0; 676 --inner) 677 fputc_unlocked (' ', stdout); 678 679 for (inner = 0; inner < remaining; ++inner) 680 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) 681 ? cp[inner] : '.', stdout); 682 fputc_unlocked ('\n', stdout); 683 684 fputc_unlocked ('\n', stdout); 685 } 686 } 687 688 return 0; 689} 690 691 692struct disasm_info 693{ 694 GElf_Addr addr; 695 const uint8_t *cur; 696 const uint8_t *last_end; 697}; 698 699 700// XXX This is not the preferred output for all architectures. Needs 701// XXX customization, too. 702static int 703disasm_output (char *buf, size_t buflen, void *arg) 704{ 705 struct disasm_info *info = (struct disasm_info *) arg; 706 707 printf ("%8" PRIx64 ": ", (uint64_t) info->addr); 708 size_t cnt; 709 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt) 710 printf (" %02" PRIx8, info->last_end[cnt]); 711 printf ("%*s %.*s\n", 712 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf); 713 714 info->addr += cnt; 715 716 /* We limit the number of bytes printed before the mnemonic to 8. 717 Print the rest on a separate, following line. */ 718 if (info->cur - info->last_end > 8) 719 { 720 printf ("%8" PRIx64 ": ", (uint64_t) info->addr); 721 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt) 722 printf (" %02" PRIx8, info->last_end[cnt]); 723 putchar_unlocked ('\n'); 724 info->addr += info->cur - info->last_end - 8; 725 } 726 727 info->last_end = info->cur; 728 729 return 0; 730} 731 732 733static int 734show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx) 735{ 736 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */); 737 if (ctx == NULL) 738 error (EXIT_FAILURE, 0, gettext ("cannot disassemble")); 739 740 Elf_Scn *scn = NULL; 741 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 742 { 743 GElf_Shdr shdr_mem; 744 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 745 746 if (shdr == NULL) 747 INTERNAL_ERROR (fname); 748 749 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0 750 && (shdr->sh_flags & SHF_EXECINSTR) != 0) 751 { 752 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx)) 753 continue; 754 755 Elf_Data *data = elf_getdata (scn, NULL); 756 if (data == NULL) 757 continue; 758 759 printf ("Disassembly of section %s:\n\n", 760 elf_strptr (ebl->elf, shstrndx, shdr->sh_name)); 761 762 struct disasm_info info; 763 info.addr = shdr->sh_addr; 764 info.last_end = info.cur = data->d_buf; 765 766 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr, 767 "%7m %.1o,%.2o,%.3o%34a %l", disasm_output, &info, 768 NULL /* XXX */); 769 } 770 } 771 772 (void) disasm_end (ctx); 773 774 return 0; 775} 776 777 778static int 779handle_elf (Elf *elf, const char *prefix, const char *fname, 780 const char *suffix) 781{ 782 783 /* Get the backend for this object file type. */ 784 Ebl *ebl = ebl_openbackend (elf); 785 786 printf ("%s: elf%d-%s\n\n", 787 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64, 788 ebl_backend_name (ebl)); 789 790 /* Create the full name of the file. */ 791 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 792 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix); 793 size_t fname_len = strlen (fname) + 1; 794 char fullname[prefix_len + 1 + fname_len + suffix_len]; 795 char *cp = fullname; 796 if (prefix != NULL) 797 cp = mempcpy (cp, prefix, prefix_len); 798 cp = mempcpy (cp, fname, fname_len); 799 if (suffix != NULL) 800 memcpy (cp - 1, suffix, suffix_len + 1); 801 802 /* Get the section header string table index. */ 803 size_t shstrndx; 804 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) 805 error (EXIT_FAILURE, 0, 806 gettext ("cannot get section header string table index")); 807 808 int result = 0; 809 if (print_disasm) 810 result = show_disasm (ebl, fullname, shstrndx); 811 if (print_relocs && !print_disasm) 812 result = show_relocs (ebl, fullname, shstrndx); 813 if (print_full_content) 814 result = show_full_content (ebl, fullname, shstrndx); 815 816 /* Close the ELF backend library descriptor. */ 817 ebl_closebackend (ebl); 818 819 return result; 820} 821 822 823#include "debugpred.h" 824