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.
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.
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.
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.
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>. */
40 #include <stdio_ext.h>
44 #include <sys/param.h>
47 #include "../libebl/libeblP.h"
50 /* Name and version of program. */
51 static void print_version (FILE *stream, struct argp_state *state);
52 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
54 /* Bug report address. */
55 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
58 /* Definitions of arguments for argp functions. */
59 static const struct argp_option options[] =
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 },
68 { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
69 { "section", 'j', "NAME", 0,
70 N_("Only display information for section NAME."), 0 },
72 { NULL, 0, NULL, 0, NULL, 0 }
75 /* Short description of program. */
76 static const char doc[] = N_("\
77 Show information from FILEs (a.out by default).");
79 /* Strings for arguments in help texts. */
80 static const char args_doc[] = N_("[FILE...]");
82 /* Prototype for option handler. */
83 static error_t parse_opt (int key, char *arg, struct argp_state *state);
85 /* Parser children. */
86 static struct argp_child argp_children[] =
88 { &color_argp, 0, N_("Output formatting"), 2 },
92 /* Data structure to communicate with argp functions. */
93 static const struct argp argp =
95 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
99 /* Print symbols in file named FNAME. */
100 static int process_file (const char *fname, bool more_than_one);
102 /* Handle content of archive. */
103 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
106 /* Handle ELF file. */
107 static int handle_elf (Elf *elf, const char *prefix, const char *fname,
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))
116 /* List of sections which should be used. */
117 static struct section_list
125 struct section_list *next;
129 /* If true print archive index. */
130 static bool print_relocs;
132 /* If true print full contents of requested sections. */
133 static bool print_full_content;
135 /* If true print disassembled output.. */
136 static bool print_disasm;
140 main (int argc, char *argv[])
142 /* Make memory leak detection possible. */
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);
151 (void) setlocale (LC_ALL, "");
153 /* Make sure the message catalog can be found. */
154 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
156 /* Initialize the message catalog. */
157 (void) textdomain (PACKAGE_TARNAME);
159 /* Parse and process arguments. */
161 (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
163 /* Tell the library which version we are expecting. */
164 (void) elf_version (EV_CURRENT);
167 if (remaining == argc)
168 /* The user didn't specify a name so we use a.out. */
169 result = process_file ("a.out", false);
172 /* Process all the remaining files. */
173 const bool more_than_one = remaining + 1 < argc;
176 result |= process_file (argv[remaining], more_than_one);
177 while (++remaining < argc);
184 /* Print the version information. */
186 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
188 fprintf (stream, "objdump (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
189 fprintf (stream, gettext ("\
190 Copyright (C) %s Red Hat, Inc.\n\
191 This is free software; see the source for copying conditions. There is NO\n\
192 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
194 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
198 /* Handle program arguments. */
200 parse_opt (int key, char *arg,
201 struct argp_state *state __attribute__ ((unused)))
203 /* True if any of the control options is set. */
204 static bool any_control_option;
210 struct section_list *newp = xmalloc (sizeof (*newp));
212 newp->scnndx = strtoul (arg, &endp, 0);
214 newp->is_name = false;
218 newp->is_name = true;
220 newp->next = section_list;
223 any_control_option = true;
228 any_control_option = true;
233 any_control_option = true;
237 print_full_content = true;
238 any_control_option = true;
242 if (! any_control_option)
244 fputs (gettext ("No operation specified.\n"), stderr);
245 argp_help (&argp, stderr, ARGP_HELP_SEE,
246 program_invocation_short_name);
251 return ARGP_ERR_UNKNOWN;
257 /* Open the file and determine the type. */
259 process_file (const char *fname, bool more_than_one)
262 int fd = open (fname, O_RDONLY);
265 error (0, errno, gettext ("cannot open %s"), fname);
269 /* Now get the ELF descriptor. */
270 Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
273 if (elf_kind (elf) == ELF_K_ELF)
275 int result = handle_elf (elf, more_than_one ? "" : NULL,
278 if (elf_end (elf) != 0)
279 INTERNAL_ERROR (fname);
282 error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
286 else if (elf_kind (elf) == ELF_K_AR)
288 int result = handle_ar (fd, elf, NULL, fname, NULL);
290 if (elf_end (elf) != 0)
291 INTERNAL_ERROR (fname);
294 error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
299 /* We cannot handle this type. Close the descriptor anyway. */
300 if (elf_end (elf) != 0)
301 INTERNAL_ERROR (fname);
304 error (0, 0, gettext ("%s: File format not recognized"), fname);
311 handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
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];
320 Elf_Cmd cmd = ELF_C_READ_MMAP;
323 char *cp = new_prefix;
325 cp = stpcpy (cp, prefix);
326 cp = stpcpy (cp, fname);
331 cp = stpcpy (cp, suffix);
334 /* Process all the files contained in the archive. */
335 while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
337 /* The the header for this element. */
338 Elf_Arhdr *arhdr = elf_getarhdr (subelf);
340 /* Skip over the index entries. */
341 if (strcmp (arhdr->ar_name, "/") != 0
342 && strcmp (arhdr->ar_name, "//") != 0)
344 if (elf_kind (subelf) == ELF_K_ELF)
345 result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
347 else if (elf_kind (subelf) == ELF_K_AR)
348 result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
352 error (0, 0, gettext ("%s%s%s: file format not recognized"),
353 new_prefix, arhdr->ar_name, new_suffix);
358 /* Get next archive element. */
359 cmd = elf_next (subelf);
360 if (elf_end (subelf) != 0)
361 INTERNAL_ERROR (fname);
369 show_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)
373 int elfclass = gelf_getclass (ebl->elf);
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)));
382 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
387 gettext ("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info));
388 else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
390 elf_strptr (ebl->elf, symstrndx, sym->st_name));
393 GElf_Shdr destshdr_mem;
395 destshdr = gelf_getshdr (elf_getscn (ebl->elf,
396 sym->st_shndx == SHN_XINDEX
397 ? xndx : sym->st_shndx),
402 gettext ("INVALID SECTION"),
403 (long int) (sym->st_shndx == SHN_XINDEX
404 ? xndx : sym->st_shndx));
407 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
416 r_addend = -r_addend;
418 printf ("%c%#" PRIx64, sign, r_addend);
425 show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
426 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
429 int nentries = shdr->sh_size / shdr->sh_entsize;
431 for (int cnt = 0; cnt < nentries; ++cnt)
436 rel = gelf_getrel (data, cnt, &relmem);
438 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
439 rel->r_offset, rel->r_info, 0);
445 show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
446 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
449 int nentries = shdr->sh_size / shdr->sh_entsize;
451 for (int cnt = 0; cnt < nentries; ++cnt)
456 rel = gelf_getrela (data, cnt, &relmem);
458 show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
459 rel->r_offset, rel->r_info, rel->r_addend);
465 section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
467 if (section_list == NULL)
470 struct section_list *runp = section_list;
476 if (strcmp (runp->name,
477 elf_strptr (elf, shstrndx, shdr->sh_name)) == 0)
482 if (runp->scnndx == scnndx)
488 while (runp != NULL);
495 show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
497 int elfclass = gelf_getclass (ebl->elf);
500 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
503 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
506 INTERNAL_ERROR (fname);
508 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
510 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
513 GElf_Shdr destshdr_mem;
514 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
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"));
523 /* Get the data of the section. */
524 Elf_Data *data = elf_getdata (scn, NULL);
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);
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)
539 GElf_Shdr xndxshdr_mem;
542 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
543 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
544 && xndxshdr->sh_link == elf_ndxscn (symscn))
547 xndxdata = elf_getdata (xndxscn, NULL);
552 if (shdr->sh_type == SHT_REL)
553 show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
554 symshdr->sh_link, shstrndx);
556 show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
557 symshdr->sh_link, shstrndx);
568 show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
571 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
574 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
577 INTERNAL_ERROR (fname);
579 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
581 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
584 printf (gettext ("Contents of section %s:\n"),
585 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
587 /* Get the data of the section. */
588 Elf_Data *data = elf_getdata (scn, NULL);
592 unsigned char *cp = data->d_buf;
594 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
596 printf (" %04zx ", cnt);
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],
602 fputc_unlocked (' ', stdout);
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);
610 printf (" %04zx ", cnt);
612 size_t remaining = data->d_size - cnt;
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]);
618 for (; inner < remaining; ++inner)
619 printf ("%02hhx", cp[inner]);
621 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
623 fputc_unlocked (' ', stdout);
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);
630 fputc_unlocked ('\n', stdout);
642 const uint8_t *last_end;
643 const char *address_color;
644 const char *bytes_color;
648 // XXX This is not the preferred output for all architectures. Needs
649 // XXX customization, too.
651 disasm_output (char *buf, size_t buflen, void *arg)
653 struct disasm_info *info = (struct disasm_info *) arg;
655 if (info->address_color != NULL)
656 printf ("%s%8" PRIx64 "%s: ",
657 info->address_color, (uint64_t) info->addr, color_off);
659 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
661 if (info->bytes_color != NULL)
662 fputs_unlocked (info->bytes_color, stdout);
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);
669 printf ("%*s %.*s\n",
670 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
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)
678 if (info->address_color != NULL)
679 printf ("%s%8" PRIx64 "%s: ",
680 info->address_color, (uint64_t) info->addr, color_off);
682 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
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;
694 info->last_end = info->cur;
701 show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
703 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
705 error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
708 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
711 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
714 INTERNAL_ERROR (fname);
716 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
717 && (shdr->sh_flags & SHF_EXECINSTR) != 0)
719 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
722 Elf_Data *data = elf_getdata (scn, NULL);
726 printf ("Disassembly of section %s:\n\n",
727 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
729 struct disasm_info info;
730 info.addr = shdr->sh_addr;
731 info.last_end = info.cur = data->d_buf;
735 info.address_color = color_address;
736 info.bytes_color = color_bytes;
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"));
748 info.address_color = info.bytes_color = NULL;
750 fmt = "%7m %.1o,%.2o,%.3o%34a %l";
753 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
754 fmt, disasm_output, &info, NULL /* XXX */);
761 (void) disasm_end (ctx);
768 handle_elf (Elf *elf, const char *prefix, const char *fname,
772 /* Get the backend for this object file type. */
773 Ebl *ebl = ebl_openbackend (elf);
775 printf ("%s: elf%d-%s\n\n",
776 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
777 ebl_backend_name (ebl));
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];
786 cp = mempcpy (cp, prefix, prefix_len);
787 cp = mempcpy (cp, fname, fname_len);
789 memcpy (cp - 1, suffix, suffix_len + 1);
791 /* Get the section header string table index. */
793 if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
794 error (EXIT_FAILURE, 0,
795 gettext ("cannot get section header string table index"));
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);
805 /* Close the ELF backend library descriptor. */
806 ebl_closebackend (ebl);
812 #include "debugpred.h"