Blame sysdeps/powerpc/powerpc32/dl-machine.h

Packit 6c4009
/* Machine-dependent ELF dynamic relocation inline functions.  PowerPC version.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
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
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the 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 "powerpc"
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <dl-tls.h>
Packit 6c4009
#include <dl-irel.h>
Packit 6c4009
#include <hwcapinfo.h>
Packit 6c4009
Packit 6c4009
/* Translate a processor specific dynamic tag to the index
Packit 6c4009
   in l_info array.  */
Packit 6c4009
#define DT_PPC(x) (DT_PPC_##x - DT_LOPROC + DT_NUM)
Packit 6c4009
Packit 6c4009
/* Return nonzero iff ELF header is compatible with the running host.  */
Packit 6c4009
static inline int
Packit 6c4009
elf_machine_matches_host (const Elf32_Ehdr *ehdr)
Packit 6c4009
{
Packit 6c4009
  return ehdr->e_machine == EM_PPC;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Return the value of the GOT pointer.  */
Packit 6c4009
static inline Elf32_Addr * __attribute__ ((const))
Packit 6c4009
ppc_got (void)
Packit 6c4009
{
Packit 6c4009
  Elf32_Addr *got;
Packit 6c4009
Packit 6c4009
  asm ("bcl 20,31,1f\n"
Packit 6c4009
       "1:	mflr %0\n"
Packit 6c4009
       "	addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n"
Packit 6c4009
       "	addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n"
Packit 6c4009
       : "=b" (got) : : "lr");
Packit 6c4009
Packit 6c4009
  return got;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Return the link-time address of _DYNAMIC, stored as
Packit 6c4009
   the first value in the GOT. */
Packit 6c4009
static inline Elf32_Addr __attribute__ ((const))
Packit 6c4009
elf_machine_dynamic (void)
Packit 6c4009
{
Packit 6c4009
  return *ppc_got ();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Return the run-time load address of the shared object.  */
Packit 6c4009
static inline Elf32_Addr __attribute__ ((const))
Packit 6c4009
elf_machine_load_address (void)
Packit 6c4009
{
Packit 6c4009
  Elf32_Addr *branchaddr;
Packit 6c4009
  Elf32_Addr runtime_dynamic;
Packit 6c4009
Packit 6c4009
  /* This is much harder than you'd expect.  Possibly I'm missing something.
Packit 6c4009
     The 'obvious' way:
Packit 6c4009
Packit 6c4009
       Apparently, "bcl 20,31,$+4" is what should be used to load LR
Packit 6c4009
       with the address of the next instruction.
Packit 6c4009
       I think this is so that machines that do bl/blr pairing don't
Packit 6c4009
       get confused.
Packit 6c4009
Packit 6c4009
     asm ("bcl 20,31,0f ;"
Packit 6c4009
	  "0: mflr 0 ;"
Packit 6c4009
	  "lis %0,0b@ha;"
Packit 6c4009
	  "addi %0,%0,0b@l;"
Packit 6c4009
	  "subf %0,%0,0"
Packit 6c4009
	  : "=b" (addr) : : "r0", "lr");
Packit 6c4009
Packit 6c4009
     doesn't work, because the linker doesn't have to (and in fact doesn't)
Packit 6c4009
     update the @ha and @l references; the loader (which runs after this
Packit 6c4009
     code) will do that.
Packit 6c4009
Packit 6c4009
     Instead, we use the following trick:
Packit 6c4009
Packit 6c4009
     The linker puts the _link-time_ address of _DYNAMIC at the first
Packit 6c4009
     word in the GOT. We could branch to that address, if we wanted,
Packit 6c4009
     by using an @local reloc; the linker works this out, so it's safe
Packit 6c4009
     to use now. We can't, of course, actually branch there, because
Packit 6c4009
     we'd cause an illegal instruction exception; so we need to compute
Packit 6c4009
     the address ourselves. That gives us the following code: */
Packit 6c4009
Packit 6c4009
  /* Get address of the 'b _DYNAMIC@local'...  */
Packit 6c4009
  asm ("bcl 20,31,0f;"
Packit 6c4009
       "b _DYNAMIC@local;"
Packit 6c4009
       "0:"
Packit 6c4009
       : "=l" (branchaddr));
Packit 6c4009
Packit 6c4009
  /* So now work out the difference between where the branch actually points,
Packit 6c4009
     and the offset of that location in memory from the start of the file.  */
Packit 6c4009
  runtime_dynamic = ((Elf32_Addr) branchaddr
Packit 6c4009
		     + ((Elf32_Sword) (*branchaddr << 6 & 0xffffff00) >> 6));
Packit 6c4009
Packit 6c4009
  return runtime_dynamic - elf_machine_dynamic ();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
Packit 6c4009
Packit 6c4009
/* The PLT uses Elf32_Rela relocs.  */
Packit 6c4009
#define elf_machine_relplt elf_machine_rela
Packit 6c4009
Packit 6c4009
/* Mask identifying addresses reserved for the user program,
Packit 6c4009
   where the dynamic linker should not map anything.  */
Packit 6c4009
#define ELF_MACHINE_USER_ADDRESS_MASK	0xf0000000UL
Packit 6c4009
Packit 6c4009
/* The actual _start code is in dl-start.S.  Use a really
Packit 6c4009
   ugly bit of assembler to let dl-start.o see _dl_start.  */
Packit 6c4009
#define RTLD_START asm (".globl _dl_start");
Packit 6c4009
Packit 6c4009
/* Decide where a relocatable object should be loaded.  */
Packit 6c4009
extern ElfW(Addr)
Packit 6c4009
__elf_preferred_address(struct link_map *loader, size_t maplength,
Packit 6c4009
			ElfW(Addr) mapstartpref);
Packit 6c4009
#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \
Packit 6c4009
  __elf_preferred_address (loader, maplength, mapstartpref)
Packit 6c4009
Packit 6c4009
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
Packit 6c4009
   PLT entries should not be allowed to define the value.
Packit 6c4009
   ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
Packit 6c4009
   of the main executable's symbols, as for a COPY reloc.  */
Packit 6c4009
/* We never want to use a PLT entry as the destination of a
Packit 6c4009
   reloc, when what is being relocated is a branch. This is
Packit 6c4009
   partly for efficiency, but mostly so we avoid loops.  */
Packit 6c4009
#define elf_machine_type_class(type)			\
Packit 6c4009
  ((((type) == R_PPC_JMP_SLOT				\
Packit 6c4009
    || (type) == R_PPC_REL24				\
Packit 6c4009
    || ((type) >= R_PPC_DTPMOD32 /* contiguous TLS */	\
Packit 6c4009
	&& (type) <= R_PPC_DTPREL32)			\
Packit 6c4009
    || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
Packit 6c4009
   | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
Packit 6c4009
Packit 6c4009
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
Packit 6c4009
#define ELF_MACHINE_JMP_SLOT	R_PPC_JMP_SLOT
Packit 6c4009
Packit 6c4009
/* The PowerPC never uses REL relocations.  */
Packit 6c4009
#define ELF_MACHINE_NO_REL 1
Packit 6c4009
#define ELF_MACHINE_NO_RELA 0
Packit 6c4009
Packit 6c4009
/* We define an initialization function to initialize HWCAP/HWCAP2 and
Packit 6c4009
   platform data so it can be copied into the TCB later.  This is called
Packit 6c4009
   very early in _dl_sysdep_start for dynamically linked binaries.  */
Packit 6c4009
#ifdef SHARED
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
  __tcb_parse_hwcap_and_convert_at_platform ();
Packit 6c4009
}
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Set up the loaded object described by MAP so its unrelocated PLT
Packit 6c4009
   entries will jump to the on-demand fixup code in dl-runtime.c.
Packit 6c4009
   Also install a small trampoline to be used by entries that have
Packit 6c4009
   been relocated to an address too far away for a single branch.  */
Packit 6c4009
extern int __elf_machine_runtime_setup (struct link_map *map,
Packit 6c4009
					int lazy, int profile);
Packit 6c4009
Packit 6c4009
static inline int
Packit 6c4009
elf_machine_runtime_setup (struct link_map *map,
Packit 6c4009
			   int lazy, int profile)
Packit 6c4009
{
Packit 6c4009
  if (map->l_info[DT_JMPREL] == 0)
Packit 6c4009
    return lazy;
Packit 6c4009
Packit 6c4009
  if (map->l_info[DT_PPC(GOT)] == 0)
Packit 6c4009
    /* Handle old style PLT.  */
Packit 6c4009
    return __elf_machine_runtime_setup (map, lazy, profile);
Packit 6c4009
Packit 6c4009
  /* New style non-exec PLT consisting of an array of addresses.  */
Packit 6c4009
  map->l_info[DT_PPC(GOT)]->d_un.d_ptr += map->l_addr;
Packit 6c4009
  if (lazy)
Packit 6c4009
    {
Packit 6c4009
      Elf32_Addr *plt, *got, glink;
Packit 6c4009
      Elf32_Word num_plt_entries;
Packit 6c4009
      void (*dlrr) (void);
Packit 6c4009
      extern void _dl_runtime_resolve (void);
Packit 6c4009
      extern void _dl_prof_resolve (void);
Packit 6c4009
Packit 6c4009
      if (__glibc_likely (!profile))
Packit 6c4009
	dlrr = _dl_runtime_resolve;
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  if (GLRO(dl_profile) != NULL
Packit 6c4009
	      &&_dl_name_match_p (GLRO(dl_profile), map))
Packit 6c4009
	    GL(dl_profile_map) = map;
Packit 6c4009
	  dlrr = _dl_prof_resolve;
Packit 6c4009
	}
Packit 6c4009
      got = (Elf32_Addr *) map->l_info[DT_PPC(GOT)]->d_un.d_ptr;
Packit 6c4009
      glink = got[1];
Packit 6c4009
      got[1] = (Elf32_Addr) dlrr;
Packit 6c4009
      got[2] = (Elf32_Addr) map;
Packit 6c4009
Packit 6c4009
      /* Relocate everything in .plt by the load address offset.  */
Packit 6c4009
      plt = (Elf32_Addr *) D_PTR (map, l_info[DT_PLTGOT]);
Packit 6c4009
      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
Packit 6c4009
			 / sizeof (Elf32_Rela));
Packit 6c4009
Packit 6c4009
      /* If a library is prelinked but we have to relocate anyway,
Packit 6c4009
	 we have to be able to undo the prelinking of .plt section.
Packit 6c4009
	 The prelinker saved us at got[1] address of .glink
Packit 6c4009
	 section's start.  */
Packit 6c4009
      if (glink)
Packit 6c4009
	{
Packit 6c4009
	  glink += map->l_addr;
Packit 6c4009
	  while (num_plt_entries-- != 0)
Packit 6c4009
	    *plt++ = glink, glink += 4;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	while (num_plt_entries-- != 0)
Packit 6c4009
	  *plt++ += map->l_addr;
Packit 6c4009
    }
Packit 6c4009
  return lazy;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Change the PLT entry whose reloc is 'reloc' to call the actual routine.  */
Packit 6c4009
extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map,
Packit 6c4009
					   Elf32_Addr *reloc_addr,
Packit 6c4009
					   Elf32_Addr finaladdr);
Packit 6c4009
Packit 6c4009
static inline Elf32_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 Elf32_Rela *reloc,
Packit 6c4009
		       Elf32_Addr *reloc_addr, Elf64_Addr finaladdr)
Packit 6c4009
{
Packit 6c4009
  if (map->l_info[DT_PPC(GOT)] == 0)
Packit 6c4009
    /* Handle old style PLT.  */
Packit 6c4009
    return __elf_machine_fixup_plt (map, reloc_addr, finaladdr);
Packit 6c4009
Packit 6c4009
  *reloc_addr = finaladdr;
Packit 6c4009
  return finaladdr;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Return the final value of a plt relocation.  */
Packit 6c4009
static inline Elf32_Addr
Packit 6c4009
elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
Packit 6c4009
		       Elf32_Addr value)
Packit 6c4009
{
Packit 6c4009
  return value + reloc->r_addend;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Names of the architecture-specific auditing callback functions.  */
Packit 6c4009
#define ARCH_LA_PLTENTER ppc32_gnu_pltenter
Packit 6c4009
#define ARCH_LA_PLTEXIT ppc32_gnu_pltexit
Packit 6c4009
Packit 6c4009
#endif /* dl_machine_h */
Packit 6c4009
Packit 6c4009
#ifdef RESOLVE_MAP
Packit 6c4009
Packit 6c4009
/* Do the actual processing of a reloc, once its target address
Packit 6c4009
   has been determined.  */
Packit 6c4009
extern void __process_machine_rela (struct link_map *map,
Packit 6c4009
				    const Elf32_Rela *reloc,
Packit 6c4009
				    struct link_map *sym_map,
Packit 6c4009
				    const Elf32_Sym *sym,
Packit 6c4009
				    const Elf32_Sym *refsym,
Packit 6c4009
				    Elf32_Addr *const reloc_addr,
Packit 6c4009
				    Elf32_Addr finaladdr,
Packit 6c4009
				    int rinfo) attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Call _dl_signal_error when a resolved value overflows a relocated area.  */
Packit 6c4009
extern void _dl_reloc_overflow (struct link_map *map,
Packit 6c4009
				const char *name,
Packit 6c4009
				Elf32_Addr *const reloc_addr,
Packit 6c4009
				const Elf32_Sym *refsym) attribute_hidden;
Packit 6c4009
Packit 6c4009
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
Packit 6c4009
   LOADADDR is the load address of the object; INFO is an array indexed
Packit 6c4009
   by DT_* of the .dynamic section info.  */
Packit 6c4009
Packit 6c4009
auto inline void __attribute__ ((always_inline))
Packit 6c4009
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
Packit 6c4009
		  const Elf32_Sym *sym, const struct r_found_version *version,
Packit 6c4009
		  void *const reloc_addr_arg, int skip_ifunc)
Packit 6c4009
{
Packit 6c4009
  Elf32_Addr *const reloc_addr = reloc_addr_arg;
Packit 6c4009
  const Elf32_Sym *const refsym = sym;
Packit 6c4009
  Elf32_Addr value;
Packit 6c4009
  const int r_type = ELF32_R_TYPE (reloc->r_info);
Packit 6c4009
  struct link_map *sym_map = NULL;
Packit 6c4009
Packit 6c4009
#ifndef RESOLVE_CONFLICT_FIND_MAP
Packit 6c4009
  if (r_type == R_PPC_RELATIVE)
Packit 6c4009
    {
Packit 6c4009
      *reloc_addr = map->l_addr + reloc->r_addend;
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (__glibc_unlikely (r_type == R_PPC_NONE))
Packit 6c4009
    return;
Packit 6c4009
Packit 6c4009
  /* binutils on ppc32 includes st_value in r_addend for relocations
Packit 6c4009
     against local symbols.  */
Packit 6c4009
  if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
Packit 6c4009
      && sym->st_shndx != SHN_UNDEF)
Packit 6c4009
    {
Packit 6c4009
      sym_map = map;
Packit 6c4009
      value = map->l_addr;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      sym_map = RESOLVE_MAP (&sym, version, r_type);
Packit 6c4009
      value = SYMBOL_ADDRESS (sym_map, sym, true);
Packit 6c4009
    }
Packit 6c4009
  value += reloc->r_addend;
Packit 6c4009
#else
Packit 6c4009
  value = reloc->r_addend;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  if (sym != NULL
Packit 6c4009
      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
Packit 6c4009
      && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
Packit 6c4009
      && __builtin_expect (!skip_ifunc, 1))
Packit 6c4009
    value = elf_ifunc_invoke (value);
Packit 6c4009
Packit 6c4009
  /* A small amount of code is duplicated here for speed.  In libc,
Packit 6c4009
     more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
Packit 6c4009
     libraries, 60% are R_PPC_RELATIVE, 24% are R_PPC_GLOB_DAT or
Packit 6c4009
     R_PPC_ADDR32, and 16% are R_PPC_JMP_SLOT (which this routine
Packit 6c4009
     wouldn't usually handle).  As an bonus, doing this here allows
Packit 6c4009
     the switch statement in __process_machine_rela to work.  */
Packit 6c4009
  switch (r_type)
Packit 6c4009
    {
Packit 6c4009
    case R_PPC_GLOB_DAT:
Packit 6c4009
    case R_PPC_ADDR32:
Packit 6c4009
      *reloc_addr = value;
Packit 6c4009
      break;
Packit 6c4009
Packit 6c4009
#ifndef RESOLVE_CONFLICT_FIND_MAP
Packit 6c4009
# ifdef RTLD_BOOTSTRAP
Packit 6c4009
#  define NOT_BOOTSTRAP 0
Packit 6c4009
# else
Packit 6c4009
#  define NOT_BOOTSTRAP 1
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
    case R_PPC_DTPMOD32:
Packit 6c4009
      if (map->l_info[DT_PPC(OPT)]
Packit 6c4009
	  && (map->l_info[DT_PPC(OPT)]->d_un.d_val & PPC_OPT_TLS))
Packit 6c4009
	{
Packit 6c4009
	  if (!NOT_BOOTSTRAP)
Packit 6c4009
	    {
Packit 6c4009
	      reloc_addr[0] = 0;
Packit 6c4009
	      reloc_addr[1] = (sym_map->l_tls_offset - TLS_TP_OFFSET
Packit 6c4009
			       + TLS_DTV_OFFSET);
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
	  else if (sym_map != NULL)
Packit 6c4009
	    {
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
# endif
Packit 6c4009
		{
Packit 6c4009
		  reloc_addr[0] = 0;
Packit 6c4009
		  /* Set up for local dynamic.  */
Packit 6c4009
		  reloc_addr[1] = (sym_map->l_tls_offset - TLS_TP_OFFSET
Packit 6c4009
				   + TLS_DTV_OFFSET);
Packit 6c4009
		  break;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      if (!NOT_BOOTSTRAP)
Packit 6c4009
	/* During startup the dynamic linker is always index 1.  */
Packit 6c4009
	*reloc_addr = 1;
Packit 6c4009
      else if (sym_map != NULL)
Packit 6c4009
	/* Get the information from the link map returned by the
Packit 6c4009
	   RESOLVE_MAP function.  */
Packit 6c4009
	*reloc_addr = sym_map->l_tls_modid;
Packit 6c4009
      break;
Packit 6c4009
    case R_PPC_DTPREL32:
Packit 6c4009
      if (map->l_info[DT_PPC(OPT)]
Packit 6c4009
	  && (map->l_info[DT_PPC(OPT)]->d_un.d_val & PPC_OPT_TLS))
Packit 6c4009
	{
Packit 6c4009
	  if (!NOT_BOOTSTRAP)
Packit 6c4009
	    {
Packit 6c4009
	      *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
	  else if (sym_map != NULL)
Packit 6c4009
	    {
Packit 6c4009
	      /* This reloc is always preceded by R_PPC_DTPMOD32.  */
Packit 6c4009
# ifndef SHARED
Packit 6c4009
	      assert (HAVE_STATIC_TLS (map, sym_map));
Packit 6c4009
# else
Packit 6c4009
	      if (HAVE_STATIC_TLS (map, sym_map))
Packit 6c4009
# endif
Packit 6c4009
		{
Packit 6c4009
		  *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
Packit 6c4009
		  break;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      /* During relocation all TLS symbols are defined and used.
Packit 6c4009
	 Therefore the offset is already correct.  */
Packit 6c4009
      if (NOT_BOOTSTRAP && sym_map != NULL)
Packit 6c4009
	*reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
Packit 6c4009
      break;
Packit 6c4009
    case R_PPC_TPREL32:
Packit 6c4009
      if (!NOT_BOOTSTRAP || sym_map != NULL)
Packit 6c4009
	{
Packit 6c4009
	  if (NOT_BOOTSTRAP)
Packit 6c4009
	    CHECK_STATIC_TLS (map, sym_map);
Packit 6c4009
	  *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
Packit 6c4009
	}
Packit 6c4009
      break;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
    case R_PPC_JMP_SLOT:
Packit 6c4009
#ifdef RESOLVE_CONFLICT_FIND_MAP
Packit 6c4009
      RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
Packit 6c4009
#endif
Packit 6c4009
      if (map->l_info[DT_PPC(GOT)] != 0)
Packit 6c4009
	{
Packit 6c4009
	  *reloc_addr = value;
Packit 6c4009
	  break;
Packit 6c4009
	}
Packit 6c4009
      /* FALLTHROUGH */
Packit 6c4009
Packit 6c4009
    default:
Packit 6c4009
      __process_machine_rela (map, reloc, sym_map, sym, refsym,
Packit 6c4009
			      reloc_addr, value, r_type);
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
auto inline void __attribute__ ((always_inline))
Packit 6c4009
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
Packit 6c4009
			   void *const reloc_addr_arg)
Packit 6c4009
{
Packit 6c4009
  Elf32_Addr *const reloc_addr = reloc_addr_arg;
Packit 6c4009
  *reloc_addr = l_addr + reloc->r_addend;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
auto inline void __attribute__ ((always_inline))
Packit 6c4009
elf_machine_lazy_rel (struct link_map *map,
Packit 6c4009
		      Elf32_Addr l_addr, const Elf32_Rela *reloc,
Packit 6c4009
		      int skip_ifunc)
Packit 6c4009
{
Packit 6c4009
  /* elf_machine_runtime_setup handles this. */
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#endif /* RESOLVE_MAP */