Blame sysdeps/aarch64/dl-machine.h

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