blob: e2fcfbf1f59d92db78bc58deb4116c7e9fe2dc0e [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* 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"