Blame sysdeps/s390/s390-64/dl-machine.h

Packit Service 82fcde
/* Machine-dependent ELF dynamic relocation inline functions.
Packit Service 82fcde
   64 bit S/390 Version.
Packit Service 82fcde
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
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
#ifndef dl_machine_h
Packit Service 82fcde
#define dl_machine_h
Packit Service 82fcde
Packit Service 82fcde
#define ELF_MACHINE_NAME "s390x"
Packit Service 82fcde
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <link.h>
Packit Service 82fcde
#include <sysdeps/s390/dl-procinfo.h>
Packit Service 82fcde
#include <dl-irel.h>
Packit Service 82fcde
Packit Service 82fcde
#define ELF_MACHINE_IRELATIVE       R_390_IRELATIVE
Packit Service 82fcde
Packit Service 82fcde
/* This is an older, now obsolete value.  */
Packit Service 82fcde
#define EM_S390_OLD	0xA390
Packit Service 82fcde
Packit Service 82fcde
/* Return nonzero iff E_MACHINE 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_S390 || ehdr->e_machine == EM_S390_OLD)
Packit Service 82fcde
	 && ehdr->e_ident[EI_CLASS] == ELFCLASS64;
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.  This must be inlined in a function which
Packit Service 82fcde
   uses global data.  */
Packit Service 82fcde
Packit Service 82fcde
static inline Elf64_Addr
Packit Service 82fcde
elf_machine_dynamic (void)
Packit Service 82fcde
{
Packit Service 82fcde
  register Elf64_Addr *got;
Packit Service 82fcde
Packit Service 82fcde
  __asm__ ( "	larl   %0,_GLOBAL_OFFSET_TABLE_\n"
Packit Service 82fcde
	    : "=&a" (got) : : "0" );
Packit Service 82fcde
Packit Service 82fcde
  return *got;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the run-time load address of the shared object.  */
Packit Service 82fcde
static inline Elf64_Addr
Packit Service 82fcde
elf_machine_load_address (void)
Packit Service 82fcde
{
Packit Service 82fcde
  Elf64_Addr addr;
Packit Service 82fcde
Packit Service 82fcde
  __asm__( "   larl	 %0,_dl_start\n"
Packit Service 82fcde
	   "   larl	 1,_GLOBAL_OFFSET_TABLE_\n"
Packit Service 82fcde
	   "   lghi	 2,_dl_start@GOT\n"
Packit Service 82fcde
	   "   slg	 %0,0(2,1)"
Packit Service 82fcde
	   : "=&d" (addr) : : "1", "2" );
Packit Service 82fcde
  return addr;
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
  extern void _dl_runtime_resolve (Elf64_Word);
Packit Service 82fcde
  extern void _dl_runtime_profile (Elf64_Word);
Packit Service 82fcde
#if defined HAVE_S390_VX_ASM_SUPPORT
Packit Service 82fcde
  extern void _dl_runtime_resolve_vx (Elf64_Word);
Packit Service 82fcde
  extern void _dl_runtime_profile_vx (Elf64_Word);
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  if (l->l_info[DT_JMPREL] && lazy)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* The GOT entries for functions in the PLT have not yet been filled
Packit Service 82fcde
	 in.  Their initial contents will arrange when called to push an
Packit Service 82fcde
	 offset into the .rela.plt section, push _GLOBAL_OFFSET_TABLE_[1],
Packit Service 82fcde
	 and then jump to _GLOBAL_OFFSET_TABLE[2].  */
Packit Service 82fcde
      Elf64_Addr *got;
Packit Service 82fcde
      got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
Packit Service 82fcde
      /* If a library is prelinked but we have to relocate anyway,
Packit Service 82fcde
	 we have to be able to undo the prelinking of .got.plt.
Packit Service 82fcde
	 The prelinker saved us here address of .plt + 0x2e.  */
Packit Service 82fcde
      if (got[1])
Packit Service 82fcde
	{
Packit Service 82fcde
	  l->l_mach.plt = got[1] + l->l_addr;
Packit Service 82fcde
	  l->l_mach.jmprel = (const Elf64_Rela *) D_PTR (l, l_info[DT_JMPREL]);
Packit Service 82fcde
	}
Packit Service 82fcde
      got[1] = (Elf64_Addr) l;	/* Identify this shared object.	 */
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 (__glibc_unlikely (profile))
Packit Service 82fcde
	{
Packit Service 82fcde
#if defined HAVE_S390_VX_ASM_SUPPORT
Packit Service 82fcde
	  if (GLRO(dl_hwcap) & HWCAP_S390_VX)
Packit Service 82fcde
	    got[2] = (Elf64_Addr) &_dl_runtime_profile_vx;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    got[2] = (Elf64_Addr) &_dl_runtime_profile;
Packit Service 82fcde
#else
Packit Service 82fcde
	  got[2] = (Elf64_Addr) &_dl_runtime_profile;
Packit Service 82fcde
#endif
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
	    /* 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) = 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 indicated by
Packit Service 82fcde
	     the offset on the stack, and then jump to the resolved address.  */
Packit Service 82fcde
#if defined HAVE_S390_VX_ASM_SUPPORT
Packit Service 82fcde
	  if (GLRO(dl_hwcap) & HWCAP_S390_VX)
Packit Service 82fcde
	    got[2] = (Elf64_Addr) &_dl_runtime_resolve_vx;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    got[2] = (Elf64_Addr) &_dl_runtime_resolve;
Packit Service 82fcde
#else
Packit Service 82fcde
	  got[2] = (Elf64_Addr) &_dl_runtime_resolve;
Packit Service 82fcde
#endif
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 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__ ("\n\
Packit Service 82fcde
.text\n\
Packit Service 82fcde
.align 4\n\
Packit Service 82fcde
.globl _start\n\
Packit Service 82fcde
.globl _dl_start_user\n\
Packit Service 82fcde
_start:\n\
Packit Service 82fcde
	lgr   %r2,%r15\n\
Packit Service 82fcde
	# Alloc stack frame\n\
Packit Service 82fcde
	aghi  %r15,-160\n\
Packit Service 82fcde
	# Set the back chain to zero\n\
Packit Service 82fcde
	xc    0(8,%r15),0(%r15)\n\
Packit Service 82fcde
	# Call _dl_start with %r2 pointing to arg on stack\n\
Packit Service 82fcde
	brasl %r14,_dl_start	     # call _dl_start\n\
Packit Service 82fcde
_dl_start_user:\n\
Packit Service 82fcde
	# Save the user entry point address in %r8.\n\
Packit Service 82fcde
	lgr   %r8,%r2\n\
Packit Service 82fcde
	# Point %r12 at the GOT.\n\
Packit Service 82fcde
	larl  %r12,_GLOBAL_OFFSET_TABLE_\n\
Packit Service 82fcde
	# See if we were run as a command with the executable file\n\
Packit Service 82fcde
	# name as an extra leading argument.\n\
Packit Service 82fcde
	lghi  %r1,_dl_skip_args@GOT\n\
Packit Service 82fcde
	lg    %r1,0(%r1,%r12)\n\
Packit Service 82fcde
	lgf   %r1,0(%r1)	  # load _dl_skip_args\n\
Packit Service 82fcde
	# Get the original argument count.\n\
Packit Service 82fcde
	lg    %r0,160(%r15)\n\
Packit Service 82fcde
	# Subtract _dl_skip_args from it.\n\
Packit Service 82fcde
	sgr   %r0,%r1\n\
Packit Service 82fcde
	# Adjust the stack pointer to skip _dl_skip_args words.\n\
Packit Service 82fcde
	sllg  %r1,%r1,3\n\
Packit Service 82fcde
	agr   %r15,%r1\n\
Packit Service 82fcde
	# Set the back chain to zero again\n\
Packit Service 82fcde
	xc    0(8,%r15),0(%r15)\n\
Packit Service 82fcde
	# Store back the modified argument count.\n\
Packit Service 82fcde
	stg   %r0,160(%r15)\n\
Packit Service 82fcde
	# The special initializer gets called with the stack just\n\
Packit Service 82fcde
	# as the application's entry point will see it; it can\n\
Packit Service 82fcde
	# switch stacks if it moves these contents over.\n\
Packit Service 82fcde
" RTLD_START_SPECIAL_INIT "\n\
Packit Service 82fcde
	# Call the function to run the initializers.\n\
Packit Service 82fcde
	# Load the parameters:\n\
Packit Service 82fcde
	# (%r2, %r3, %r4, %r5) = (_dl_loaded, argc, argv, envp)\n\
Packit Service 82fcde
	lghi  %r2,_rtld_local@GOT\n\
Packit Service 82fcde
	lg    %r2,0(%r2,%r12)\n\
Packit Service 82fcde
	lg    %r2,0(%r2)\n\
Packit Service 82fcde
	lg    %r3,160(%r15)\n\
Packit Service 82fcde
	la    %r4,168(%r15)\n\
Packit Service 82fcde
	lgr   %r5,%r3\n\
Packit Service 82fcde
	sllg  %r5,%r5,3\n\
Packit Service 82fcde
	la    %r5,176(%r5,%r15)\n\
Packit Service 82fcde
	brasl %r14,_dl_init@PLT\n\
Packit Service 82fcde
	# Pass our finalizer function to the user in %r14, as per ELF ABI.\n\
Packit Service 82fcde
	lghi  %r14,_dl_fini@GOT\n\
Packit Service 82fcde
	lg    %r14,0(%r14,%r12)\n\
Packit Service 82fcde
	# Free stack frame\n\
Packit Service 82fcde
	aghi  %r15,160\n\
Packit Service 82fcde
	# Jump to the user's entry point (saved in %r8).\n\
Packit Service 82fcde
	br    %r8\n\
Packit Service 82fcde
");
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 or
Packit Service 82fcde
   TLS variable, so undefined references should not be allowed to
Packit Service 82fcde
   define the value.
Packit Service 82fcde
   ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
Packit Service 82fcde
   of the main executable's symbols, as for a COPY reloc.  */
Packit Service 82fcde
#define elf_machine_type_class(type) \
Packit Service 82fcde
  ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD		      \
Packit Service 82fcde
     || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF)	      \
Packit Service 82fcde
    * ELF_RTYPE_CLASS_PLT)						      \
Packit Service 82fcde
   | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
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_390_JMP_SLOT
Packit Service 82fcde
Packit Service 82fcde
/* The 64 bit S/390 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
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 *reloc_addr, Elf64_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 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;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Names of the architecture-specific auditing callback functions.  */
Packit Service 82fcde
#define ARCH_LA_PLTENTER s390_64_gnu_pltenter
Packit Service 82fcde
#define ARCH_LA_PLTEXIT s390_64_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
Packit Service 82fcde
auto inline void
Packit Service 82fcde
__attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
Packit Service 82fcde
		  const Elf64_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
  Elf64_Addr *const reloc_addr = reloc_addr_arg;
Packit Service 82fcde
  const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
Packit Service 82fcde
Packit Service 82fcde
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
Packit Service 82fcde
  if (__glibc_unlikely (r_type == R_390_RELATIVE))
Packit Service 82fcde
    {
Packit Service 82fcde
# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
Packit Service 82fcde
      /* This is defined in rtld.c, but nowhere in the static libc.a;
Packit Service 82fcde
	 make the reference weak so static programs can still link.
Packit Service 82fcde
	 This declaration cannot be done when compiling rtld.c
Packit Service 82fcde
	 (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
Packit Service 82fcde
	 common defn for _dl_rtld_map, which is incompatible with a
Packit Service 82fcde
	 weak decl in the same 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
# endif
Packit Service 82fcde
	*reloc_addr = map->l_addr + reloc->r_addend;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
#endif
Packit Service 82fcde
  if (__glibc_unlikely (r_type == R_390_NONE))
Packit Service 82fcde
    return;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
Packit Service 82fcde
      /* Only needed for R_390_COPY below.  */
Packit Service 82fcde
      const Elf64_Sym *const refsym = sym;
Packit Service 82fcde
#endif
Packit Service 82fcde
      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Packit Service 82fcde
      Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
Packit Service 82fcde
Packit Service 82fcde
      if (sym != NULL
Packit Service 82fcde
	  && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
Packit Service 82fcde
			       0)
Packit Service 82fcde
	  && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
Packit Service 82fcde
	  && __builtin_expect (!skip_ifunc, 1))
Packit Service 82fcde
	value = elf_ifunc_invoke (value);
Packit Service 82fcde
Packit Service 82fcde
      switch (r_type)
Packit Service 82fcde
	{
Packit Service 82fcde
	case R_390_IRELATIVE:
Packit Service 82fcde
	  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
	  break;
Packit Service 82fcde
	case R_390_GLOB_DAT:
Packit Service 82fcde
	case R_390_JMP_SLOT:
Packit Service 82fcde
	  *reloc_addr = value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
#ifndef RESOLVE_CONFLICT_FIND_MAP
Packit Service 82fcde
	case R_390_TLS_DTPMOD:
Packit Service 82fcde
# ifdef RTLD_BOOTSTRAP
Packit Service 82fcde
	  /* During startup the dynamic linker is always the module
Packit Service 82fcde
	     with index 1.
Packit Service 82fcde
	     XXX If this relocation is necessary move before RESOLVE
Packit Service 82fcde
	     call.  */
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
	  break;
Packit Service 82fcde
	case R_390_TLS_DTPOFF:
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
	  if (sym != NULL)
Packit Service 82fcde
	    *reloc_addr = sym->st_value + reloc->r_addend;
Packit Service 82fcde
# endif
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_TLS_TPOFF:
Packit Service 82fcde
	  /* The offset is negative, forward from the thread pointer.  */
Packit Service 82fcde
# ifdef RTLD_BOOTSTRAP
Packit Service 82fcde
	  *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
Packit Service 82fcde
# else
Packit Service 82fcde
	  /* We know the offset of the object the symbol is contained in.
Packit Service 82fcde
	     It is a negative value which will be added to the
Packit Service 82fcde
	     thread pointer.  */
Packit Service 82fcde
	  if (sym != NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      CHECK_STATIC_TLS (map, sym_map);
Packit Service 82fcde
	      *reloc_addr = (sym->st_value + reloc->r_addend
Packit Service 82fcde
			     - sym_map->l_tls_offset);
Packit Service 82fcde
	    }
Packit Service 82fcde
#endif
Packit Service 82fcde
	  break;
Packit Service 82fcde
#endif  /* use TLS */
Packit Service 82fcde
Packit Service 82fcde
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
# ifndef RESOLVE_CONFLICT_FIND_MAP
Packit Service 82fcde
	/* Not needed for dl-conflict.c.  */
Packit Service 82fcde
	case R_390_COPY:
Packit Service 82fcde
	  if (sym == NULL)
Packit Service 82fcde
	    /* This can happen in trace mode if an object could not be
Packit Service 82fcde
	       found.  */
Packit Service 82fcde
	    break;
Packit Service 82fcde
	  if (__builtin_expect (sym->st_size > refsym->st_size, 0)
Packit Service 82fcde
	      || (__builtin_expect (sym->st_size < refsym->st_size, 0)
Packit Service 82fcde
		  && __builtin_expect (GLRO(dl_verbose), 0)))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      const char *strtab;
Packit Service 82fcde
Packit Service 82fcde
	      strtab = (const char *) 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
		  MIN (sym->st_size, refsym->st_size));
Packit Service 82fcde
	  break;
Packit Service 82fcde
# endif
Packit Service 82fcde
	case R_390_64:
Packit Service 82fcde
	  *reloc_addr = value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_32:
Packit Service 82fcde
	  *(unsigned int *) reloc_addr = value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_16:
Packit Service 82fcde
	  *(unsigned short *) reloc_addr = value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_8:
Packit Service 82fcde
	  *(char *) reloc_addr = value + reloc->r_addend;
Packit Service 82fcde
	  break;
Packit Service 82fcde
# ifndef RESOLVE_CONFLICT_FIND_MAP
Packit Service 82fcde
	case R_390_PC64:
Packit Service 82fcde
	  *reloc_addr = value +reloc->r_addend - (Elf64_Addr) reloc_addr;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_PC32DBL:
Packit Service 82fcde
	  *(unsigned int *) reloc_addr = (unsigned int)
Packit Service 82fcde
	    ((int) (value + reloc->r_addend - (Elf64_Addr) reloc_addr) >> 1);
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_PC32:
Packit Service 82fcde
	  *(unsigned int *) reloc_addr =
Packit Service 82fcde
	    value + reloc->r_addend - (Elf64_Addr) reloc_addr;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_PC16DBL:
Packit Service 82fcde
	  *(unsigned short *) reloc_addr = (unsigned short)
Packit Service 82fcde
	    ((short) (value + reloc->r_addend - (Elf64_Addr) reloc_addr) >> 1);
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_PC16:
Packit Service 82fcde
	  *(unsigned short *) reloc_addr =
Packit Service 82fcde
	    value + reloc->r_addend - (Elf64_Addr) reloc_addr;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case R_390_NONE:
Packit Service 82fcde
	  break;
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
#if !defined(RTLD_BOOTSTRAP) || defined(_NDEBUG)
Packit Service 82fcde
	default:
Packit Service 82fcde
	  /* We add these checks in the version to relocate ld.so only
Packit Service 82fcde
	     if we are still debugging.	 */
Packit Service 82fcde
	  _dl_reloc_bad_type (map, r_type, 0);
Packit Service 82fcde
	  break;
Packit Service 82fcde
#endif
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
}
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
  Elf64_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
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
  const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
Packit Service 82fcde
  /* Check for unexpected PLT reloc type.  */
Packit Service 82fcde
  if (__glibc_likely (r_type == R_390_JMP_SLOT))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (__builtin_expect (map->l_mach.plt, 0) == 0)
Packit Service 82fcde
	*reloc_addr += l_addr;
Packit Service 82fcde
      else
Packit Service 82fcde
	*reloc_addr = map->l_mach.plt + (reloc - map->l_mach.jmprel) * 32;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (__glibc_likely (r_type == R_390_IRELATIVE))
Packit Service 82fcde
    {
Packit Service 82fcde
      Elf64_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 /* RESOLVE_MAP */