Blame src/objdump.c

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