Blame src/objdump.c

Packit 032894
/* Print information from ELF file in human-readable form.
Packit 032894
   Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of the GNU General Public License as published by
Packit 032894
   the Free Software Foundation; either version 3 of the License, or
Packit 032894
   (at your option) any later version.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 032894
   GNU General Public License for more details.
Packit 032894
Packit 032894
   You should have received a copy of the GNU General Public License
Packit 032894
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include <argp.h>
Packit 032894
#include <fcntl.h>
Packit 032894
#include <inttypes.h>
Packit 032894
#include <libintl.h>
Packit 032894
#include <locale.h>
Packit 032894
#include <stdbool.h>
Packit 032894
#include <stdio.h>
Packit 032894
#include <stdio_ext.h>
Packit 032894
#include <stdlib.h>
Packit 032894
#include <string.h>
Packit 032894
#include <unistd.h>
Packit 032894
Packit 032894
#include <libeu.h>
Packit 032894
#include <system.h>
Packit 032894
#include <color.h>
Packit 032894
#include <printversion.h>
Packit 032894
#include "../libebl/libeblP.h"
Packit 032894
Packit 032894
Packit 032894
/* Name and version of program.  */
Packit 032894
ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Packit 032894
Packit 032894
/* Bug report address.  */
Packit 032894
ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Packit 032894
Packit 032894
Packit 032894
/* Definitions of arguments for argp functions.  */
Packit 032894
static const struct argp_option options[] =
Packit 032894
{
Packit 032894
  { NULL, 0, NULL, 0, N_("Mode selection:"), 0 },
Packit 032894
  { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 },
Packit 032894
  { "full-contents", 's', NULL, 0,
Packit 032894
    N_("Display the full contents of all sections requested"), 0 },
Packit 032894
  { "disassemble", 'd', NULL, 0,
Packit 032894
    N_("Display assembler code of executable sections"), 0 },
Packit 032894
Packit 032894
  { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
Packit 032894
  { "section", 'j', "NAME", 0,
Packit 032894
    N_("Only display information for section NAME."), 0 },
Packit 032894
Packit 032894
  { NULL, 0, NULL, 0, NULL, 0 }
Packit 032894
};
Packit 032894
Packit 032894
/* Short description of program.  */
Packit 032894
static const char doc[] = N_("\
Packit 032894
Show information from FILEs (a.out by default).");
Packit 032894
Packit 032894
/* Strings for arguments in help texts.  */
Packit 032894
static const char args_doc[] = N_("[FILE...]");
Packit 032894
Packit 032894
/* Prototype for option handler.  */
Packit 032894
static error_t parse_opt (int key, char *arg, struct argp_state *state);
Packit 032894
Packit 032894
/* Parser children.  */
Packit 032894
static struct argp_child argp_children[] =
Packit 032894
  {
Packit 032894
    { &color_argp, 0, N_("Output formatting"), 2 },
Packit 032894
    { NULL, 0, NULL, 0}
Packit 032894
  };
Packit 032894
Packit 032894
/* Data structure to communicate with argp functions.  */
Packit 032894
static const struct argp argp =
Packit 032894
{
Packit 032894
  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
Packit 032894
};
Packit 032894
Packit 032894
Packit 032894
/* Print symbols in file named FNAME.  */
Packit 032894
static int process_file (const char *fname, bool more_than_one);
Packit 032894
Packit 032894
/* Handle content of archive.  */
Packit 032894
static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
Packit 032894
		      const char *suffix);
Packit 032894
Packit 032894
/* Handle ELF file.  */
Packit 032894
static int handle_elf (Elf *elf, const char *prefix, const char *fname,
Packit 032894
		       const char *suffix);
Packit 032894
Packit 032894
Packit 032894
#define INTERNAL_ERROR(fname) \
Packit 032894
  error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s): %s"),      \
Packit 032894
	 fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
Packit 032894
Packit 032894
Packit 032894
/* List of sections which should be used.  */
Packit 032894
static struct section_list
Packit 032894
{
Packit 032894
  bool is_name;
Packit 032894
  union
Packit 032894
  {
Packit 032894
    const char *name;
Packit 032894
    uint32_t scnndx;
Packit 032894
  };
Packit 032894
  struct section_list *next;
Packit 032894
} *section_list;
Packit 032894
Packit 032894
Packit 032894
/* If true print archive index.  */
Packit 032894
static bool print_relocs;
Packit 032894
Packit 032894
/* If true print full contents of requested sections.  */
Packit 032894
static bool print_full_content;
Packit 032894
Packit 032894
/* If true print disassembled output..  */
Packit 032894
static bool print_disasm;
Packit 032894
Packit 032894
Packit 032894
int
Packit 032894
main (int argc, char *argv[])
Packit 032894
{
Packit 032894
  /* We use no threads here which can interfere with handling a stream.  */
Packit 032894
  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
Packit 032894
  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
Packit 032894
  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
Packit 032894
Packit 032894
  /* Set locale.  */
Packit 032894
  (void) setlocale (LC_ALL, "");
Packit 032894
Packit 032894
  /* Make sure the message catalog can be found.  */
Packit 032894
  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
Packit 032894
Packit 032894
  /* Initialize the message catalog.  */
Packit 032894
  (void) textdomain (PACKAGE_TARNAME);
Packit 032894
Packit 032894
  /* Parse and process arguments.  */
Packit 032894
  int remaining;
Packit 032894
  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit 032894
Packit 032894
  /* Tell the library which version we are expecting.  */
Packit 032894
  (void) elf_version (EV_CURRENT);
Packit 032894
Packit 032894
  int result = 0;
Packit 032894
  if (remaining == argc)
Packit 032894
    /* The user didn't specify a name so we use a.out.  */
Packit 032894
    result = process_file ("a.out", false);
Packit 032894
  else
Packit 032894
    {
Packit 032894
      /* Process all the remaining files.  */
Packit 032894
      const bool more_than_one = remaining + 1 < argc;
Packit 032894
Packit 032894
      do
Packit 032894
	result |= process_file (argv[remaining], more_than_one);
Packit 032894
      while (++remaining < argc);
Packit 032894
    }
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
/* Handle program arguments.  */
Packit 032894
static error_t
Packit 032894
parse_opt (int key, char *arg,
Packit 032894
	   struct argp_state *state __attribute__ ((unused)))
Packit 032894
{
Packit 032894
  /* True if any of the control options is set.  */
Packit 032894
  static bool any_control_option;
Packit 032894
Packit 032894
  switch (key)
Packit 032894
    {
Packit 032894
    case 'j':
Packit 032894
      {
Packit 032894
	struct section_list *newp = xmalloc (sizeof (*newp));
Packit 032894
	char *endp;
Packit 032894
	newp->scnndx = strtoul (arg, &endp, 0);
Packit 032894
	if (*endp == 0)
Packit 032894
	  newp->is_name = false;
Packit 032894
	else
Packit 032894
	  {
Packit 032894
	    newp->name = arg;
Packit 032894
	    newp->is_name = true;
Packit 032894
	  }
Packit 032894
	newp->next = section_list;
Packit 032894
	section_list = newp;
Packit 032894
      }
Packit 032894
      any_control_option = true;
Packit 032894
      break;
Packit 032894
Packit 032894
    case 'd':
Packit 032894
      print_disasm = true;
Packit 032894
      any_control_option = true;
Packit 032894
      break;
Packit 032894
Packit 032894
    case 'r':
Packit 032894
      print_relocs = true;
Packit 032894
      any_control_option = true;
Packit 032894
      break;
Packit 032894
Packit 032894
    case 's':
Packit 032894
      print_full_content = true;
Packit 032894
      any_control_option = true;
Packit 032894
      break;
Packit 032894
Packit 032894
    case ARGP_KEY_FINI:
Packit 032894
      if (! any_control_option)
Packit 032894
	{
Packit 032894
	  fputs (gettext ("No operation specified.\n"), stderr);
Packit 032894
	  argp_help (&argp, stderr, ARGP_HELP_SEE,
Packit 032894
		     program_invocation_short_name);
Packit 032894
	  exit (EXIT_FAILURE);
Packit 032894
	}
Packit 032894
      /* We only use this for checking the number of arguments, we don't
Packit 032894
	 actually want to consume them.  */
Packit 032894
      FALLTHROUGH;
Packit 032894
    default:
Packit 032894
      return ARGP_ERR_UNKNOWN;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
/* Open the file and determine the type.  */
Packit 032894
static int
Packit 032894
process_file (const char *fname, bool more_than_one)
Packit 032894
{
Packit 032894
  /* Open the file.  */
Packit 032894
  int fd = open (fname, O_RDONLY);
Packit 032894
  if (fd == -1)
Packit 032894
    {
Packit 032894
      error (0, errno, gettext ("cannot open %s"), fname);
Packit 032894
      return 1;
Packit 032894
    }
Packit 032894
Packit 032894
  /* Now get the ELF descriptor.  */
Packit 032894
  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
Packit 032894
  if (elf != NULL)
Packit 032894
    {
Packit 032894
      if (elf_kind (elf) == ELF_K_ELF)
Packit 032894
	{
Packit 032894
	  int result = handle_elf (elf, more_than_one ? "" : NULL,
Packit 032894
				   fname, NULL);
Packit 032894
Packit 032894
	  if (elf_end (elf) != 0)
Packit 032894
	    INTERNAL_ERROR (fname);
Packit 032894
Packit 032894
	  if (close (fd) != 0)
Packit 032894
	    error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
Packit 032894
Packit 032894
	  return result;
Packit 032894
	}
Packit 032894
      else if (elf_kind (elf) == ELF_K_AR)
Packit 032894
	{
Packit 032894
	  int result = handle_ar (fd, elf, NULL, fname, NULL);
Packit 032894
Packit 032894
	  if (elf_end (elf) != 0)
Packit 032894
	    INTERNAL_ERROR (fname);
Packit 032894
Packit 032894
	  if (close (fd) != 0)
Packit 032894
	    error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
Packit 032894
Packit 032894
	  return result;
Packit 032894
	}
Packit 032894
Packit 032894
      /* We cannot handle this type.  Close the descriptor anyway.  */
Packit 032894
      if (elf_end (elf) != 0)
Packit 032894
	INTERNAL_ERROR (fname);
Packit 032894
    }
Packit 032894
Packit 032894
  error (0, 0, gettext ("%s: File format not recognized"), fname);
Packit 032894
Packit 032894
  return 1;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
Packit 032894
	   const char *suffix)
Packit 032894
{
Packit 032894
  size_t fname_len = strlen (fname) + 1;
Packit 032894
  size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
Packit 032894
  char new_prefix[prefix_len + fname_len + 2];
Packit 032894
  size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
Packit 032894
  char new_suffix[suffix_len + 2];
Packit 032894
  Elf *subelf;
Packit 032894
  Elf_Cmd cmd = ELF_C_READ_MMAP;
Packit 032894
  int result = 0;
Packit 032894
Packit 032894
  char *cp = new_prefix;
Packit 032894
  if (prefix != NULL)
Packit 032894
    cp = stpcpy (cp, prefix);
Packit 032894
  cp = stpcpy (cp, fname);
Packit 032894
  stpcpy (cp, "[");
Packit 032894
Packit 032894
  cp = new_suffix;
Packit 032894
  if (suffix != NULL)
Packit 032894
    cp = stpcpy (cp, suffix);
Packit 032894
  stpcpy (cp, "]");
Packit 032894
Packit 032894
  /* Process all the files contained in the archive.  */
Packit 032894
  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
Packit 032894
    {
Packit 032894
      /* The the header for this element.  */
Packit 032894
      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
Packit 032894
Packit 032894
      /* Skip over the index entries.  */
Packit 032894
      if (strcmp (arhdr->ar_name, "/") != 0
Packit 032894
	  && strcmp (arhdr->ar_name, "//") != 0)
Packit 032894
	{
Packit 032894
	  if (elf_kind (subelf) == ELF_K_ELF)
Packit 032894
	    result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
Packit 032894
				  new_suffix);
Packit 032894
	  else if (elf_kind (subelf) == ELF_K_AR)
Packit 032894
	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
Packit 032894
				 new_suffix);
Packit 032894
	  else
Packit 032894
	    {
Packit 032894
	      error (0, 0, gettext ("%s%s%s: file format not recognized"),
Packit 032894
		     new_prefix, arhdr->ar_name, new_suffix);
Packit 032894
	      result = 1;
Packit 032894
	    }
Packit 032894
	}
Packit 032894
Packit 032894
      /* Get next archive element.  */
Packit 032894
      cmd = elf_next (subelf);
Packit 032894
      if (elf_end (subelf) != 0)
Packit 032894
	INTERNAL_ERROR (fname);
Packit 032894
    }
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata,
Packit 032894
	       Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx,
Packit 032894
	       GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend)
Packit 032894
{
Packit 032894
  int elfclass = gelf_getclass (ebl->elf);
Packit 032894
  char buf[128];
Packit 032894
Packit 032894
  printf ("%0*" PRIx64 " %-20s ",
Packit 032894
	  elfclass == ELFCLASS32 ? 8 : 16, r_offset,
Packit 032894
	  ebl_reloc_type_name (ebl, GELF_R_TYPE (r_info), buf, sizeof (buf)));
Packit 032894
Packit 032894
  Elf32_Word xndx;
Packit 032894
  GElf_Sym symmem;
Packit 032894
  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
Packit 032894
				    &symmem, &xndx);
Packit 032894
Packit 032894
  if (sym == NULL)
Packit 032894
    printf ("<%s %ld>",
Packit 032894
	    gettext ("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info));
Packit 032894
  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
Packit 032894
    printf ("%s",
Packit 032894
	    elf_strptr (ebl->elf, symstrndx, sym->st_name));
Packit 032894
  else
Packit 032894
    {
Packit 032894
      GElf_Shdr destshdr_mem;
Packit 032894
      GElf_Shdr *destshdr;
Packit 032894
      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
Packit 032894
					   sym->st_shndx == SHN_XINDEX
Packit 032894
					   ? xndx : sym->st_shndx),
Packit 032894
			       &destshdr_mem);
Packit 032894
Packit 032894
      if (shdr == NULL || destshdr == NULL)
Packit 032894
	printf ("<%s %ld>",
Packit 032894
		gettext ("INVALID SECTION"),
Packit 032894
		(long int) (sym->st_shndx == SHN_XINDEX
Packit 032894
			    ? xndx : sym->st_shndx));
Packit 032894
      else
Packit 032894
	printf ("%s",
Packit 032894
		elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
Packit 032894
    }
Packit 032894
Packit 032894
  if (r_addend != 0)
Packit 032894
    {
Packit 032894
      char sign = '+';
Packit 032894
      if (r_addend < 0)
Packit 032894
	{
Packit 032894
	  sign = '-';
Packit 032894
	  r_addend = -r_addend;
Packit 032894
	}
Packit 032894
      printf ("%c%#" PRIx64, sign, r_addend);
Packit 032894
    }
Packit 032894
  putchar ('\n');
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
Packit 032894
		 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
Packit 032894
		 size_t shstrndx)
Packit 032894
{
Packit 032894
  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
Packit 032894
  int nentries = shdr->sh_size / sh_entsize;
Packit 032894
Packit 032894
  for (int cnt = 0; cnt < nentries; ++cnt)
Packit 032894
    {
Packit 032894
      GElf_Rel relmem;
Packit 032894
      GElf_Rel *rel;
Packit 032894
Packit 032894
      rel = gelf_getrel (data, cnt, &relmem);
Packit 032894
      if (rel != NULL)
Packit 032894
	show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
Packit 032894
		       rel->r_offset, rel->r_info, 0);
Packit 032894
    }
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
Packit 032894
		  Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
Packit 032894
		  size_t shstrndx)
Packit 032894
{
Packit 032894
  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
Packit 032894
  int nentries = shdr->sh_size / sh_entsize;
Packit 032894
Packit 032894
  for (int cnt = 0; cnt < nentries; ++cnt)
Packit 032894
    {
Packit 032894
      GElf_Rela relmem;
Packit 032894
      GElf_Rela *rel;
Packit 032894
Packit 032894
      rel = gelf_getrela (data, cnt, &relmem);
Packit 032894
      if (rel != NULL)
Packit 032894
	show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
Packit 032894
		       rel->r_offset, rel->r_info, rel->r_addend);
Packit 032894
    }
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static bool
Packit 032894
section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
Packit 032894
{
Packit 032894
  if (section_list == NULL)
Packit 032894
    return true;
Packit 032894
Packit 032894
  struct section_list *runp = section_list;
Packit 032894
  const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
Packit 032894
Packit 032894
  do
Packit 032894
    {
Packit 032894
      if (runp->is_name)
Packit 032894
	{
Packit 032894
	  if (name && strcmp (runp->name, name) == 0)
Packit 032894
	    return true;
Packit 032894
	}
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  if (runp->scnndx == scnndx)
Packit 032894
	    return true;
Packit 032894
	}
Packit 032894
Packit 032894
      runp = runp->next;
Packit 032894
    }
Packit 032894
  while (runp != NULL);
Packit 032894
Packit 032894
  return false;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
Packit 032894
{
Packit 032894
  int elfclass = gelf_getclass (ebl->elf);
Packit 032894
Packit 032894
  Elf_Scn *scn = NULL;
Packit 032894
  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
Packit 032894
    {
Packit 032894
      GElf_Shdr shdr_mem;
Packit 032894
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit 032894
Packit 032894
      if (shdr == NULL)
Packit 032894
	INTERNAL_ERROR (fname);
Packit 032894
Packit 032894
      if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
Packit 032894
	{
Packit 032894
	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  GElf_Shdr destshdr_mem;
Packit 032894
	  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
Packit 032894
							  shdr->sh_info),
Packit 032894
					      &destshdr_mem);
Packit 032894
	  if (unlikely (destshdr == NULL))
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  printf (gettext ("\nRELOCATION RECORDS FOR [%s]:\n"
Packit 032894
			   "%-*s TYPE                 VALUE\n"),
Packit 032894
		  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
Packit 032894
		  elfclass == ELFCLASS32 ? 8 : 16, gettext ("OFFSET"));
Packit 032894
Packit 032894
	  /* Get the data of the section.  */
Packit 032894
	  Elf_Data *data = elf_getdata (scn, NULL);
Packit 032894
	  if (data == NULL)
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  /* Get the symbol table information.  */
Packit 032894
	  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
Packit 032894
	  GElf_Shdr symshdr_mem;
Packit 032894
	  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
Packit 032894
	  Elf_Data *symdata = elf_getdata (symscn, NULL);
Packit 032894
	  if (unlikely (symshdr == NULL || symdata == NULL))
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  /* Search for the optional extended section index table.  */
Packit 032894
	  Elf_Data *xndxdata = NULL;
Packit 032894
	  Elf_Scn *xndxscn = NULL;
Packit 032894
	  while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
Packit 032894
	    {
Packit 032894
	      GElf_Shdr xndxshdr_mem;
Packit 032894
	      GElf_Shdr *xndxshdr;
Packit 032894
Packit 032894
	      xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
Packit 032894
	      if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
Packit 032894
		  && xndxshdr->sh_link == elf_ndxscn (symscn))
Packit 032894
		{
Packit 032894
		  /* Found it.  */
Packit 032894
		  xndxdata = elf_getdata (xndxscn, NULL);
Packit 032894
		  break;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
Packit 032894
	  if (shdr->sh_type == SHT_REL)
Packit 032894
	    show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
Packit 032894
			     symshdr->sh_link, shstrndx);
Packit 032894
	  else
Packit 032894
	    show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
Packit 032894
			      symshdr->sh_link, shstrndx);
Packit 032894
Packit 032894
	  putchar ('\n');
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
Packit 032894
{
Packit 032894
  Elf_Scn *scn = NULL;
Packit 032894
  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
Packit 032894
    {
Packit 032894
      GElf_Shdr shdr_mem;
Packit 032894
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit 032894
Packit 032894
      if (shdr == NULL)
Packit 032894
	INTERNAL_ERROR (fname);
Packit 032894
Packit 032894
      if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
Packit 032894
	{
Packit 032894
	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  printf (gettext ("Contents of section %s:\n"),
Packit 032894
		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
Packit 032894
Packit 032894
	  /* Get the data of the section.  */
Packit 032894
	  Elf_Data *data = elf_getdata (scn, NULL);
Packit 032894
	  if (data == NULL)
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  unsigned char *cp = data->d_buf;
Packit 032894
	  size_t cnt;
Packit 032894
	  for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
Packit 032894
	    {
Packit 032894
	      printf (" %04zx ", cnt);
Packit 032894
Packit 032894
	      for (size_t inner = 0; inner < 16; inner += 4)
Packit 032894
		printf ("%02hhx%02hhx%02hhx%02hhx ",
Packit 032894
			cp[inner], cp[inner + 1], cp[inner + 2],
Packit 032894
			cp[inner + 3]);
Packit 032894
	      fputc_unlocked (' ', stdout);
Packit 032894
Packit 032894
	      for (size_t inner = 0; inner < 16; ++inner)
Packit 032894
		fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
Packit 032894
				? cp[inner] : '.', stdout);
Packit 032894
	      fputc_unlocked ('\n', stdout);
Packit 032894
	    }
Packit 032894
Packit 032894
	  printf (" %04zx ", cnt);
Packit 032894
Packit 032894
	  size_t remaining = data->d_size - cnt;
Packit 032894
	  size_t inner;
Packit 032894
	  for (inner = 0; inner + 4 <= remaining; inner += 4)
Packit 032894
	    printf ("%02hhx%02hhx%02hhx%02hhx ",
Packit 032894
		    cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
Packit 032894
Packit 032894
	  for (; inner < remaining; ++inner)
Packit 032894
	    printf ("%02hhx", cp[inner]);
Packit 032894
Packit 032894
	  for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
Packit 032894
	       --inner)
Packit 032894
	    fputc_unlocked (' ', stdout);
Packit 032894
Packit 032894
	  for (inner = 0; inner < remaining; ++inner)
Packit 032894
	    fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
Packit 032894
			    ? cp[inner] : '.', stdout);
Packit 032894
	  fputc_unlocked ('\n', stdout);
Packit 032894
Packit 032894
	  fputc_unlocked ('\n', stdout);
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
struct disasm_info
Packit 032894
{
Packit 032894
  GElf_Addr addr;
Packit 032894
  const uint8_t *cur;
Packit 032894
  const uint8_t *last_end;
Packit 032894
  const char *address_color;
Packit 032894
  const char *bytes_color;
Packit 032894
};
Packit 032894
Packit 032894
Packit 032894
// XXX This is not the preferred output for all architectures.  Needs
Packit 032894
// XXX customization, too.
Packit 032894
static int
Packit 032894
disasm_output (char *buf, size_t buflen, void *arg)
Packit 032894
{
Packit 032894
  struct disasm_info *info = (struct disasm_info *) arg;
Packit 032894
Packit 032894
  if (info->address_color != NULL)
Packit 032894
    printf ("%s%8" PRIx64 "%s:   ",
Packit 032894
	    info->address_color, (uint64_t) info->addr, color_off);
Packit 032894
  else
Packit 032894
    printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
Packit 032894
Packit 032894
  if (info->bytes_color != NULL)
Packit 032894
    fputs_unlocked (info->bytes_color, stdout);
Packit 032894
  size_t cnt;
Packit 032894
  for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
Packit 032894
    printf (" %02" PRIx8, info->last_end[cnt]);
Packit 032894
  if (info->bytes_color != NULL)
Packit 032894
    fputs_unlocked (color_off, stdout);
Packit 032894
Packit 032894
  printf ("%*s %.*s\n",
Packit 032894
	  (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
Packit 032894
Packit 032894
  info->addr += cnt;
Packit 032894
Packit 032894
  /* We limit the number of bytes printed before the mnemonic to 8.
Packit 032894
     Print the rest on a separate, following line.  */
Packit 032894
  if (info->cur - info->last_end > 8)
Packit 032894
    {
Packit 032894
      if (info->address_color != NULL)
Packit 032894
	printf ("%s%8" PRIx64 "%s:   ",
Packit 032894
		info->address_color, (uint64_t) info->addr, color_off);
Packit 032894
      else
Packit 032894
	printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
Packit 032894
Packit 032894
      if (info->bytes_color != NULL)
Packit 032894
	fputs_unlocked (info->bytes_color, stdout);
Packit 032894
      for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
Packit 032894
	printf (" %02" PRIx8, info->last_end[cnt]);
Packit 032894
      if (info->bytes_color != NULL)
Packit 032894
	fputs_unlocked (color_off, stdout);
Packit 032894
      putchar_unlocked ('\n');
Packit 032894
      info->addr += info->cur - info->last_end - 8;
Packit 032894
    }
Packit 032894
Packit 032894
  info->last_end = info->cur;
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
Packit 032894
{
Packit 032894
  DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
Packit 032894
  if (ctx == NULL)
Packit 032894
    error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
Packit 032894
Packit 032894
  Elf_Scn *scn = NULL;
Packit 032894
  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
Packit 032894
    {
Packit 032894
      GElf_Shdr shdr_mem;
Packit 032894
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Packit 032894
Packit 032894
      if (shdr == NULL)
Packit 032894
	INTERNAL_ERROR (fname);
Packit 032894
Packit 032894
      if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
Packit 032894
	  && (shdr->sh_flags & SHF_EXECINSTR) != 0)
Packit 032894
	{
Packit 032894
	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  Elf_Data *data = elf_getdata (scn, NULL);
Packit 032894
	  if (data == NULL)
Packit 032894
	    continue;
Packit 032894
Packit 032894
	  printf ("Disassembly of section %s:\n\n",
Packit 032894
		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
Packit 032894
Packit 032894
	  struct disasm_info info;
Packit 032894
	  info.addr = shdr->sh_addr;
Packit 032894
	  info.last_end = info.cur = data->d_buf;
Packit 032894
	  char *fmt;
Packit 032894
	  if (color_mode)
Packit 032894
	    {
Packit 032894
	      info.address_color = color_address;
Packit 032894
	      info.bytes_color = color_bytes;
Packit 032894
Packit 032894
	      if (asprintf (&fmt, "%s%%7m %s%%.1o,%s%%.2o,%s%%.3o,,%s%%.4o%s%%.5o%%34a %s%%l",
Packit 032894
			    color_mnemonic ?: "",
Packit 032894
			    color_operand1 ?: "",
Packit 032894
			    color_operand2 ?: "",
Packit 032894
			    color_operand3 ?: "",
Packit 032894
                            color_operand4 ?: "",
Packit 032894
                            color_operand5 ?: "",
Packit 032894
			    color_label ?: "") < 0)
Packit 032894
		error (EXIT_FAILURE, errno, _("cannot allocate memory"));
Packit 032894
	    }
Packit 032894
	  else
Packit 032894
	    {
Packit 032894
	      info.address_color = info.bytes_color = NULL;
Packit 032894
Packit 032894
	      fmt = "%7m %.1o,%.2o,%.3o,%.4o,%.5o%34a %l";
Packit 032894
	    }
Packit 032894
Packit 032894
	  disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
Packit 032894
		     fmt, disasm_output, &info, NULL /* XXX */);
Packit 032894
Packit 032894
	  if (color_mode)
Packit 032894
	    free (fmt);
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  (void) disasm_end (ctx);
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
handle_elf (Elf *elf, const char *prefix, const char *fname,
Packit 032894
	    const char *suffix)
Packit 032894
{
Packit 032894
Packit 032894
  /* Get the backend for this object file type.  */
Packit 032894
  Ebl *ebl = ebl_openbackend (elf);
Packit Service 35cfd5
  if (ebl == NULL)
Packit Service 35cfd5
    error (EXIT_FAILURE, 0,
Packit Service 35cfd5
	   gettext ("cannot create backend for elf file"));
Packit 032894
Packit 032894
  printf ("%s: elf%d-%s\n\n",
Packit 032894
	  fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
Packit 032894
	  ebl_backend_name (ebl));
Packit 032894
Packit 032894
  /* Create the full name of the file.  */
Packit 032894
  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
Packit 032894
  size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
Packit 032894
  size_t fname_len = strlen (fname) + 1;
Packit 032894
  char fullname[prefix_len + 1 + fname_len + suffix_len];
Packit 032894
  char *cp = fullname;
Packit 032894
  if (prefix != NULL)
Packit 032894
    cp = mempcpy (cp, prefix, prefix_len);
Packit 032894
  cp = mempcpy (cp, fname, fname_len);
Packit 032894
  if (suffix != NULL)
Packit 032894
    memcpy (cp - 1, suffix, suffix_len + 1);
Packit 032894
Packit 032894
  /* Get the section header string table index.  */
Packit 032894
  size_t shstrndx;
Packit 032894
  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
Packit 032894
    error (EXIT_FAILURE, 0,
Packit 032894
	   gettext ("cannot get section header string table index"));
Packit 032894
Packit 032894
  int result = 0;
Packit 032894
  if (print_disasm)
Packit 032894
    result = show_disasm (ebl, fullname, shstrndx);
Packit 032894
  if (print_relocs && !print_disasm)
Packit 032894
    result = show_relocs (ebl, fullname, shstrndx);
Packit 032894
  if (print_full_content)
Packit 032894
    result = show_full_content (ebl, fullname, shstrndx);
Packit 032894
Packit 032894
  /* Close the ELF backend library descriptor.  */
Packit 032894
  ebl_closebackend (ebl);
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#include "debugpred.h"