Blame elf/do-rel.h

Packit Service 82fcde
/* Do relocations for ELF dynamic linking.
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
/* This file may be included twice, to define both
Packit Service 82fcde
   `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.  */
Packit Service 82fcde
Packit Service 82fcde
#ifdef DO_RELA
Packit Service 82fcde
# define elf_dynamic_do_Rel		elf_dynamic_do_Rela
Packit Service 82fcde
# define Rel				Rela
Packit Service 82fcde
# define elf_machine_rel		elf_machine_rela
Packit Service 82fcde
# define elf_machine_rel_relative	elf_machine_rela_relative
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifndef DO_ELF_MACHINE_REL_RELATIVE
Packit Service 82fcde
# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
Packit Service 82fcde
  elf_machine_rel_relative (l_addr, relative,				      \
Packit Service 82fcde
			    (void *) (l_addr + relative->r_offset))
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Perform the relocations in MAP on the running program image as specified
Packit Service 82fcde
   by RELTAG, SZTAG.  If LAZY is nonzero, this is the first pass on PLT
Packit Service 82fcde
   relocations; they should be set up to call _dl_runtime_resolve, rather
Packit Service 82fcde
   than fully resolved now.  */
Packit Service 82fcde
Packit Service 82fcde
auto inline void __attribute__ ((always_inline))
Packit Service 82fcde
elf_dynamic_do_Rel (struct link_map *map,
Packit Service 82fcde
		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
Packit Service 82fcde
		    __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
Packit Service 82fcde
		    int lazy, int skip_ifunc)
Packit Service 82fcde
{
Packit Service 82fcde
  const ElfW(Rel) *r = (const void *) reladdr;
Packit Service 82fcde
  const ElfW(Rel) *end = (const void *) (reladdr + relsize);
Packit Service 82fcde
  ElfW(Addr) l_addr = map->l_addr;
Packit Service 82fcde
# if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
Packit Service 82fcde
  const ElfW(Rel) *r2 = NULL;
Packit Service 82fcde
  const ElfW(Rel) *end2 = NULL;
Packit Service 82fcde
# endif
Packit Service 82fcde
Packit Service 82fcde
#if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
Packit Service 82fcde
  /* We never bind lazily during ld.so bootstrap.  Unfortunately gcc is
Packit Service 82fcde
     not clever enough to see through all the function calls to realize
Packit Service 82fcde
     that.  */
Packit Service 82fcde
  if (lazy)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Doing lazy PLT relocations; they need very little info.  */
Packit Service 82fcde
      for (; r < end; ++r)
Packit Service 82fcde
# ifdef ELF_MACHINE_IRELATIVE
Packit Service 82fcde
	if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    if (r2 == NULL)
Packit Service 82fcde
	      r2 = r;
Packit Service 82fcde
	    end2 = r;
Packit Service 82fcde
	  }
Packit Service 82fcde
	else
Packit Service 82fcde
# endif
Packit Service 82fcde
	  elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
Packit Service 82fcde
Packit Service 82fcde
# ifdef ELF_MACHINE_IRELATIVE
Packit Service 82fcde
      if (r2 != NULL)
Packit Service 82fcde
	for (; r2 <= end2; ++r2)
Packit Service 82fcde
	  if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
Packit Service 82fcde
	    elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc);
Packit Service 82fcde
# endif
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
#endif
Packit Service 82fcde
    {
Packit Service 82fcde
      const ElfW(Sym) *const symtab =
Packit Service 82fcde
	(const void *) D_PTR (map, l_info[DT_SYMTAB]);
Packit Service 82fcde
      const ElfW(Rel) *relative = r;
Packit Service 82fcde
      r += nrelative;
Packit Service 82fcde
Packit Service 82fcde
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
      /* This is defined in rtld.c, but nowhere in the static libc.a; make
Packit Service 82fcde
	 the reference weak so static programs can still link.  This
Packit Service 82fcde
	 declaration cannot be done when compiling rtld.c (i.e. #ifdef
Packit Service 82fcde
	 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
Packit Service 82fcde
	 _dl_rtld_map, which is incompatible with a weak decl in the same
Packit Service 82fcde
	 file.  */
Packit Service 82fcde
# ifndef SHARED
Packit Service 82fcde
      weak_extern (GL(dl_rtld_map));
Packit Service 82fcde
# endif
Packit Service 82fcde
      if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
Packit Service 82fcde
# if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE
Packit Service 82fcde
	/* Rela platforms get the offset from r_addend and this must
Packit Service 82fcde
	   be copied in the relocation address.  Therefore we can skip
Packit Service 82fcde
	   the relative relocations only if this is for rel
Packit Service 82fcde
	   relocations or rela relocations if they are computed as
Packit Service 82fcde
	   memory_loc += l_addr...  */
Packit Service 82fcde
	if (l_addr != 0)
Packit Service 82fcde
# else
Packit Service 82fcde
	/* ...or we know the object has been prelinked.  */
Packit Service 82fcde
	if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)])
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
	  for (; relative < r; ++relative)
Packit Service 82fcde
	    DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
Packit Service 82fcde
Packit Service 82fcde
#ifdef RTLD_BOOTSTRAP
Packit Service 82fcde
      /* The dynamic linker always uses versioning.  */
Packit Service 82fcde
      assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
Packit Service 82fcde
#else
Packit Service 82fcde
      if (map->l_info[VERSYMIDX (DT_VERSYM)])
Packit Service 82fcde
#endif
Packit Service 82fcde
	{
Packit Service 82fcde
	  const ElfW(Half) *const version =
Packit Service 82fcde
	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
Packit Service 82fcde
Packit Service 82fcde
	  for (; r < end; ++r)
Packit Service 82fcde
	    {
Packit Service 82fcde
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
Packit Service 82fcde
	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
Packit Service 82fcde
		{
Packit Service 82fcde
		  if (r2 == NULL)
Packit Service 82fcde
		    r2 = r;
Packit Service 82fcde
		  end2 = r;
Packit Service 82fcde
		  continue;
Packit Service 82fcde
		}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
Packit Service 82fcde
	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
Packit Service 82fcde
			       &map->l_versions[ndx],
Packit Service 82fcde
			       (void *) (l_addr + r->r_offset), skip_ifunc);
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
Packit Service 82fcde
	  if (r2 != NULL)
Packit Service 82fcde
	    for (; r2 <= end2; ++r2)
Packit Service 82fcde
	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
Packit Service 82fcde
		{
Packit Service 82fcde
		  ElfW(Half) ndx
Packit Service 82fcde
		    = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
Packit Service 82fcde
		  elf_machine_rel (map, r2,
Packit Service 82fcde
				   &symtab[ELFW(R_SYM) (r2->r_info)],
Packit Service 82fcde
				   &map->l_versions[ndx],
Packit Service 82fcde
				   (void *) (l_addr + r2->r_offset),
Packit Service 82fcde
				   skip_ifunc);
Packit Service 82fcde
		}
Packit Service 82fcde
#endif
Packit Service 82fcde
	}
Packit Service 82fcde
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  for (; r < end; ++r)
Packit Service 82fcde
# ifdef ELF_MACHINE_IRELATIVE
Packit Service 82fcde
	    if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
Packit Service 82fcde
	      {
Packit Service 82fcde
		if (r2 == NULL)
Packit Service 82fcde
		  r2 = r;
Packit Service 82fcde
		end2 = r;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    else
Packit Service 82fcde
# endif
Packit Service 82fcde
	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
Packit Service 82fcde
			       (void *) (l_addr + r->r_offset), skip_ifunc);
Packit Service 82fcde
Packit Service 82fcde
# ifdef ELF_MACHINE_IRELATIVE
Packit Service 82fcde
	  if (r2 != NULL)
Packit Service 82fcde
	    for (; r2 <= end2; ++r2)
Packit Service 82fcde
	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
Packit Service 82fcde
		elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
Packit Service 82fcde
				 NULL, (void *) (l_addr + r2->r_offset),
Packit Service 82fcde
				 skip_ifunc);
Packit Service 82fcde
# endif
Packit Service 82fcde
	}
Packit Service 82fcde
#endif
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#undef elf_dynamic_do_Rel
Packit Service 82fcde
#undef Rel
Packit Service 82fcde
#undef elf_machine_rel
Packit Service 82fcde
#undef elf_machine_rel_relative
Packit Service 82fcde
#undef DO_ELF_MACHINE_REL_RELATIVE
Packit Service 82fcde
#undef DO_RELA