Blame elf/dl-runtime.c

Packit Service 82fcde
/* On-demand PLT fixup for shared objects.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#define IN_DL_RUNTIME 1		/* This can be tested in dl-machine.h.  */
Packit Service 82fcde
Packit Service 82fcde
#include <alloca.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <ldsodefs.h>
Packit Service 82fcde
#include <sysdep-cancel.h>
Packit Service 82fcde
#include "dynamic-link.h"
Packit Service 82fcde
#include <tls.h>
Packit Service 82fcde
#include <dl-irel.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
Packit Service 82fcde
    || ELF_MACHINE_NO_REL
Packit Service 82fcde
# define PLTREL  ElfW(Rela)
Packit Service 82fcde
#else
Packit Service 82fcde
# define PLTREL  ElfW(Rel)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* The fixup functions might have need special attributes.  If none
Packit Service 82fcde
   are provided define the macro as empty.  */
Packit Service 82fcde
#ifndef ARCH_FIXUP_ATTRIBUTE
Packit Service 82fcde
# define ARCH_FIXUP_ATTRIBUTE
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifndef reloc_offset
Packit Service 82fcde
# define reloc_offset reloc_arg
Packit Service 82fcde
# define reloc_index  reloc_arg / sizeof (PLTREL)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* This function is called through a special trampoline from the PLT the
Packit Service 82fcde
   first time each PLT entry is called.  We must perform the relocation
Packit Service 82fcde
   specified in the PLT of the given shared object, and return the resolved
Packit Service 82fcde
   function address to the trampoline, which will restart the original call
Packit Service 82fcde
   to that address.  Future calls will bounce directly from the PLT to the
Packit Service 82fcde
   function.  */
Packit Service 82fcde
Packit Service 82fcde
DL_FIXUP_VALUE_TYPE
Packit Service 82fcde
attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
Packit Service 82fcde
_dl_fixup (
Packit Service 82fcde
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
Packit Service 82fcde
	   ELF_MACHINE_RUNTIME_FIXUP_ARGS,
Packit Service 82fcde
# endif
Packit Service 82fcde
	   struct link_map *l, ElfW(Word) reloc_arg)
Packit Service 82fcde
{
Packit Service 82fcde
  const ElfW(Sym) *const symtab
Packit Service 82fcde
    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
Packit Service 82fcde
  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
Packit Service 82fcde
Packit Service 82fcde
  const PLTREL *const reloc
Packit Service 82fcde
    = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
Packit Service 82fcde
  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
Packit Service 82fcde
  const ElfW(Sym) *refsym = sym;
Packit Service 82fcde
  void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
Packit Service 82fcde
  lookup_t result;
Packit Service 82fcde
  DL_FIXUP_VALUE_TYPE value;
Packit Service 82fcde
Packit Service 82fcde
  /* Sanity check that we're really looking at a PLT relocation.  */
Packit Service 82fcde
  assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
Packit Service 82fcde
Packit Service 82fcde
   /* Look up the target symbol.  If the normal lookup rules are not
Packit Service 82fcde
      used don't look in the global scope.  */
Packit Service 82fcde
  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      const struct r_found_version *version = NULL;
Packit Service 82fcde
Packit Service 82fcde
      if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  const ElfW(Half) *vernum =
Packit Service 82fcde
	    (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
Packit Service 82fcde
	  ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
Packit Service 82fcde
	  version = &l->l_versions[ndx];
Packit Service 82fcde
	  if (version->hash == 0)
Packit Service 82fcde
	    version = NULL;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* We need to keep the scope around so do some locking.  This is
Packit Service 82fcde
	 not necessary for objects which cannot be unloaded or when
Packit Service 82fcde
	 we are not using any threads (yet).  */
Packit Service 82fcde
      int flags = DL_LOOKUP_ADD_DEPENDENCY;
Packit Service 82fcde
      if (!RTLD_SINGLE_THREAD_P)
Packit Service 82fcde
	{
Packit Service 82fcde
	  THREAD_GSCOPE_SET_FLAG ();
Packit Service 82fcde
	  flags |= DL_LOOKUP_GSCOPE_LOCK;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
#ifdef RTLD_ENABLE_FOREIGN_CALL
Packit Service 82fcde
      RTLD_ENABLE_FOREIGN_CALL;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
Packit Service 82fcde
				    version, ELF_RTYPE_CLASS_PLT, flags, NULL);
Packit Service 82fcde
Packit Service 82fcde
      /* We are done with the global scope.  */
Packit Service 82fcde
      if (!RTLD_SINGLE_THREAD_P)
Packit Service 82fcde
	THREAD_GSCOPE_RESET_FLAG ();
Packit Service 82fcde
Packit Service 82fcde
#ifdef RTLD_FINALIZE_FOREIGN_CALL
Packit Service 82fcde
      RTLD_FINALIZE_FOREIGN_CALL;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      /* Currently result contains the base load address (or link map)
Packit Service 82fcde
	 of the object that defines sym.  Now add in the symbol
Packit Service 82fcde
	 offset.  */
Packit Service 82fcde
      value = DL_FIXUP_MAKE_VALUE (result,
Packit Service 82fcde
				   SYMBOL_ADDRESS (result, sym, false));
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We already found the symbol.  The module (and therefore its load
Packit Service 82fcde
	 address) is also known.  */
Packit Service 82fcde
      value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, sym, true));
Packit Service 82fcde
      result = l;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* And now perhaps the relocation addend.  */
Packit Service 82fcde
  value = elf_machine_plt_value (l, reloc, value);
Packit Service 82fcde
Packit Service 82fcde
  if (sym != NULL
Packit Service 82fcde
      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
Packit Service 82fcde
    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
Packit Service 82fcde
Packit Service 82fcde
  /* Finally, fix up the plt itself.  */
Packit Service 82fcde
  if (__glibc_unlikely (GLRO(dl_bind_not)))
Packit Service 82fcde
    return value;
Packit Service 82fcde
Packit Service 82fcde
  return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifndef PROF
Packit Service 82fcde
DL_FIXUP_VALUE_TYPE
Packit Service 82fcde
__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
Packit Service 82fcde
_dl_profile_fixup (
Packit Service 82fcde
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
Packit Service 82fcde
		   ELF_MACHINE_RUNTIME_FIXUP_ARGS,
Packit Service 82fcde
#endif
Packit Service 82fcde
		   struct link_map *l, ElfW(Word) reloc_arg,
Packit Service 82fcde
		   ElfW(Addr) retaddr, void *regs, long int *framesizep)
Packit Service 82fcde
{
Packit Service 82fcde
  void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
Packit Service 82fcde
Packit Service 82fcde
  if (l->l_reloc_result == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* BZ #14843: ELF_DYNAMIC_RELOCATE is called before l_reloc_result
Packit Service 82fcde
	 is allocated.  We will get here if ELF_DYNAMIC_RELOCATE calls a
Packit Service 82fcde
	 resolver function to resolve an IRELATIVE relocation and that
Packit Service 82fcde
	 resolver calls a function that is not yet resolved (lazy).  For
Packit Service 82fcde
	 example, the resolver in x86-64 libm.so calls __get_cpu_features
Packit Service 82fcde
	 defined in libc.so.  Skip audit and resolve the external function
Packit Service 82fcde
	 in this case.  */
Packit Service 82fcde
      *framesizep = -1;
Packit Service 82fcde
      return _dl_fixup (
Packit Service 82fcde
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
Packit Service 82fcde
#  ifndef ELF_MACHINE_RUNTIME_FIXUP_PARAMS
Packit Service 82fcde
#   error Please define ELF_MACHINE_RUNTIME_FIXUP_PARAMS.
Packit Service 82fcde
#  endif
Packit Service 82fcde
			ELF_MACHINE_RUNTIME_FIXUP_PARAMS,
Packit Service 82fcde
# endif
Packit Service 82fcde
			l, reloc_arg);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* This is the address in the array where we store the result of previous
Packit Service 82fcde
     relocations.  */
Packit Service 82fcde
  struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
Packit Service 1c5418
  DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
Packit Service 82fcde
Packit Service 1c5418
  DL_FIXUP_VALUE_TYPE value = *resultp;
Packit Service 1c5418
  if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This is the first time we have to relocate this object.  */
Packit Service 82fcde
      const ElfW(Sym) *const symtab
Packit Service 82fcde
	= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
Packit Service 82fcde
      const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
Packit Service 82fcde
Packit Service 82fcde
      const PLTREL *const reloc
Packit Service 82fcde
	= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
Packit Service 82fcde
      const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
Packit Service 82fcde
      const ElfW(Sym) *defsym = refsym;
Packit Service 82fcde
      lookup_t result;
Packit Service 82fcde
Packit Service 82fcde
      /* Sanity check that we're really looking at a PLT relocation.  */
Packit Service 82fcde
      assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
Packit Service 82fcde
Packit Service 82fcde
      /* Look up the target symbol.  If the symbol is marked STV_PROTECTED
Packit Service 82fcde
	 don't look in the global scope.  */
Packit Service 82fcde
      if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  const struct r_found_version *version = NULL;
Packit Service 82fcde
Packit Service 82fcde
	  if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      const ElfW(Half) *vernum =
Packit Service 82fcde
		(const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
Packit Service 82fcde
	      ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
Packit Service 82fcde
	      version = &l->l_versions[ndx];
Packit Service 82fcde
	      if (version->hash == 0)
Packit Service 82fcde
		version = NULL;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  /* We need to keep the scope around so do some locking.  This is
Packit Service 82fcde
	     not necessary for objects which cannot be unloaded or when
Packit Service 82fcde
	     we are not using any threads (yet).  */
Packit Service 82fcde
	  int flags = DL_LOOKUP_ADD_DEPENDENCY;
Packit Service 82fcde
	  if (!RTLD_SINGLE_THREAD_P)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      THREAD_GSCOPE_SET_FLAG ();
Packit Service 82fcde
	      flags |= DL_LOOKUP_GSCOPE_LOCK;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
Packit Service 82fcde
					&defsym, l->l_scope, version,
Packit Service 82fcde
					ELF_RTYPE_CLASS_PLT, flags, NULL);
Packit Service 82fcde
Packit Service 82fcde
	  /* We are done with the global scope.  */
Packit Service 82fcde
	  if (!RTLD_SINGLE_THREAD_P)
Packit Service 82fcde
	    THREAD_GSCOPE_RESET_FLAG ();
Packit Service 82fcde
Packit Service 82fcde
	  /* Currently result contains the base load address (or link map)
Packit Service 82fcde
	     of the object that defines sym.  Now add in the symbol
Packit Service 82fcde
	     offset.  */
Packit Service 82fcde
	  value = DL_FIXUP_MAKE_VALUE (result,
Packit Service 82fcde
				       SYMBOL_ADDRESS (result, defsym, false));
Packit Service 82fcde
Packit Service 82fcde
	  if (defsym != NULL
Packit Service 82fcde
	      && __builtin_expect (ELFW(ST_TYPE) (defsym->st_info)
Packit Service 82fcde
				   == STT_GNU_IFUNC, 0))
Packit Service 82fcde
	    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* We already found the symbol.  The module (and therefore its load
Packit Service 82fcde
	     address) is also known.  */
Packit Service 82fcde
	  value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, refsym, true));
Packit Service 82fcde
Packit Service 82fcde
	  if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info)
Packit Service 82fcde
				== STT_GNU_IFUNC, 0))
Packit Service 82fcde
	    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
Packit Service 82fcde
Packit Service 82fcde
	  result = l;
Packit Service 82fcde
	}
Packit Service 82fcde
      /* And now perhaps the relocation addend.  */
Packit Service 82fcde
      value = elf_machine_plt_value (l, reloc, value);
Packit Service 82fcde
Packit Service 82fcde
#ifdef SHARED
Packit Service 82fcde
      /* Auditing checkpoint: we have a new binding.  Provide the
Packit Service 82fcde
	 auditing libraries the possibility to change the value and
Packit Service 82fcde
	 tell us whether further auditing is wanted.  */
Packit Service 82fcde
      if (defsym != NULL && GLRO(dl_naudit) > 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  reloc_result->bound = result;
Packit Service 82fcde
	  /* Compute index of the symbol entry in the symbol table of
Packit Service 82fcde
	     the DSO with the definition.  */
Packit Service 82fcde
	  reloc_result->boundndx = (defsym
Packit Service 82fcde
				    - (ElfW(Sym) *) D_PTR (result,
Packit Service 82fcde
							   l_info[DT_SYMTAB]));
Packit Service 82fcde
Packit Service 82fcde
	  /* Determine whether any of the two participating DSOs is
Packit Service 82fcde
	     interested in auditing.  */
Packit Service 82fcde
	  if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      unsigned int flags = 0;
Packit Service 82fcde
	      struct audit_ifaces *afct = GLRO(dl_audit);
Packit Service 82fcde
	      /* Synthesize a symbol record where the st_value field is
Packit Service 82fcde
		 the result.  */
Packit Service 82fcde
	      ElfW(Sym) sym = *defsym;
Packit Service 82fcde
	      sym.st_value = DL_FIXUP_VALUE_ADDR (value);
Packit Service 82fcde
Packit Service 82fcde
	      /* Keep track whether there is any interest in tracing
Packit Service 82fcde
		 the call in the lower two bits.  */
Packit Service 82fcde
	      assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
Packit Service 82fcde
	      assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
Packit Service 82fcde
	      reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
Packit Service 82fcde
Packit Service 82fcde
	      const char *strtab2 = (const void *) D_PTR (result,
Packit Service 82fcde
							  l_info[DT_STRTAB]);
Packit Service 82fcde
Packit Service 82fcde
	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* XXX Check whether both DSOs must request action or
Packit Service 82fcde
		     only one */
Packit Service 82fcde
		  if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
Packit Service 82fcde
		      && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      if (afct->symbind != NULL)
Packit Service 82fcde
			{
Packit Service 82fcde
			  uintptr_t new_value
Packit Service 82fcde
			    = afct->symbind (&sym, reloc_result->boundndx,
Packit Service 82fcde
					     &l->l_audit[cnt].cookie,
Packit Service 82fcde
					     &result->l_audit[cnt].cookie,
Packit Service 82fcde
					     &flags,
Packit Service 82fcde
					     strtab2 + defsym->st_name);
Packit Service 82fcde
			  if (new_value != (uintptr_t) sym.st_value)
Packit Service 82fcde
			    {
Packit Service 82fcde
			      flags |= LA_SYMB_ALTVALUE;
Packit Service 82fcde
			      sym.st_value = new_value;
Packit Service 82fcde
			    }
Packit Service 82fcde
			}
Packit Service 82fcde
Packit Service 82fcde
		      /* Remember the results for every audit library and
Packit Service 82fcde
			 store a summary in the first two bits.  */
Packit Service 82fcde
		      reloc_result->enterexit
Packit Service 82fcde
			&= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
Packit Service 82fcde
		      reloc_result->enterexit
Packit Service 82fcde
			|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
Packit Service 82fcde
			    << ((cnt + 1) * 2));
Packit Service 82fcde
		    }
Packit Service 82fcde
		  else
Packit Service 82fcde
		    /* If the bind flags say this auditor is not interested,
Packit Service 82fcde
		       set the bits manually.  */
Packit Service 82fcde
		    reloc_result->enterexit
Packit Service 82fcde
		      |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
Packit Service 82fcde
			  << ((cnt + 1) * 2));
Packit Service 82fcde
Packit Service 82fcde
		  afct = afct->next;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      reloc_result->flags = flags;
Packit Service 82fcde
	      value = DL_FIXUP_ADDR_VALUE (sym.st_value);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    /* Set all bits since this symbol binding is not interesting.  */
Packit Service 82fcde
	    reloc_result->enterexit = (1u << DL_NNS) - 1;
Packit Service 82fcde
	}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      /* Store the result for later runs.  */
Packit Service 82fcde
      if (__glibc_likely (! GLRO(dl_bind_not)))
Packit Service 1c5418
	*resultp = value;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* By default we do not call the pltexit function.  */
Packit Service 82fcde
  long int framesize = -1;
Packit Service 82fcde
Packit Service 82fcde
#ifdef SHARED
Packit Service 82fcde
  /* Auditing checkpoint: report the PLT entering and allow the
Packit Service 82fcde
     auditors to change the value.  */
Packit Service 1c5418
  if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
Packit Service 82fcde
      /* Don't do anything if no auditor wants to intercept this call.  */
Packit Service 82fcde
      && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
Packit Service 82fcde
						l_info[DT_SYMTAB])
Packit Service 82fcde
			   + reloc_result->boundndx);
Packit Service 82fcde
Packit Service 82fcde
      /* Set up the sym parameter.  */
Packit Service 82fcde
      ElfW(Sym) sym = *defsym;
Packit Service 82fcde
      sym.st_value = DL_FIXUP_VALUE_ADDR (value);
Packit Service 82fcde
Packit Service 82fcde
      /* Get the symbol name.  */
Packit Service 82fcde
      const char *strtab = (const void *) D_PTR (reloc_result->bound,
Packit Service 82fcde
						 l_info[DT_STRTAB]);
Packit Service 82fcde
      const char *symname = strtab + sym.st_name;
Packit Service 82fcde
Packit Service 82fcde
      /* Keep track of overwritten addresses.  */
Packit Service 82fcde
      unsigned int flags = reloc_result->flags;
Packit Service 82fcde
Packit Service 82fcde
      struct audit_ifaces *afct = GLRO(dl_audit);
Packit Service 82fcde
      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (afct->ARCH_LA_PLTENTER != NULL
Packit Service 82fcde
	      && (reloc_result->enterexit
Packit Service 82fcde
		  & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      long int new_framesize = -1;
Packit Service 82fcde
	      uintptr_t new_value
Packit Service 82fcde
		= afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
Packit Service 82fcde
					  &l->l_audit[cnt].cookie,
Packit Service 82fcde
					  &reloc_result->bound->l_audit[cnt].cookie,
Packit Service 82fcde
					  regs, &flags, symname,
Packit Service 82fcde
					  &new_framesize);
Packit Service 82fcde
	      if (new_value != (uintptr_t) sym.st_value)
Packit Service 82fcde
		{
Packit Service 82fcde
		  flags |= LA_SYMB_ALTVALUE;
Packit Service 82fcde
		  sym.st_value = new_value;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      /* Remember the results for every audit library and
Packit Service 82fcde
		 store a summary in the first two bits.  */
Packit Service 82fcde
	      reloc_result->enterexit
Packit Service 82fcde
		|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
Packit Service 82fcde
		    << (2 * (cnt + 1)));
Packit Service 82fcde
Packit Service 82fcde
	      if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
Packit Service 82fcde
					      << (2 * (cnt + 1))))
Packit Service 82fcde
		  == 0 && new_framesize != -1 && framesize != -2)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* If this is the first call providing information,
Packit Service 82fcde
		     use it.  */
Packit Service 82fcde
		  if (framesize == -1)
Packit Service 82fcde
		    framesize = new_framesize;
Packit Service 82fcde
		  /* If two pltenter calls provide conflicting information,
Packit Service 82fcde
		     use the larger value.  */
Packit Service 82fcde
		  else if (new_framesize != framesize)
Packit Service 82fcde
		    framesize = MAX (new_framesize, framesize);
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  afct = afct->next;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      value = DL_FIXUP_ADDR_VALUE (sym.st_value);
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  /* Store the frame size information.  */
Packit Service 82fcde
  *framesizep = framesize;
Packit Service 82fcde
Packit Service 82fcde
  (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
Packit Service 82fcde
Packit Service 82fcde
  return value;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif /* PROF */
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
void
Packit Service 82fcde
ARCH_FIXUP_ATTRIBUTE
Packit Service 82fcde
_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
Packit Service 82fcde
		  const void *inregs, void *outregs)
Packit Service 82fcde
{
Packit Service 82fcde
#ifdef SHARED
Packit Service 82fcde
  /* This is the address in the array where we store the result of previous
Packit Service 82fcde
     relocations.  */
Packit Service 82fcde
  // XXX Maybe the bound information must be stored on the stack since
Packit Service 82fcde
  // XXX with bind_not a new value could have been stored in the meantime.
Packit Service 82fcde
  struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
Packit Service 82fcde
  ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
Packit Service 82fcde
					    l_info[DT_SYMTAB])
Packit Service 82fcde
		       + reloc_result->boundndx);
Packit Service 82fcde
Packit Service 82fcde
  /* Set up the sym parameter.  */
Packit Service 82fcde
  ElfW(Sym) sym = *defsym;
Packit Service 82fcde
  sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
Packit Service 82fcde
Packit Service 82fcde
  /* Get the symbol name.  */
Packit Service 82fcde
  const char *strtab = (const void *) D_PTR (reloc_result->bound,
Packit Service 82fcde
					     l_info[DT_STRTAB]);
Packit Service 82fcde
  const char *symname = strtab + sym.st_name;
Packit Service 82fcde
Packit Service 82fcde
  struct audit_ifaces *afct = GLRO(dl_audit);
Packit Service 82fcde
  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (afct->ARCH_LA_PLTEXIT != NULL
Packit Service 82fcde
	  && (reloc_result->enterexit
Packit Service 82fcde
	      & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
Packit Service 82fcde
				 &l->l_audit[cnt].cookie,
Packit Service 82fcde
				 &reloc_result->bound->l_audit[cnt].cookie,
Packit Service 82fcde
				 inregs, outregs, symname);
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      afct = afct->next;
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
}