blob: 91fa875092461612f9c70084ab0365fdb9943eb3 [file] [log] [blame]
Ben Chengcc6695e2012-03-07 23:04:02 -08001/* Print information from ELF file in human-readable form.
2 Copyright (C) 2005, 2006, 2007 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);
52void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
53
54/* Bug report address. */
55const char *argp_program_bug_address = 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"), "2008");
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 | ARGP_HELP_EXIT_ERR,
238 program_invocation_short_name);
239 exit (1);
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 printf ("+%#" PRIx64, rel->r_addend);
504 putchar ('\n');
505 }
506 }
507}
508
509
510static bool
511section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
512{
513 if (section_list == NULL)
514 return true;
515
516 struct section_list *runp = section_list;
517
518 do
519 {
520 if (runp->is_name)
521 {
522 if (strcmp (runp->name,
523 elf_strptr (elf, shstrndx, shdr->sh_name)) == 0)
524 return true;
525 }
526 else
527 {
528 if (runp->scnndx == scnndx)
529 return true;
530 }
531
532 runp = runp->next;
533 }
534 while (runp != NULL);
535
536 return false;
537}
538
539
540static int
541show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
542{
543 int elfclass = gelf_getclass (ebl->elf);
544
545 Elf_Scn *scn = NULL;
546 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
547 {
548 GElf_Shdr shdr_mem;
549 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
550
551 if (shdr == NULL)
552 INTERNAL_ERROR (fname);
553
554 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
555 {
556 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
557 continue;
558
559 GElf_Shdr destshdr_mem;
560 GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
561 shdr->sh_info),
562 &destshdr_mem);
563
564 printf (gettext ("RELOCATION RECORDS FOR [%s]:\n"
565 "%-*s TYPE VALUE\n"),
566 elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
567 elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET"));
568
569 /* Get the data of the section. */
570 Elf_Data *data = elf_getdata (scn, NULL);
571 if (data == NULL)
572 continue;
573
574 /* Get the symbol table information. */
575 Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
576 GElf_Shdr symshdr_mem;
577 GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
578 Elf_Data *symdata = elf_getdata (symscn, NULL);
579
580 /* Search for the optional extended section index table. */
581 Elf_Data *xndxdata = NULL;
582 Elf_Scn *xndxscn = NULL;
583 while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
584 {
585 GElf_Shdr xndxshdr_mem;
586 GElf_Shdr *xndxshdr;
587
588 xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
589 if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
590 && xndxshdr->sh_link == elf_ndxscn (symscn))
591 {
592 /* Found it. */
593 xndxdata = elf_getdata (xndxscn, NULL);
594 break;
595 }
596 }
597
598 if (shdr->sh_type == SHT_REL)
599 show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
600 symshdr->sh_link, shstrndx);
601 else
602 show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
603 symshdr->sh_link, shstrndx);
604 }
605 }
606
607 fputs_unlocked ("\n\n", stdout);
608
609 return 0;
610}
611
612
613static int
614show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
615{
616 Elf_Scn *scn = NULL;
617 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
618 {
619 GElf_Shdr shdr_mem;
620 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
621
622 if (shdr == NULL)
623 INTERNAL_ERROR (fname);
624
625 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
626 {
627 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
628 continue;
629
630 printf (gettext ("Contents of section %s:\n"),
631 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
632
633 /* Get the data of the section. */
634 Elf_Data *data = elf_getdata (scn, NULL);
635 if (data == NULL)
636 continue;
637
638 unsigned char *cp = data->d_buf;
639 size_t cnt;
640 for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
641 {
642 printf (" %04zx ", cnt);
643
644 for (size_t inner = 0; inner < 16; inner += 4)
645 printf ("%02hhx%02hhx%02hhx%02hhx ",
646 cp[inner], cp[inner + 1], cp[inner + 2],
647 cp[inner + 3]);
648 fputc_unlocked (' ', stdout);
649
650 for (size_t inner = 0; inner < 16; ++inner)
651 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
652 ? cp[inner] : '.', stdout);
653 fputc_unlocked ('\n', stdout);
654 }
655
656 printf (" %04zx ", cnt);
657
658 size_t remaining = data->d_size - cnt;
659 size_t inner;
660 for (inner = 0; inner + 4 <= remaining; inner += 4)
661 printf ("%02hhx%02hhx%02hhx%02hhx ",
662 cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
663
664 for (; inner < remaining; ++inner)
665 printf ("%02hhx", cp[inner]);
666
667 for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
668 --inner)
669 fputc_unlocked (' ', stdout);
670
671 for (inner = 0; inner < remaining; ++inner)
672 fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
673 ? cp[inner] : '.', stdout);
674 fputc_unlocked ('\n', stdout);
675
676 fputc_unlocked ('\n', stdout);
677 }
678 }
679
680 return 0;
681}
682
683
684struct disasm_info
685{
686 GElf_Addr addr;
687 const uint8_t *cur;
688 const uint8_t *last_end;
689};
690
691
692// XXX This is not the preferred output for all architectures. Needs
693// XXX customization, too.
694static int
695disasm_output (char *buf, size_t buflen, void *arg)
696{
697 struct disasm_info *info = (struct disasm_info *) arg;
698
699 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
700 size_t cnt;
701 for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
702 printf (" %02" PRIx8, info->last_end[cnt]);
703 printf ("%*s %.*s\n",
704 (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
705
706 info->addr += cnt;
707
708 /* We limit the number of bytes printed before the mnemonic to 8.
709 Print the rest on a separate, following line. */
710 if (info->cur - info->last_end > 8)
711 {
712 printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
713 for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
714 printf (" %02" PRIx8, info->last_end[cnt]);
715 putchar_unlocked ('\n');
716 info->addr += info->cur - info->last_end - 8;
717 }
718
719 info->last_end = info->cur;
720
721 return 0;
722}
723
724
725static int
726show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
727{
728 DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
729 if (ctx == NULL)
730 error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
731
732 Elf_Scn *scn = NULL;
733 while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
734 {
735 GElf_Shdr shdr_mem;
736 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
737
738 if (shdr == NULL)
739 INTERNAL_ERROR (fname);
740
741 if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
742 && (shdr->sh_flags & SHF_EXECINSTR) != 0)
743 {
744 if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
745 continue;
746
747 Elf_Data *data = elf_getdata (scn, NULL);
748 if (data == NULL)
749 continue;
750
751 printf ("Disassembly of section %s:\n\n",
752 elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
753
754 struct disasm_info info;
755 info.addr = shdr->sh_addr;
756 info.last_end = info.cur = data->d_buf;
757
758 disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
759 "%7m %.1o,%.2o,%.3o%34a %l", disasm_output, &info,
760 NULL /* XXX */);
761 }
762 }
763
764 (void) disasm_end (ctx);
765
766 return 0;
767}
768
769
770static int
771handle_elf (Elf *elf, const char *prefix, const char *fname,
772 const char *suffix)
773{
774
775 /* Get the backend for this object file type. */
776 Ebl *ebl = ebl_openbackend (elf);
777
778 printf ("%s: elf%d-%s\n\n",
779 fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
780 ebl_backend_name (ebl));
781
782 /* Create the full name of the file. */
783 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
784 size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
785 size_t fname_len = strlen (fname) + 1;
786 char fullname[prefix_len + 1 + fname_len + suffix_len];
787 char *cp = fullname;
788 if (prefix != NULL)
789 cp = mempcpy (cp, prefix, prefix_len);
790 cp = mempcpy (cp, fname, fname_len);
791 if (suffix != NULL)
792 memcpy (cp - 1, suffix, suffix_len + 1);
793
794 /* Get the section header string table index. */
795 size_t shstrndx;
796 if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
797 error (EXIT_FAILURE, 0,
798 gettext ("cannot get section header string table index"));
799
800 int result = 0;
801 if (print_disasm)
802 result = show_disasm (ebl, fullname, shstrndx);
803 if (print_relocs && !print_disasm)
804 result = show_relocs (ebl, fullname, shstrndx);
805 if (print_full_content)
806 result = show_full_content (ebl, fullname, shstrndx);
807
808 /* Close the ELF backend library descriptor. */
809 ebl_closebackend (ebl);
810
811 return result;
812}
813
814
815#include "debugpred.h"