Blame sysdeps/alpha/dl-machine.h

Packit Service 82fcde
/* Machine-dependent ELF dynamic relocation inline functions.  Alpha version.
Packit Service 82fcde
   Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Richard Henderson <rth@tamu.edu>.
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 was written in the absence of an ABI -- don't expect
Packit Service 82fcde
   it to remain unchanged.  */
Packit Service 82fcde
Packit Service 82fcde
#ifndef dl_machine_h
Packit Service 82fcde
#define dl_machine_h 1
Packit Service 82fcde
Packit Service 82fcde
#define ELF_MACHINE_NAME "alpha"
Packit Service 82fcde
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Mask identifying addresses reserved for the user program,
Packit Service 82fcde
   where the dynamic linker should not map anything.  */
Packit Service 82fcde
#define ELF_MACHINE_USER_ADDRESS_MASK	0x120000000UL
Packit Service 82fcde
Packit Service 82fcde
/* Translate a processor specific dynamic tag to the index in l_info array.  */
Packit Service 82fcde
#define DT_ALPHA(x) (DT_ALPHA_##x - DT_LOPROC + DT_NUM)
Packit Service 82fcde
Packit Service 82fcde
/* Return nonzero iff ELF header is compatible with the running host.  */
Packit Service 82fcde
static inline int
Packit Service 82fcde
elf_machine_matches_host (const Elf64_Ehdr *ehdr)
Packit Service 82fcde
{
Packit Service 82fcde
  return ehdr->e_machine == EM_ALPHA;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the link-time address of _DYNAMIC.  The multiple-got-capable
Packit Service 82fcde
   linker no longer allocates the first .got entry for this.  But not to
Packit Service 82fcde
   worry, no special tricks are needed.  */
Packit Service 82fcde
static inline Elf64_Addr
Packit Service 82fcde
elf_machine_dynamic (void)
Packit Service 82fcde
{
Packit Service 82fcde
#ifndef NO_AXP_MULTI_GOT_LD
Packit Service 82fcde
  return (Elf64_Addr) &_DYNAMIC;
Packit Service 82fcde
#else
Packit Service 82fcde
  register Elf64_Addr *gp __asm__ ("$29");
Packit Service 82fcde
  return gp[-4096];
Packit Service 82fcde
#endif
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the run-time load address of the shared object.  */
Packit Service 82fcde
Packit Service 82fcde
static inline Elf64_Addr
Packit Service 82fcde
elf_machine_load_address (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* This relies on the compiler using gp-relative addresses for static symbols.  */
Packit Service 82fcde
  static void *dot = ˙
Packit Service 82fcde
  return (void *)&dot - dot;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Set up the loaded object described by L so its unrelocated PLT
Packit Service 82fcde
   entries will jump to the on-demand fixup code in dl-runtime.c.  */
Packit Service 82fcde
Packit Service 82fcde
static inline int
Packit Service 82fcde
elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
Packit Service 82fcde
{
Packit Service 82fcde
  extern char _dl_runtime_resolve_new[] attribute_hidden;
Packit Service 82fcde
  extern char _dl_runtime_profile_new[] attribute_hidden;
Packit Service 82fcde
  extern char _dl_runtime_resolve_old[] attribute_hidden;
Packit Service 82fcde
  extern char _dl_runtime_profile_old[] attribute_hidden;
Packit Service 82fcde
Packit Service 82fcde
  struct pltgot {
Packit Service 82fcde
    char *resolve;
Packit Service 82fcde
    struct link_map *link;
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
  struct pltgot *pg;
Packit Service 82fcde
  long secureplt;
Packit Service 82fcde
  char *resolve;
Packit Service 82fcde
Packit Service 82fcde
  if (map->l_info[DT_JMPREL] == 0 || !lazy)
Packit Service 82fcde
    return lazy;
Packit Service 82fcde
Packit Service 82fcde
  /* Check to see if we're using the read-only plt form.  */
Packit Service 82fcde
  secureplt = map->l_info[DT_ALPHA(PLTRO)] != 0;
Packit Service 82fcde
Packit Service 82fcde
  /* If the binary uses the read-only secure plt format, PG points to
Packit Service 82fcde
     the .got.plt section, which is the right place for ld.so to place
Packit Service 82fcde
     its hooks.  Otherwise, PG is currently pointing at the start of
Packit Service 82fcde
     the plt; the hooks go at offset 16.  */
Packit Service 82fcde
  pg = (struct pltgot *) D_PTR (map, l_info[DT_PLTGOT]);
Packit Service 82fcde
  pg += !secureplt;
Packit Service 82fcde
Packit Service 82fcde
  /* This function will be called to perform the relocation.  They're
Packit Service 82fcde
     not declared as functions to convince the compiler to use gp
Packit Service 82fcde
     relative relocations for them.  */
Packit Service 82fcde
  if (secureplt)
Packit Service 82fcde
    resolve = _dl_runtime_resolve_new;
Packit Service 82fcde
  else
Packit Service 82fcde
    resolve = _dl_runtime_resolve_old;
Packit Service 82fcde
Packit Service 82fcde
  if (__builtin_expect (profile, 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (secureplt)
Packit Service 82fcde
	resolve = _dl_runtime_profile_new;
Packit Service 82fcde
      else
Packit Service 82fcde
	resolve = _dl_runtime_profile_old;
Packit Service 82fcde
Packit Service 82fcde
      if (GLRO(dl_profile) && _dl_name_match_p (GLRO(dl_profile), map))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* This is the object we are looking for.  Say that we really
Packit Service 82fcde
	     want profiling and the timers are started.  */
Packit Service 82fcde
	  GL(dl_profile_map) = map;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  pg->resolve = resolve;
Packit Service 82fcde
  pg->link = map;
Packit Service 82fcde
Packit Service 82fcde
  return lazy;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Initial entry point code for the dynamic linker.
Packit Service 82fcde
   The C function `_dl_start' is the real entry point;
Packit Service 82fcde
   its return value is the user program's entry point.  */
Packit Service 82fcde
Packit Service 82fcde
#define RTLD_START asm ("\
Packit Service 82fcde
	.section .text						\n\
Packit Service 82fcde
	.set at							\n\
Packit Service 82fcde
	.globl _start						\n\
Packit Service 82fcde
	.ent _start						\n\
Packit Service 82fcde
_start:								\n\
Packit Service 82fcde
	.frame $31,0,$31,0					\n\
Packit Service 82fcde
	br	$gp, 0f						\n\
Packit Service 82fcde
0:	ldgp	$gp, 0($gp)					\n\
Packit Service 82fcde
	.prologue 0						\n\
Packit Service 82fcde
	/* Pass pointer to argument block to _dl_start.  */	\n\
Packit Service 82fcde
	mov	$sp, $16					\n\
Packit Service 82fcde
	bsr	$26, _dl_start		!samegp			\n\
Packit Service 82fcde
	.end _start						\n\
Packit Service 82fcde
	/* FALLTHRU */						\n\
Packit Service 82fcde
	.globl _dl_start_user					\n\
Packit Service 82fcde
	.ent _dl_start_user					\n\
Packit Service 82fcde
_dl_start_user:							\n\
Packit Service 82fcde
	.frame $31,0,$31,0					\n\
Packit Service 82fcde
	.prologue 0						\n\
Packit Service 82fcde
	/* Save the user entry point address in s0.  */		\n\
Packit Service 82fcde
	mov	$0, $9						\n\
Packit Service 82fcde
	/* See if we were run as a command with the executable	\n\
Packit Service 82fcde
	   file name as an extra leading argument.  */		\n\
Packit Service 82fcde
	ldah	$1, _dl_skip_args($gp)	!gprelhigh		\n\
Packit Service 82fcde
	ldl	$1, _dl_skip_args($1)	!gprellow		\n\
Packit Service 82fcde
	bne	$1, $fixup_stack				\n\
Packit Service 82fcde
$fixup_stack_ret:						\n\
Packit Service 82fcde
	/* The special initializer gets called with the stack	\n\
Packit Service 82fcde
	   just as the application's entry point will see it;	\n\
Packit Service 82fcde
	   it can switch stacks if it moves these contents	\n\
Packit Service 82fcde
	   over.  */						\n\
Packit Service 82fcde
" RTLD_START_SPECIAL_INIT "					\n\
Packit Service 82fcde
	/* Call _dl_init(_dl_loaded, argc, argv, envp) to run	\n\
Packit Service 82fcde
	   initializers.  */					\n\
Packit Service 82fcde
	ldah	$16, _rtld_local($gp)	!gprelhigh		\n\
Packit Service 82fcde
	ldq	$16, _rtld_local($16)	!gprellow		\n\
Packit Service 82fcde
	ldq	$17, 0($sp)					\n\
Packit Service 82fcde
	lda	$18, 8($sp)					\n\
Packit Service 82fcde
	s8addq	$17, 8, $19					\n\
Packit Service 82fcde
	addq	$19, $18, $19					\n\
Packit Service 82fcde
	bsr	$26, _dl_init		!samegp			\n\
Packit Service 82fcde
	/* Pass our finalizer function to the user in $0. */	\n\
Packit Service 82fcde
	ldah	$0, _dl_fini($gp)	!gprelhigh		\n\
Packit Service 82fcde
	lda	$0, _dl_fini($0)	!gprellow		\n\
Packit Service 82fcde
	/* Jump to the user's entry point.  */			\n\
Packit Service 82fcde
	mov	$9, $27						\n\
Packit Service 82fcde
	jmp	($9)						\n\
Packit Service 82fcde
$fixup_stack:							\n\
Packit Service 82fcde
	/* Adjust the stack pointer to skip _dl_skip_args words.\n\
Packit Service 82fcde
	   This involves copying everything down, since the	\n\
Packit Service 82fcde
	   stack pointer must always be 16-byte aligned.  */	\n\
Packit Service 82fcde
	ldah	$7, __GI__dl_argv($gp) !gprelhigh		\n\
Packit Service 82fcde
	ldq	$2, 0($sp)					\n\
Packit Service 82fcde
	ldq	$5, __GI__dl_argv($7) !gprellow			\n\
Packit Service 82fcde
	subq	$31, $1, $6					\n\
Packit Service 82fcde
	subq	$2, $1, $2					\n\
Packit Service 82fcde
	s8addq	$6, $5, $5					\n\
Packit Service 82fcde
	mov	$sp, $4						\n\
Packit Service 82fcde
	s8addq	$1, $sp, $3					\n\
Packit Service 82fcde
	stq	$2, 0($sp)					\n\
Packit Service 82fcde
	stq	$5, __GI__dl_argv($7) !gprellow			\n\
Packit Service 82fcde
	/* Copy down argv.  */					\n\
Packit Service 82fcde
0:	ldq	$5, 8($3)					\n\
Packit Service 82fcde
	addq	$4, 8, $4					\n\
Packit Service 82fcde
	addq	$3, 8, $3					\n\
Packit Service 82fcde
	stq	$5, 0($4)					\n\
Packit Service 82fcde
	bne	$5, 0b						\n\
Packit Service 82fcde
	/* Copy down envp.  */					\n\
Packit Service 82fcde
1:	ldq	$5, 8($3)					\n\
Packit Service 82fcde
	addq	$4, 8, $4					\n\
Packit Service 82fcde
	addq	$3, 8, $3					\n\
Packit Service 82fcde
	stq	$5, 0($4)					\n\
Packit Service 82fcde
	bne	$5, 1b						\n\
Packit Service 82fcde
	/* Copy down auxiliary table.  */			\n\
Packit Service 82fcde
2:	ldq	$5, 8($3)					\n\
Packit Service 82fcde
	ldq	$6, 16($3)					\n\
Packit Service 82fcde
	addq	$4, 16, $4					\n\
Packit Service 82fcde
	addq	$3, 16, $3					\n\
Packit Service 82fcde
	stq	$5, -8($4)					\n\
Packit Service 82fcde
	stq	$6, 0($4)					\n\
Packit Service 82fcde
	bne	$5, 2b						\n\
Packit Service 82fcde
	br	$fixup_stack_ret				\n\
Packit Service 82fcde
	.end _dl_start_user					\n\
Packit Service 82fcde
	.set noat						\n\
Packit Service 82fcde
.previous");
Packit Service 82fcde
Packit Service 82fcde
#ifndef RTLD_START_SPECIAL_INIT
Packit Service 82fcde
#define RTLD_START_SPECIAL_INIT /* nothing */
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry
Packit Service 82fcde
   or TLS variables, so undefined references should not be allowed
Packit Service 82fcde
   to define the value.
Packit Service 82fcde
Packit Service 82fcde
   ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve
Packit Service 82fcde
   to one of the main executable's symbols, as for a COPY reloc.
Packit Service 82fcde
   This is unused on Alpha.  */
Packit Service 82fcde
Packit Service 82fcde
# define elf_machine_type_class(type)	\
Packit Service 82fcde
  (((type) == R_ALPHA_JMP_SLOT		\
Packit Service 82fcde
    || (type) == R_ALPHA_DTPMOD64	\
Packit Service 82fcde
    || (type) == R_ALPHA_DTPREL64	\
Packit Service 82fcde
    || (type) == R_ALPHA_TPREL64) * ELF_RTYPE_CLASS_PLT)
Packit Service 82fcde
Packit Service 82fcde
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
Packit Service 82fcde
#define ELF_MACHINE_JMP_SLOT	 R_ALPHA_JMP_SLOT
Packit Service 82fcde
Packit Service 82fcde
/* The alpha never uses Elf64_Rel relocations.  */
Packit Service 82fcde
#define ELF_MACHINE_NO_REL 1
Packit Service 82fcde
#define ELF_MACHINE_NO_RELA 0
Packit Service 82fcde
Packit Service 82fcde
/* We define an initialization functions.  This is called very early in
Packit Service 82fcde
 *    _dl_sysdep_start.  */
Packit Service 82fcde
#define DL_PLATFORM_INIT dl_platform_init ()
Packit Service 82fcde
Packit Service 82fcde
static inline void __attribute__ ((unused))
Packit Service 82fcde
dl_platform_init (void)
Packit Service 82fcde
{
Packit Service 82fcde
	if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
Packit Service 82fcde
	/* Avoid an empty string which would disturb us.  */
Packit Service 82fcde
		GLRO(dl_platform) = NULL;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Fix up the instructions of a PLT entry to invoke the function
Packit Service 82fcde
   rather than the dynamic linker.  */
Packit Service 82fcde
static inline Elf64_Addr
Packit Service 82fcde
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
Packit Service 82fcde
		       const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
Packit Service 82fcde
		       const Elf64_Rela *reloc,
Packit Service 82fcde
		       Elf64_Addr *got_addr, Elf64_Addr value)
Packit Service 82fcde
{
Packit Service 82fcde
  const Elf64_Rela *rela_plt;
Packit Service 82fcde
  Elf64_Word *plte;
Packit Service 82fcde
  long int edisp;
Packit Service 82fcde
Packit Service 82fcde
  /* Store the value we are going to load.  */
Packit Service 82fcde
  *got_addr = value;
Packit Service 82fcde
Packit Service 82fcde
  /* If this binary uses the read-only secure plt format, we're done.  */
Packit Service 82fcde
  if (map->l_info[DT_ALPHA(PLTRO)])
Packit Service 82fcde
    return value;
Packit Service 82fcde
Packit Service 82fcde
  /* Otherwise we have to modify the plt entry in place to do the branch.  */
Packit Service 82fcde
Packit Service 82fcde
  /* Recover the PLT entry address by calculating reloc's index into the
Packit Service 82fcde
     .rela.plt, and finding that entry in the .plt.  */
Packit Service 82fcde
  rela_plt = (const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]);
Packit Service 82fcde
  plte = (Elf64_Word *) (D_PTR (map, l_info[DT_PLTGOT]) + 32);
Packit Service 82fcde
  plte += 3 * (reloc - rela_plt);
Packit Service 82fcde
Packit Service 82fcde
  /* Find the displacement from the plt entry to the function.  */
Packit Service 82fcde
  edisp = (long int) (value - (Elf64_Addr)&plte[3]) / 4;
Packit Service 82fcde
Packit Service 82fcde
  if (edisp >= -0x100000 && edisp < 0x100000)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* If we are in range, use br to perfect branch prediction and
Packit Service 82fcde
	 elide the dependency on the address load.  This case happens,
Packit Service 82fcde
	 e.g., when a shared library call is resolved to the same library.  */
Packit Service 82fcde
Packit Service 82fcde
      int hi, lo;
Packit Service 82fcde
      hi = value - (Elf64_Addr)&plte[0];
Packit Service 82fcde
      lo = (short int) hi;
Packit Service 82fcde
      hi = (hi - lo) >> 16;
Packit Service 82fcde
Packit Service 82fcde
      /* Emit "lda $27,lo($27)" */
Packit Service 82fcde
      plte[1] = 0x237b0000 | (lo & 0xffff);
Packit Service 82fcde
Packit Service 82fcde
      /* Emit "br $31,function" */
Packit Service 82fcde
      plte[2] = 0xc3e00000 | (edisp & 0x1fffff);
Packit Service 82fcde
Packit Service 82fcde
      /* Think about thread-safety -- the previous instructions must be
Packit Service 82fcde
	 committed to memory before the first is overwritten.  */
Packit Service 82fcde
      __asm__ __volatile__("wmb" : : : "memory");
Packit Service 82fcde
Packit Service 82fcde
      /* Emit "ldah $27,hi($27)" */
Packit Service 82fcde
      plte[0] = 0x277b0000 | (hi & 0xffff);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Don't bother with the hint since we already know the hint is
Packit Service 82fcde
	 wrong.  Eliding it prevents the wrong page from getting pulled
Packit Service 82fcde
	 into the cache.  */
Packit Service 82fcde
Packit Service 82fcde
      int hi, lo;
Packit Service 82fcde
      hi = (Elf64_Addr)got_addr - (Elf64_Addr)&plte[0];
Packit Service 82fcde
      lo = (short)hi;
Packit Service 82fcde
      hi = (hi - lo) >> 16;
Packit Service 82fcde
Packit Service 82fcde
      /* Emit "ldq $27,lo($27)" */
Packit Service 82fcde
      plte[1] = 0xa77b0000 | (lo & 0xffff);
Packit Service 82fcde
Packit Service 82fcde
      /* Emit "jmp $31,($27)" */
Packit Service 82fcde
      plte[2] = 0x6bfb0000;
Packit Service 82fcde
Packit Service 82fcde
      /* Think about thread-safety -- the previous instructions must be
Packit Service 82fcde
	 committed to memory before the first is overwritten.  */
Packit Service 82fcde
      __asm__ __volatile__("wmb" : : : "memory");
Packit Service 82fcde
Packit Service 82fcde
      /* Emit "ldah $27,hi($27)" */
Packit Service 82fcde
      plte[0] = 0x277b0000 | (hi & 0xffff);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* At this point, if we've been doing runtime resolution, Icache is dirty.
Packit Service 82fcde
     This will be taken care of in _dl_runtime_resolve.  If instead we are
Packit Service 82fcde
     doing this as part of non-lazy startup relocation, that bit of code
Packit Service 82fcde
     hasn't made it into Icache yet, so there's nothing to clean up.  */
Packit Service 82fcde
Packit Service 82fcde
  return value;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the final value of a plt relocation.  */
Packit Service 82fcde
static inline Elf64_Addr
Packit Service 82fcde
elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
Packit Service 82fcde
		       Elf64_Addr value)
Packit Service 82fcde
{
Packit Service 82fcde
  return value + reloc->r_addend;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Names of the architecture-specific auditing callback functions.  */
Packit Service 82fcde
#define ARCH_LA_PLTENTER	alpha_gnu_pltenter
Packit Service 82fcde
#define ARCH_LA_PLTEXIT		alpha_gnu_pltexit
Packit Service 82fcde
Packit Service 82fcde
#endif /* !dl_machine_h */
Packit Service 82fcde
Packit Service 82fcde
#ifdef RESOLVE_MAP
Packit Service 82fcde
Packit Service 82fcde
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
Packit Service 82fcde
   MAP is the object containing the reloc.  */
Packit Service 82fcde
auto inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_rela (struct link_map *map,
Packit Service 82fcde
		  const Elf64_Rela *reloc,
Packit Service 82fcde
		  const Elf64_Sym *sym,
Packit Service 82fcde
		  const struct r_found_version *version,
Packit Service 82fcde
		  void *const reloc_addr_arg,
Packit Service 82fcde
		  int skip_ifunc)
Packit Service 82fcde
{
Packit Service 82fcde
  Elf64_Addr *const reloc_addr = reloc_addr_arg;
Packit Service 82fcde
  unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
Packit Service 82fcde
Packit Service 82fcde
#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC && !defined SHARED
Packit Service 82fcde
  /* This is defined in rtld.c, but nowhere in the static libc.a; make the
Packit Service 82fcde
     reference weak so static programs can still link.  This declaration
Packit Service 82fcde
     cannot be done when compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP)
Packit Service 82fcde
     because rtld.c contains the common defn for _dl_rtld_map, which is
Packit Service 82fcde
     incompatible with a weak decl in the same file.  */
Packit Service 82fcde
  weak_extern (_dl_rtld_map);
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  /* We cannot use a switch here because we cannot locate the switch
Packit Service 82fcde
     jump table until we've self-relocated.  */
Packit Service 82fcde
Packit Service 82fcde
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
Packit Service 82fcde
  if (__builtin_expect (r_type == R_ALPHA_RELATIVE, 0))
Packit Service 82fcde
    {
Packit Service 82fcde
# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
Packit Service 82fcde
      /* Already done in dynamic linker.  */
Packit Service 82fcde
      if (map != &GL(dl_rtld_map))
Packit Service 82fcde
# endif
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* XXX Make some timings.  Maybe it's preferable to test for
Packit Service 82fcde
	     unaligned access and only do it the complex way if necessary.  */
Packit Service 82fcde
	  Elf64_Addr reloc_addr_val;
Packit Service 82fcde
Packit Service 82fcde
	  /* Load value without causing unaligned trap. */
Packit Service 82fcde
	  memcpy (&reloc_addr_val, reloc_addr_arg, 8);
Packit Service 82fcde
	  reloc_addr_val += map->l_addr;
Packit Service 82fcde
Packit Service 82fcde
	  /* Store value without causing unaligned trap. */
Packit Service 82fcde
	  memcpy (reloc_addr_arg, &reloc_addr_val, 8);
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
#endif
Packit Service 82fcde
    if (__builtin_expect (r_type == R_ALPHA_NONE, 0))
Packit Service 82fcde
      return;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Packit Service 82fcde
      Elf64_Addr sym_value;
Packit Service 82fcde
      Elf64_Addr sym_raw_value;
Packit Service 82fcde
Packit Service 82fcde
      sym_raw_value = sym_value = reloc->r_addend;
Packit Service 82fcde
      if (sym_map)
Packit Service 82fcde
	{
Packit Service 82fcde
	  sym_raw_value += sym->st_value;
Packit Service 82fcde
	  sym_value += SYMBOL_ADDRESS (sym_map, sym, true);
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (r_type == R_ALPHA_GLOB_DAT)
Packit Service 82fcde
	*reloc_addr = sym_value;
Packit Service 82fcde
#ifdef RESOLVE_CONFLICT_FIND_MAP
Packit Service 82fcde
      /* In .gnu.conflict section, R_ALPHA_JMP_SLOT relocations have
Packit Service 82fcde
	 R_ALPHA_JMP_SLOT in lower 8 bits and the remaining 24 bits
Packit Service 82fcde
	 are .rela.plt index.  */
Packit Service 82fcde
      else if ((r_type & 0xff) == R_ALPHA_JMP_SLOT)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* elf_machine_fixup_plt needs the map reloc_addr points into,
Packit Service 82fcde
	     while in _dl_resolve_conflicts map is _dl_loaded.  */
Packit Service 82fcde
	  RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
Packit Service 82fcde
	  reloc = ((const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]))
Packit Service 82fcde
		  + (r_type >> 8);
Packit Service 82fcde
	  elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
Packit Service 82fcde
	}
Packit Service 82fcde
#else
Packit Service 82fcde
      else if (r_type == R_ALPHA_JMP_SLOT)
Packit Service 82fcde
	elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
      else if (r_type == R_ALPHA_REFQUAD)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Store value without causing unaligned trap.  */
Packit Service 82fcde
	  memcpy (reloc_addr_arg, &sym_value, 8);
Packit Service 82fcde
	}
Packit Service 82fcde
#endif
Packit Service 82fcde
      else if (r_type == R_ALPHA_DTPMOD64)
Packit Service 82fcde
	{
Packit Service 82fcde
# ifdef RTLD_BOOTSTRAP
Packit Service 82fcde
	  /* During startup the dynamic linker is always index 1.  */
Packit Service 82fcde
	  *reloc_addr = 1;
Packit Service 82fcde
# else
Packit Service 82fcde
	  /* Get the information from the link map returned by the
Packit Service 82fcde
	     resolv function.  */
Packit Service 82fcde
	  if (sym_map != NULL)
Packit Service 82fcde
	    *reloc_addr = sym_map->l_tls_modid;
Packit Service 82fcde
# endif
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (r_type == R_ALPHA_DTPREL64)
Packit Service 82fcde
	{
Packit Service 82fcde
# ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
	  /* During relocation all TLS symbols are defined and used.
Packit Service 82fcde
	     Therefore the offset is already correct.  */
Packit Service 82fcde
	  *reloc_addr = sym_raw_value;
Packit Service 82fcde
# endif
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (r_type == R_ALPHA_TPREL64)
Packit Service 82fcde
	{
Packit Service 82fcde
# ifdef RTLD_BOOTSTRAP
Packit Service 82fcde
	  *reloc_addr = sym_raw_value + map->l_tls_offset;
Packit Service 82fcde
# else
Packit Service 82fcde
	  if (sym_map)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      CHECK_STATIC_TLS (map, sym_map);
Packit Service 82fcde
	      *reloc_addr = sym_raw_value + sym_map->l_tls_offset;
Packit Service 82fcde
	    }
Packit Service 82fcde
# endif
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	_dl_reloc_bad_type (map, r_type, 0);
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Let do-rel.h know that on Alpha if l_addr is 0, all RELATIVE relocs
Packit Service 82fcde
   can be skipped.  */
Packit Service 82fcde
#define ELF_MACHINE_REL_RELATIVE 1
Packit Service 82fcde
Packit Service 82fcde
auto inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
Packit Service 82fcde
			   void *const reloc_addr_arg)
Packit Service 82fcde
{
Packit Service 82fcde
  /* XXX Make some timings.  Maybe it's preferable to test for
Packit Service 82fcde
     unaligned access and only do it the complex way if necessary.  */
Packit Service 82fcde
  Elf64_Addr reloc_addr_val;
Packit Service 82fcde
Packit Service 82fcde
  /* Load value without causing unaligned trap. */
Packit Service 82fcde
  memcpy (&reloc_addr_val, reloc_addr_arg, 8);
Packit Service 82fcde
  reloc_addr_val += l_addr;
Packit Service 82fcde
Packit Service 82fcde
  /* Store value without causing unaligned trap. */
Packit Service 82fcde
  memcpy (reloc_addr_arg, &reloc_addr_val, 8);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
auto inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_lazy_rel (struct link_map *map,
Packit Service 82fcde
		      Elf64_Addr l_addr, const Elf64_Rela *reloc,
Packit Service 82fcde
		      int skip_ifunc)
Packit Service 82fcde
{
Packit Service 82fcde
  Elf64_Addr * const reloc_addr = (void *)(l_addr + reloc->r_offset);
Packit Service 82fcde
  unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
Packit Service 82fcde
Packit Service 82fcde
  if (r_type == R_ALPHA_JMP_SLOT)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Perform a RELATIVE reloc on the .got entry that transfers
Packit Service 82fcde
	 to the .plt.  */
Packit Service 82fcde
      *reloc_addr += l_addr;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (r_type == R_ALPHA_NONE)
Packit Service 82fcde
    return;
Packit Service 82fcde
  else
Packit Service 82fcde
    _dl_reloc_bad_type (map, r_type, 1);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif /* RESOLVE_MAP */