Blame src/findtextrel.c

Packit 032894
/* Locate source files or functions which caused text relocations.
Packit 032894
   Copyright (C) 2005-2010, 2012, 2014, 2018 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 <assert.h>
Packit 032894
#include <errno.h>
Packit 032894
#include <fcntl.h>
Packit 032894
#include <gelf.h>
Packit 032894
#include <libdw.h>
Packit 032894
#include <libintl.h>
Packit 032894
#include <locale.h>
Packit 032894
#include <search.h>
Packit 032894
#include <stdbool.h>
Packit 032894
#include <stdio.h>
Packit 032894
#include <stdlib.h>
Packit 032894
#include <string.h>
Packit 032894
#include <unistd.h>
Packit 032894
Packit 032894
#include <printversion.h>
Packit 032894
#include "system.h"
Packit 032894
Packit 032894
struct segments
Packit 032894
{
Packit 032894
  GElf_Addr from;
Packit 032894
  GElf_Addr to;
Packit 032894
};
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
/* Values for the parameters which have no short form.  */
Packit 032894
#define OPT_DEBUGINFO 0x100
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_("Input Selection:"), 0 },
Packit 032894
  { "root", 'r', "PATH", 0, N_("Prepend PATH to all file names"), 0 },
Packit 032894
  { "debuginfo", OPT_DEBUGINFO, "PATH", 0,
Packit 032894
    N_("Use PATH as root of debuginfo hierarchy"), 0 },
Packit 032894
Packit 032894
  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
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
Locate source of text relocations in 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
/* Data structure to communicate with argp functions.  */
Packit 032894
static struct argp argp =
Packit 032894
{
Packit 032894
  options, parse_opt, args_doc, doc, NULL, 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
/* Check for text relocations in the given file.  The segment
Packit 032894
   information is known.  */
Packit 032894
static void check_rel (size_t nsegments, struct segments segments[nsegments],
Packit 032894
		       GElf_Addr addr, Elf *elf, Elf_Scn *symscn, Dwarf *dw,
Packit 032894
		       const char *fname, bool more_than_one,
Packit 032894
		       void **knownsrcs);
Packit 032894
Packit 032894
Packit 032894
Packit 032894
/* User-provided root directory.  */
Packit 032894
static const char *rootdir = "/";
Packit 032894
Packit 032894
/* Root of debuginfo directory hierarchy.  */
Packit 032894
static const char *debuginfo_root;
Packit 032894
Packit 032894
Packit 032894
int
Packit 032894
main (int argc, char *argv[])
Packit 032894
{
Packit 032894
  int remaining;
Packit 032894
  int result = 0;
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
  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit 032894
Packit 032894
  /* Tell the library which version we are expecting.  */
Packit 032894
  elf_version (EV_CURRENT);
Packit 032894
Packit 032894
  /* If the user has not specified the root directory for the
Packit 032894
     debuginfo hierarchy, we have to determine it ourselves.  */
Packit 032894
  if (debuginfo_root == NULL)
Packit 032894
    {
Packit 032894
      // XXX The runtime should provide this information.
Packit 032894
#if defined __ia64__ || defined __alpha__
Packit 032894
      debuginfo_root = "/usr/lib/debug";
Packit 032894
#else
Packit 032894
      debuginfo_root = (sizeof (long int) == 4
Packit 032894
			? "/usr/lib/debug" : "/usr/lib64/debug");
Packit 032894
#endif
Packit 032894
    }
Packit 032894
Packit 032894
  if (remaining == argc)
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
  switch (key)
Packit 032894
    {
Packit 032894
    case 'r':
Packit 032894
      rootdir = arg;
Packit 032894
      break;
Packit 032894
Packit 032894
    case OPT_DEBUGINFO:
Packit 032894
      debuginfo_root = arg;
Packit 032894
      break;
Packit 032894
Packit 032894
    default:
Packit 032894
      return ARGP_ERR_UNKNOWN;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
noop (void *arg __attribute__ ((unused)))
Packit 032894
{
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
process_file (const char *fname, bool more_than_one)
Packit 032894
{
Packit 032894
  int result = 0;
Packit 032894
  void *knownsrcs = NULL;
Packit 032894
Packit 032894
  size_t fname_len = strlen (fname);
Packit 032894
  size_t rootdir_len = strlen (rootdir);
Packit 032894
  const char *real_fname = fname;
Packit 032894
  if (fname[0] == '/' && (rootdir[0] != '/' || rootdir[1] != '\0'))
Packit 032894
    {
Packit 032894
      /* Prepend the user-provided root directory.  */
Packit 032894
      char *new_fname = alloca (rootdir_len + fname_len + 2);
Packit 032894
      *((char *) mempcpy (stpcpy (mempcpy (new_fname, rootdir, rootdir_len),
Packit 032894
				  "/"),
Packit 032894
			  fname, fname_len)) = '\0';
Packit 032894
      real_fname = new_fname;
Packit 032894
    }
Packit 032894
Packit 032894
  int fd = open (real_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
  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
Packit 032894
  if (elf == NULL)
Packit 032894
    {
Packit 032894
      error (0, 0, gettext ("cannot create ELF descriptor for '%s': %s"),
Packit 032894
	     fname, elf_errmsg (-1));
Packit 032894
      goto err_close;
Packit 032894
    }
Packit 032894
Packit 032894
  /* Make sure the file is a DSO.  */
Packit 032894
  GElf_Ehdr ehdr_mem;
Packit 032894
  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
Packit 032894
  if (ehdr == NULL)
Packit 032894
    {
Packit 032894
      error (0, 0, gettext ("cannot get ELF header '%s': %s"),
Packit 032894
	     fname, elf_errmsg (-1));
Packit 032894
    err_elf_close:
Packit 032894
      elf_end (elf);
Packit 032894
    err_close:
Packit 032894
      close (fd);
Packit 032894
      return 1;
Packit 032894
    }
Packit 032894
Packit 032894
  if (ehdr->e_type != ET_DYN)
Packit 032894
    {
Packit 032894
      error (0, 0, gettext ("'%s' is not a DSO or PIE"), fname);
Packit 032894
      goto err_elf_close;
Packit 032894
    }
Packit 032894
Packit 032894
  /* Determine whether the DSO has text relocations at all and locate
Packit 032894
     the symbol table.  */
Packit 032894
  Elf_Scn *symscn = NULL;
Packit 032894
  Elf_Scn *scn = NULL;
Packit 032894
  bool seen_dynamic = false;
Packit 032894
  bool have_textrel = false;
Packit 032894
  while ((scn = elf_nextscn (elf, scn)) != NULL
Packit 032894
	 && (!seen_dynamic || symscn == NULL))
Packit 032894
    {
Packit 032894
      /* Handle the section if it is a symbol table.  */
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
	{
Packit 032894
	  error (0, 0,
Packit 032894
		 gettext ("getting get section header of section %zu: %s"),
Packit 032894
		 elf_ndxscn (scn), elf_errmsg (-1));
Packit 032894
	  goto err_elf_close;
Packit 032894
	}
Packit 032894
Packit 032894
      switch (shdr->sh_type)
Packit 032894
	{
Packit 032894
	case SHT_DYNAMIC:
Packit 032894
	  if (!seen_dynamic)
Packit 032894
	    {
Packit 032894
	      seen_dynamic = true;
Packit 032894
Packit 032894
	      Elf_Data *data = elf_getdata (scn, NULL);
Packit 032894
	      size_t entries = (shdr->sh_entsize == 0
Packit 032894
				? 0 : shdr->sh_size / shdr->sh_entsize);
Packit 032894
Packit 032894
	      for (size_t cnt = 0; cnt < entries; ++cnt)
Packit 032894
		{
Packit 032894
		  GElf_Dyn dynmem;
Packit 032894
		  GElf_Dyn *dyn;
Packit 032894
Packit 032894
		  dyn = gelf_getdyn (data, cnt, &dynmem);
Packit 032894
		  if (dyn == NULL)
Packit 032894
		    {
Packit 032894
		      error (0, 0, gettext ("cannot read dynamic section: %s"),
Packit 032894
			     elf_errmsg (-1));
Packit 032894
		      goto err_elf_close;
Packit 032894
		    }
Packit 032894
Packit 032894
		  if (dyn->d_tag == DT_TEXTREL
Packit 032894
		      || (dyn->d_tag == DT_FLAGS
Packit 032894
			  && (dyn->d_un.d_val & DF_TEXTREL) != 0))
Packit 032894
		    have_textrel = true;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
	  break;
Packit 032894
Packit 032894
	case SHT_SYMTAB:
Packit 032894
	  symscn = scn;
Packit 032894
	  break;
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  if (!have_textrel)
Packit 032894
    {
Packit 032894
      error (0, 0, gettext ("no text relocations reported in '%s'"), fname);
Packit 032894
      goto err_elf_close;
Packit 032894
    }
Packit 032894
Packit 032894
  int fd2 = -1;
Packit 032894
  Elf *elf2 = NULL;
Packit 032894
  /* Get the address ranges for the loaded segments.  */
Packit 032894
  size_t nsegments_max = 10;
Packit 032894
  size_t nsegments = 0;
Packit 032894
  struct segments *segments
Packit 032894
    = (struct segments *) malloc (nsegments_max * sizeof (segments[0]));
Packit 032894
  if (segments == NULL)
Packit 032894
    error (1, errno, gettext ("while reading ELF file"));
Packit 032894
Packit 032894
  size_t phnum;
Packit 032894
  if (elf_getphdrnum (elf, &phnum) != 0)
Packit 032894
    error (1, 0, gettext ("cannot get program header count: %s"),
Packit 032894
           elf_errmsg (-1));
Packit 032894
Packit 032894
Packit 032894
  for (size_t i = 0; i < phnum; ++i)
Packit 032894
    {
Packit 032894
      GElf_Phdr phdr_mem;
Packit 032894
      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
Packit 032894
      if (phdr == NULL)
Packit 032894
	{
Packit 032894
	  error (0, 0,
Packit 032894
		 gettext ("cannot get program header index at offset %zd: %s"),
Packit 032894
		 i, elf_errmsg (-1));
Packit 032894
	  result = 1;
Packit 032894
	  goto next;
Packit 032894
	}
Packit 032894
Packit 032894
      if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
Packit 032894
	{
Packit 032894
	  if (nsegments == nsegments_max)
Packit 032894
	    {
Packit 032894
	      nsegments_max *= 2;
Packit 032894
	      segments
Packit 032894
		= (struct segments *) realloc (segments,
Packit 032894
					       nsegments_max
Packit 032894
					       * sizeof (segments[0]));
Packit 032894
	      if (segments == NULL)
Packit 032894
		{
Packit 032894
		  error (0, 0, gettext ("\
Packit 032894
cannot get program header index at offset %zd: %s"),
Packit 032894
			 i, elf_errmsg (-1));
Packit 032894
		  result = 1;
Packit 032894
		  goto next;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
Packit 032894
	  segments[nsegments].from = phdr->p_vaddr;
Packit 032894
	  segments[nsegments].to = phdr->p_vaddr + phdr->p_memsz;
Packit 032894
	  ++nsegments;
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  if (nsegments > 0)
Packit 032894
    {
Packit 032894
Packit 032894
      Dwarf *dw = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
Packit 032894
      /* Look for debuginfo files if the information is not the in
Packit 032894
	 opened file itself.  This makes only sense if the input file
Packit 032894
	 is specified with an absolute path.  */
Packit 032894
      if (dw == NULL && fname[0] == '/')
Packit 032894
	{
Packit 032894
	  size_t debuginfo_rootlen = strlen (debuginfo_root);
Packit 032894
	  char *difname = (char *) alloca (rootdir_len + debuginfo_rootlen
Packit 032894
					   + fname_len + 8);
Packit 032894
	  strcpy (mempcpy (stpcpy (mempcpy (mempcpy (difname, rootdir,
Packit 032894
						     rootdir_len),
Packit 032894
					    debuginfo_root,
Packit 032894
					    debuginfo_rootlen),
Packit 032894
				   "/"),
Packit 032894
			   fname, fname_len),
Packit 032894
		  ".debug");
Packit 032894
Packit 032894
	  fd2 = open (difname, O_RDONLY);
Packit 032894
	  if (fd2 != -1
Packit 032894
	      && (elf2 = elf_begin (fd2, ELF_C_READ_MMAP, NULL)) != NULL)
Packit 032894
	    dw = dwarf_begin_elf (elf2, DWARF_C_READ, NULL);
Packit 032894
	}
Packit 032894
Packit 032894
      /* Look at all relocations and determine which modify
Packit 032894
	 write-protected segments.  */
Packit 032894
      scn = NULL;
Packit 032894
      while ((scn = elf_nextscn (elf, scn)) != NULL)
Packit 032894
	{
Packit 032894
	  /* Handle the section if it is a symbol table.  */
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
	    {
Packit 032894
	      error (0, 0,
Packit 032894
		     gettext ("cannot get section header of section %zu: %s"),
Packit 032894
		     elf_ndxscn (scn), elf_errmsg (-1));
Packit 032894
	      result = 1;
Packit 032894
	      goto next;
Packit 032894
	    }
Packit 032894
Packit 032894
	  if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
Packit 032894
	      && symscn == NULL)
Packit 032894
	    {
Packit 032894
	      symscn = elf_getscn (elf, shdr->sh_link);
Packit 032894
	      if (symscn == NULL)
Packit 032894
		{
Packit 032894
		  error (0, 0, gettext ("\
Packit 032894
cannot get symbol table section %zu in '%s': %s"),
Packit 032894
			 (size_t) shdr->sh_link, fname, elf_errmsg (-1));
Packit 032894
		  result = 1;
Packit 032894
		  goto next;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
Packit 032894
	  if (shdr->sh_type == SHT_REL)
Packit 032894
	    {
Packit 032894
	      Elf_Data *data = elf_getdata (scn, NULL);
Packit 032894
	      size_t entries = (shdr->sh_entsize == 0
Packit 032894
				? 0 : shdr->sh_size / shdr->sh_entsize);
Packit 032894
Packit 032894
	      for (int cnt = 0;
Packit 032894
		   (size_t) cnt < entries; ++cnt)
Packit 032894
		{
Packit 032894
		  GElf_Rel rel_mem;
Packit 032894
		  GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
Packit 032894
		  if (rel == NULL)
Packit 032894
		    {
Packit 032894
		      error (0, 0, gettext ("\
Packit 032894
cannot get relocation at index %d in section %zu in '%s': %s"),
Packit 032894
			     cnt, elf_ndxscn (scn), fname, elf_errmsg (-1));
Packit 032894
		      result = 1;
Packit 032894
		      goto next;
Packit 032894
		    }
Packit 032894
Packit 032894
		  check_rel (nsegments, segments, rel->r_offset, elf,
Packit 032894
			     symscn, dw, fname, more_than_one, &knownsrcs);
Packit 032894
		}
Packit 032894
	    }
Packit 032894
	  else if (shdr->sh_type == SHT_RELA)
Packit 032894
	    {
Packit 032894
	      Elf_Data *data = elf_getdata (scn, NULL);
Packit 032894
	      size_t entries = (shdr->sh_entsize == 0
Packit 032894
				? 0 : shdr->sh_size / shdr->sh_entsize);
Packit 032894
Packit 032894
	      for (int cnt = 0; (size_t) cnt < entries; ++cnt)
Packit 032894
		{
Packit 032894
		  GElf_Rela rela_mem;
Packit 032894
		  GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
Packit 032894
		  if (rela == NULL)
Packit 032894
		    {
Packit 032894
		      error (0, 0, gettext ("\
Packit 032894
cannot get relocation at index %d in section %zu in '%s': %s"),
Packit 032894
			     cnt, elf_ndxscn (scn), fname, elf_errmsg (-1));
Packit 032894
		      result = 1;
Packit 032894
		      goto next;
Packit 032894
		    }
Packit 032894
Packit 032894
		  check_rel (nsegments, segments, rela->r_offset, elf,
Packit 032894
			     symscn, dw, fname, more_than_one, &knownsrcs);
Packit 032894
		}
Packit 032894
	    }
Packit 032894
	}
Packit 032894
Packit 032894
      dwarf_end (dw);
Packit 032894
    }
Packit 032894
Packit 032894
 next:
Packit 032894
  elf_end (elf);
Packit 032894
  elf_end (elf2);
Packit 032894
  close (fd);
Packit 032894
  if (fd2 != -1)
Packit 032894
    close (fd2);
Packit 032894
Packit 032894
  free (segments);
Packit 032894
  tdestroy (knownsrcs, noop);
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
ptrcompare (const void *p1, const void *p2)
Packit 032894
{
Packit 032894
  if ((uintptr_t) p1 < (uintptr_t) p2)
Packit 032894
    return -1;
Packit 032894
  if ((uintptr_t) p1 > (uintptr_t) p2)
Packit 032894
    return 1;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static void
Packit 032894
check_rel (size_t nsegments, struct segments segments[nsegments],
Packit 032894
	   GElf_Addr addr, Elf *elf, Elf_Scn *symscn, Dwarf *dw,
Packit 032894
	   const char *fname, bool more_than_one, void **knownsrcs)
Packit 032894
{
Packit 032894
  for (size_t cnt = 0; cnt < nsegments; ++cnt)
Packit 032894
    if (segments[cnt].from <= addr && segments[cnt].to > addr)
Packit 032894
      {
Packit 032894
	Dwarf_Die die_mem;
Packit 032894
	Dwarf_Die *die;
Packit 032894
	Dwarf_Line *line;
Packit 032894
	const char *src;
Packit 032894
Packit 032894
	if (more_than_one)
Packit 032894
	  printf ("%s: ", fname);
Packit 032894
Packit 032894
	if ((die = dwarf_addrdie (dw, addr, &die_mem)) != NULL
Packit 032894
	    && (line = dwarf_getsrc_die (die, addr)) != NULL
Packit 032894
	    && (src = dwarf_linesrc (line, NULL, NULL)) != NULL)
Packit 032894
	  {
Packit 032894
	    /* There can be more than one relocation against one file.
Packit 032894
	       Try to avoid multiple messages.  And yes, the code uses
Packit 032894
	       pointer comparison.  */
Packit 032894
	    if (tfind (src, knownsrcs, ptrcompare) == NULL)
Packit 032894
	      {
Packit 032894
		printf (gettext ("%s not compiled with -fpic/-fPIC\n"), src);
Packit 032894
		tsearch (src, knownsrcs, ptrcompare);
Packit 032894
	      }
Packit 032894
	    return;
Packit 032894
	  }
Packit 032894
	else
Packit 032894
	  {
Packit 032894
	    /* At least look at the symbol table to see which function
Packit 032894
	       the modified address is in.  */
Packit 032894
	    Elf_Data *symdata = elf_getdata (symscn, NULL);
Packit 032894
	    GElf_Shdr shdr_mem;
Packit 032894
	    GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
Packit 032894
	    if (shdr != NULL)
Packit 032894
	      {
Packit 032894
		GElf_Addr lowaddr = 0;
Packit 032894
		int lowidx = -1;
Packit 032894
		GElf_Addr highaddr = ~0ul;
Packit 032894
		int highidx = -1;
Packit 032894
		GElf_Sym sym_mem;
Packit 032894
		GElf_Sym *sym;
Packit 032894
		size_t entries = (shdr->sh_entsize == 0
Packit 032894
				  ? 0 : shdr->sh_size / shdr->sh_entsize);
Packit 032894
Packit 032894
		for (int i = 0; (size_t) i < entries; ++i)
Packit 032894
		  {
Packit 032894
		    sym = gelf_getsym (symdata, i, &sym_mem);
Packit 032894
		    if (sym == NULL)
Packit 032894
		      continue;
Packit 032894
Packit 032894
		    if (sym->st_value < addr && sym->st_value > lowaddr)
Packit 032894
		      {
Packit 032894
			lowaddr = sym->st_value;
Packit 032894
			lowidx = i;
Packit 032894
		      }
Packit 032894
		    if (sym->st_value > addr && sym->st_value < highaddr)
Packit 032894
		      {
Packit 032894
			highaddr = sym->st_value;
Packit 032894
			highidx = i;
Packit 032894
		      }
Packit 032894
		  }
Packit 032894
Packit 032894
		if (lowidx != -1)
Packit 032894
		  {
Packit 032894
		    sym = gelf_getsym (symdata, lowidx, &sym_mem);
Packit 032894
		    assert (sym != NULL);
Packit 032894
Packit 032894
		    const char *lowstr = elf_strptr (elf, shdr->sh_link,
Packit 032894
						     sym->st_name);
Packit 032894
Packit 032894
		    if (sym->st_value + sym->st_size > addr)
Packit 032894
		      {
Packit 032894
			/* It is this function.  */
Packit 032894
			if (tfind (lowstr, knownsrcs, ptrcompare) == NULL)
Packit 032894
			  {
Packit 032894
			    printf (gettext ("\
Packit 032894
the file containing the function '%s' is not compiled with -fpic/-fPIC\n"),
Packit 032894
				    lowstr);
Packit 032894
			    tsearch (lowstr, knownsrcs, ptrcompare);
Packit 032894
			  }
Packit 032894
		      }
Packit 032894
		    else if (highidx == -1)
Packit 032894
		      printf (gettext ("\
Packit 032894
the file containing the function '%s' might not be compiled with -fpic/-fPIC\n"),
Packit 032894
			      lowstr);
Packit 032894
		    else
Packit 032894
		      {
Packit 032894
			sym = gelf_getsym (symdata, highidx, &sym_mem);
Packit 032894
			assert (sym != NULL);
Packit 032894
Packit 032894
			printf (gettext ("\
Packit 032894
either the file containing the function '%s' or the file containing the function '%s' is not compiled with -fpic/-fPIC\n"),
Packit 032894
				lowstr, elf_strptr (elf, shdr->sh_link,
Packit 032894
						    sym->st_name));
Packit 032894
		      }
Packit 032894
		    return;
Packit 032894
		  }
Packit 032894
		else if (highidx != -1)
Packit 032894
		  {
Packit 032894
		    sym = gelf_getsym (symdata, highidx, &sym_mem);
Packit 032894
		    assert (sym != NULL);
Packit 032894
Packit 032894
		    printf (gettext ("\
Packit 032894
the file containing the function '%s' might not be compiled with -fpic/-fPIC\n"),
Packit 032894
			    elf_strptr (elf, shdr->sh_link, sym->st_name));
Packit 032894
		    return;
Packit 032894
		  }
Packit 032894
	      }
Packit 032894
	  }
Packit 032894
Packit 032894
	printf (gettext ("\
Packit 032894
a relocation modifies memory at offset %llu in a write-protected segment\n"),
Packit 032894
		(unsigned long long int) addr);
Packit 032894
	break;
Packit 032894
      }
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#include "debugpred.h"