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.
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"
813