Blame sysdeps/aarch64/dl-machine.h

Packit Service 82fcde
/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
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 License as
Packit Service 82fcde
   published by the Free Software Foundation; either version 2.1 of the
Packit Service 82fcde
   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
#ifndef dl_machine_h
Packit Service 82fcde
#define dl_machine_h
Packit Service 82fcde
Packit Service 82fcde
#define ELF_MACHINE_NAME "aarch64"
Packit Service 82fcde
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#include <tls.h>
Packit Service 82fcde
#include <dl-tlsdesc.h>
Packit Service 82fcde
#include <dl-irel.h>
Packit Service 82fcde
#include <cpu-features.c>
Packit Service 82fcde
Packit Service 82fcde
/* Return nonzero iff ELF header is compatible with the running host.  */
Packit Service 82fcde
static inline int __attribute__ ((unused))
Packit Service 82fcde
elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
Packit Service 82fcde
{
Packit Service 82fcde
  return ehdr->e_machine == EM_AARCH64;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
Packit Service 82fcde
   first element of the GOT. */
Packit Service 82fcde
static inline ElfW(Addr) __attribute__ ((unused))
Packit Service 82fcde
elf_machine_dynamic (void)
Packit Service 82fcde
{
Packit Service 82fcde
  extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
Packit Service 82fcde
  return _GLOBAL_OFFSET_TABLE_[0];
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 ElfW(Addr) __attribute__ ((unused))
Packit Service 82fcde
elf_machine_load_address (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* To figure out the load address we use the definition that for any symbol:
Packit Service 82fcde
     dynamic_addr(symbol) = static_addr(symbol) + load_addr
Packit Service 82fcde
Packit Service 82fcde
    _DYNAMIC sysmbol is used here as its link-time address stored in
Packit Service 82fcde
    the special unrelocated first GOT entry.  */
Packit Service 82fcde
Packit Service 82fcde
    extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
Packit Service 82fcde
    return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
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 __attribute__ ((unused))
Packit Service 82fcde
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
Packit Service 82fcde
{
Packit Service 82fcde
  if (l->l_info[DT_JMPREL] && lazy)
Packit Service 82fcde
    {
Packit Service 82fcde
      ElfW(Addr) *got;
Packit Service 82fcde
      extern void _dl_runtime_resolve (ElfW(Word));
Packit Service 82fcde
      extern void _dl_runtime_profile (ElfW(Word));
Packit Service 82fcde
Packit Service 82fcde
      got = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
Packit Service 82fcde
      if (got[1])
Packit Service 82fcde
	{
Packit Service 82fcde
	  l->l_mach.plt = got[1] + l->l_addr;
Packit Service 82fcde
	}
Packit Service 82fcde
      got[1] = (ElfW(Addr)) l;
Packit Service 82fcde
Packit Service 82fcde
      /* The got[2] entry contains the address of a function which gets
Packit Service 82fcde
	 called to get the address of a so far unresolved function and
Packit Service 82fcde
	 jump to it.  The profiling extension of the dynamic linker allows
Packit Service 82fcde
	 to intercept the calls to collect information.  In this case we
Packit Service 82fcde
	 don't store the address in the GOT so that all future calls also
Packit Service 82fcde
	 end in this function.  */
Packit Service 82fcde
      if ( profile)
Packit Service 82fcde
	{
Packit Service 82fcde
	   got[2] = (ElfW(Addr)) &_dl_runtime_profile;
Packit Service 82fcde
Packit Service 82fcde
	  if (GLRO(dl_profile) != NULL
Packit Service 82fcde
	      && _dl_name_match_p (GLRO(dl_profile), l))
Packit Service 82fcde
	    /* Say that we really want profiling and the timers are
Packit Service 82fcde
	       started.  */
Packit Service 82fcde
	    GL(dl_profile_map) = l;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* This function will get called to fix up the GOT entry
Packit Service 82fcde
	     indicated by the offset on the stack, and then jump to
Packit Service 82fcde
	     the resolved address.  */
Packit Service 82fcde
	  got[2] = (ElfW(Addr)) &_dl_runtime_resolve;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return lazy;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Initial entry point for the dynamic linker. The C function
Packit Service 82fcde
   _dl_start is the real entry point, its return value is the user
Packit Service 82fcde
   program's entry point */
Packit Service 82fcde
#ifdef __LP64__
Packit Service 82fcde
# define RTLD_START RTLD_START_1 ("x", "3", "sp")
Packit Service 82fcde
#else
Packit Service 82fcde
# define RTLD_START RTLD_START_1 ("w", "2", "wsp")
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#define RTLD_START_1(PTR, PTR_SIZE_LOG, PTR_SP) asm ("\
Packit Service 82fcde
.text									\n\
Packit Service 82fcde
.globl _start								\n\
Packit Service 82fcde
.type _start, %function							\n\
Packit Service 82fcde
.globl _dl_start_user							\n\
Packit Service 82fcde
.type _dl_start_user, %function						\n\
Packit Service 82fcde
_start:									\n\
Packit Service 82fcde
	mov	" PTR "0, " PTR_SP "					\n\
Packit Service 82fcde
	bl	_dl_start						\n\
Packit Service 82fcde
	// returns user entry point in x0				\n\
Packit Service 82fcde
	mov	x21, x0							\n\
Packit Service 82fcde
_dl_start_user:								\n\
Packit Service 82fcde
	// get the original arg count					\n\
Packit Service 82fcde
	ldr	" PTR "1, [sp]						\n\
Packit Service 82fcde
	// get the argv address						\n\
Packit Service 82fcde
	add	" PTR "2, " PTR_SP ", #(1<<"  PTR_SIZE_LOG ")		\n\
Packit Service 82fcde
	// get _dl_skip_args to see if we were				\n\
Packit Service 82fcde
	// invoked as an executable					\n\
Packit Service 82fcde
	adrp	x4, _dl_skip_args					\n\
Packit Service 82fcde
        ldr	w4, [x4, #:lo12:_dl_skip_args]				\n\
Packit Service 82fcde
	// do we need to adjust argc/argv				\n\
Packit Service 82fcde
        cmp	w4, 0							\n\
Packit Service 82fcde
	beq	.L_done_stack_adjust					\n\
Packit Service 82fcde
	// subtract _dl_skip_args from original arg count		\n\
Packit Service 82fcde
	sub	" PTR "1, " PTR "1, " PTR "4				\n\
Packit Service 82fcde
	// store adjusted argc back to stack				\n\
Packit Service 82fcde
	str	" PTR "1, [sp]						\n\
Packit Service 82fcde
	// find the first unskipped argument				\n\
Packit Service 82fcde
	mov	" PTR "3, " PTR "2					\n\
Packit Service 82fcde
	add	" PTR "4, " PTR "2, " PTR "4, lsl #" PTR_SIZE_LOG "	\n\
Packit Service 82fcde
	// shuffle argv down						\n\
Packit Service 82fcde
1:	ldr	" PTR "5, [x4], #(1<<"  PTR_SIZE_LOG ")			\n\
Packit Service 82fcde
	str	" PTR "5, [x3], #(1<<"  PTR_SIZE_LOG ")			\n\
Packit Service 82fcde
	cmp	" PTR "5, #0						\n\
Packit Service 82fcde
	bne	1b							\n\
Packit Service 82fcde
	// shuffle envp down						\n\
Packit Service 82fcde
1:	ldr	" PTR "5, [x4], #(1<<"  PTR_SIZE_LOG ")			\n\
Packit Service 82fcde
	str	" PTR "5, [x3], #(1<<"  PTR_SIZE_LOG ")			\n\
Packit Service 82fcde
	cmp	" PTR "5, #0						\n\
Packit Service 82fcde
	bne	1b							\n\
Packit Service 82fcde
	// shuffle auxv down						\n\
Packit Service 82fcde
1:	ldp	" PTR "0, " PTR "5, [x4, #(2<<"  PTR_SIZE_LOG ")]!	\n\
Packit Service 82fcde
	stp	" PTR "0, " PTR "5, [x3], #(2<<"  PTR_SIZE_LOG ")	\n\
Packit Service 82fcde
	cmp	" PTR "0, #0						\n\
Packit Service 82fcde
	bne	1b							\n\
Packit Service 82fcde
	// Update _dl_argv						\n\
Packit Service 82fcde
	adrp	x3, __GI__dl_argv					\n\
Packit Service 82fcde
	str	" PTR "2, [x3, #:lo12:__GI__dl_argv]			\n\
Packit Service 82fcde
.L_done_stack_adjust:							\n\
Packit Service 82fcde
	// compute envp							\n\
Packit Service 82fcde
	add	" PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG "	\n\
Packit Service 82fcde
	add	" PTR "3, " PTR "3, #(1<<"  PTR_SIZE_LOG ")		\n\
Packit Service 82fcde
	adrp	x16, _rtld_local					\n\
Packit Service 82fcde
        add	" PTR "16, " PTR "16, #:lo12:_rtld_local		\n\
Packit Service 82fcde
        ldr	" PTR "0, [x16]						\n\
Packit Service 82fcde
	bl	_dl_init						\n\
Packit Service 82fcde
	// load the finalizer function					\n\
Packit Service 82fcde
	adrp	x0, _dl_fini						\n\
Packit Service 82fcde
	add	" PTR "0, " PTR "0, #:lo12:_dl_fini			\n\
Packit Service 82fcde
	// jump to the user_s entry point				\n\
Packit Service 82fcde
	br      x21							\n\
Packit Service 82fcde
");
Packit Service 82fcde
Packit Service 82fcde
#define elf_machine_type_class(type)					\
Packit Service 82fcde
  ((((type) == AARCH64_R(JUMP_SLOT)					\
Packit Service 82fcde
     || (type) == AARCH64_R(TLS_DTPMOD)					\
Packit Service 82fcde
     || (type) == AARCH64_R(TLS_DTPREL)					\
Packit Service 82fcde
     || (type) == AARCH64_R(TLS_TPREL)					\
Packit Service 82fcde
     || (type) == AARCH64_R(TLSDESC)) * ELF_RTYPE_CLASS_PLT)		\
Packit Service 82fcde
   | (((type) == AARCH64_R(COPY)) * ELF_RTYPE_CLASS_COPY)		\
Packit Service 82fcde
   | (((type) == AARCH64_R(GLOB_DAT)) * ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA))
Packit Service 82fcde
Packit Service 82fcde
#define ELF_MACHINE_JMP_SLOT	AARCH64_R(JUMP_SLOT)
Packit Service 82fcde
Packit Service 82fcde
/* AArch64 uses RELA not REL */
Packit Service 82fcde
#define ELF_MACHINE_NO_REL 1
Packit Service 82fcde
#define ELF_MACHINE_NO_RELA 0
Packit Service 82fcde
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
#ifdef SHARED
Packit Service 82fcde
  /* init_cpu_features has been called early from __libc_start_main in
Packit Service 82fcde
     static executable.  */
Packit Service 82fcde
  init_cpu_features (&GLRO(dl_aarch64_cpu_features));
Packit Service 82fcde
#endif
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static inline ElfW(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 ElfW(Rela) *reloc,
Packit Service 82fcde
		       ElfW(Addr) *reloc_addr,
Packit Service 82fcde
		       ElfW(Addr) value)
Packit Service 82fcde
{
Packit Service 82fcde
  return *reloc_addr = value;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the final value of a plt relocation.  */
Packit Service 82fcde
static inline ElfW(Addr)
Packit Service 82fcde
elf_machine_plt_value (struct link_map *map,
Packit Service 82fcde
		       const ElfW(Rela) *reloc,
Packit Service 82fcde
		       ElfW(Addr) value)
Packit Service 82fcde
{
Packit Service 82fcde
  return value;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Names of the architecture-specific auditing callback functions.  */
Packit Service 82fcde
#define ARCH_LA_PLTENTER aarch64_gnu_pltenter
Packit Service 82fcde
#define ARCH_LA_PLTEXIT  aarch64_gnu_pltexit
Packit Service 82fcde
Packit Service 82fcde
#ifdef RESOLVE_MAP
Packit Service 82fcde
Packit Service 82fcde
auto inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
Packit Service 82fcde
		  const ElfW(Sym) *sym, const struct r_found_version *version,
Packit Service 82fcde
		  void *const reloc_addr_arg, int skip_ifunc)
Packit Service 82fcde
{
Packit Service 82fcde
  ElfW(Addr) *const reloc_addr = reloc_addr_arg;
Packit Service 82fcde
  const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
Packit Service 82fcde
Packit Service 82fcde
  if (__builtin_expect (r_type == AARCH64_R(RELATIVE), 0))
Packit Service 82fcde
      *reloc_addr = map->l_addr + reloc->r_addend;
Packit Service 82fcde
  else if (__builtin_expect (r_type == R_AARCH64_NONE, 0))
Packit Service 82fcde
      return;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      const ElfW(Sym) *const refsym = sym;
Packit Service 82fcde
      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Packit Service 82fcde
      ElfW(Addr) value = SYMBOL_ADDRESS (sym_map, sym, true);
Packit Service 82fcde
Packit Service 82fcde
      if (sym != NULL
Packit Service 82fcde
	  && __glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
Packit Service 82fcde
	  && __glibc_likely (sym->st_shndx != SHN_UNDEF)
Packit Service 82fcde
	  && __glibc_likely (!skip_ifunc))
Packit Service 82fcde
	value = elf_ifunc_invoke (value);
Packit Service 82fcde
Packit Service 82fcde
      switch (r_type)
Packit Service 82fcde
	{
Packit Service 82fcde
	case AARCH64_R(COPY):
Packit Service 82fcde
	  if (sym == NULL)
Packit Service 82fcde
	      break;
Packit Service 82fcde
Packit Service 82fcde
	  if (sym->st_size > refsym->st_size
Packit Service 82fcde
	      || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      const char *strtab;
Packit Service 82fcde
Packit Service 82fcde
	      strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
Packit Service 82fcde
	      _dl_error_printf ("\
Packit Service 82fcde
%s: Symbol `%s' has different size in shared object, consider re-linking\n",
Packit Service 82fcde
				RTLD_PROGNAME, strtab + refsym->st_name);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  memcpy (reloc_addr_arg, (void *) value,
Packit Service 82fcde
		  sym->st_size < refsym->st_size
Packit Service 82fcde
		  ? sym->st_size : refsym->st_size);
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case AARCH64_R(RELATIVE):
Packit Service 82fcde
	case AARCH64_R(GLOB_DAT):
Packit Service 82fcde
	case AARCH64_R(JUMP_SLOT):
Packit Service 82fcde
	case AARCH64_R(ABS32):
Packit Service 82fcde
#ifdef __LP64__
Packit Service 82fcde
	case AARCH64_R(ABS64):
Packit Service 82fcde
#endif
Packit Service 82fcde
	  *reloc_addr = value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case AARCH64_R(TLSDESC):
Packit Service 82fcde
	  {
Packit Service 82fcde
	    struct tlsdesc volatile *td =
Packit Service 82fcde
	      (struct tlsdesc volatile *)reloc_addr;
Packit Service 82fcde
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
	    if (! sym)
Packit Service 82fcde
	      {
Packit Service 82fcde
		td->arg = (void*)reloc->r_addend;
Packit Service 82fcde
		td->entry = _dl_tlsdesc_undefweak;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    else
Packit Service 82fcde
#endif
Packit Service 82fcde
	      {
Packit Service 82fcde
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
# ifndef SHARED
Packit Service 82fcde
		CHECK_STATIC_TLS (map, sym_map);
Packit Service 82fcde
# else
Packit Service 82fcde
		if (!TRY_STATIC_TLS (map, sym_map))
Packit Service 82fcde
		  {
Packit Service 82fcde
		    td->arg = _dl_make_tlsdesc_dynamic
Packit Service 82fcde
		      (sym_map, sym->st_value + reloc->r_addend);
Packit Service 82fcde
		    td->entry = _dl_tlsdesc_dynamic;
Packit Service 82fcde
		  }
Packit Service 82fcde
		else
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
		  {
Packit Service 82fcde
		    td->arg = (void*)(sym->st_value + sym_map->l_tls_offset
Packit Service 82fcde
				      + reloc->r_addend);
Packit Service 82fcde
		    td->entry = _dl_tlsdesc_return;
Packit Service 82fcde
		  }
Packit Service 82fcde
	      }
Packit Service 82fcde
	    break;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	case AARCH64_R(TLS_DTPMOD):
Packit Service 82fcde
#ifdef RTLD_BOOTSTRAP
Packit Service 82fcde
	  *reloc_addr = 1;
Packit Service 82fcde
#else
Packit Service 82fcde
	  if (sym_map != NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      *reloc_addr = sym_map->l_tls_modid;
Packit Service 82fcde
	    }
Packit Service 82fcde
#endif
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case AARCH64_R(TLS_DTPREL):
Packit Service 82fcde
	  if (sym)
Packit Service 82fcde
	    *reloc_addr = sym->st_value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case AARCH64_R(TLS_TPREL):
Packit Service 82fcde
	  if (sym)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      CHECK_STATIC_TLS (map, sym_map);
Packit Service 82fcde
	      *reloc_addr =
Packit Service 82fcde
		sym->st_value + reloc->r_addend + sym_map->l_tls_offset;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case AARCH64_R(IRELATIVE):
Packit Service 82fcde
	  value = map->l_addr + reloc->r_addend;
Packit Service 82fcde
	  value = elf_ifunc_invoke (value);
Packit Service 82fcde
	  *reloc_addr = value;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	default:
Packit Service 82fcde
	  _dl_reloc_bad_type (map, r_type, 0);
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_rela_relative (ElfW(Addr) l_addr,
Packit Service 82fcde
			   const ElfW(Rela) *reloc,
Packit Service 82fcde
			   void *const reloc_addr_arg)
Packit Service 82fcde
{
Packit Service 82fcde
  ElfW(Addr) *const reloc_addr = reloc_addr_arg;
Packit Service 82fcde
  *reloc_addr = l_addr + reloc->r_addend;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_lazy_rel (struct link_map *map,
Packit Service 82fcde
		      ElfW(Addr) l_addr,
Packit Service 82fcde
		      const ElfW(Rela) *reloc,
Packit Service 82fcde
		      int skip_ifunc)
Packit Service 82fcde
{
Packit Service 82fcde
  ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
Packit Service 82fcde
  const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
Packit Service 82fcde
  /* Check for unexpected PLT reloc type.  */
Packit Service 82fcde
  if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1))
Packit Service 82fcde
    {
Packit Service 1c5418
      if (__builtin_expect (map->l_mach.plt, 0) == 0)
Packit Service 1c5418
	*reloc_addr += l_addr;
Packit Service 1c5418
      else
Packit Service 1c5418
	*reloc_addr = map->l_mach.plt;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1))
Packit Service 82fcde
    {
Packit Service 82fcde
      const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
Packit Service 82fcde
      const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
Packit Service 82fcde
      const ElfW (Sym) *sym = &symtab[symndx];
Packit Service 82fcde
      const struct r_found_version *version = NULL;
Packit Service 82fcde
Packit Service 82fcde
      if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  const ElfW (Half) *vernum =
Packit Service 82fcde
	    (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
Packit Service 82fcde
	  version = &map->l_versions[vernum[symndx] & 0x7fff];
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Always initialize TLS descriptors completely, because lazy
Packit Service 82fcde
	 initialization requires synchronization at every TLS access.  */
Packit Service 82fcde
      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (__glibc_unlikely (r_type == AARCH64_R(IRELATIVE)))
Packit Service 82fcde
    {
Packit Service 82fcde
      ElfW(Addr) value = map->l_addr + reloc->r_addend;
Packit Service 82fcde
      if (__glibc_likely (!skip_ifunc))
Packit Service 82fcde
	value = elf_ifunc_invoke (value);
Packit Service 82fcde
      *reloc_addr = value;
Packit Service 82fcde
    }
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