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