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