Blame sysdeps/microblaze/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 "microblaze"
Packit Service 82fcde
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <tls.h>
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 Elf32_Ehdr *ehdr)
Packit Service 82fcde
{
Packit Service 82fcde
  return (ehdr->e_machine == EM_MICROBLAZE);
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
static inline Elf32_Addr
Packit Service 82fcde
elf_machine_dynamic (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* This produces a GOTOFF reloc that resolves to zero at link time, so in
Packit Service 82fcde
     fact just loads from the GOT register directly.  By doing it without
Packit Service 82fcde
     an asm we can let the compiler choose any register.  */
Packit Service 82fcde
Packit Service 82fcde
  Elf32_Addr got_entry_0;
Packit Service 82fcde
  __asm__ __volatile__(
Packit Service 82fcde
    "lwi %0,r20,0"
Packit Service 82fcde
    :"=r"(got_entry_0)
Packit Service 82fcde
    );
Packit Service 82fcde
  return got_entry_0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Return the run-time load address of the shared object.  */
Packit Service 82fcde
static inline Elf32_Addr
Packit Service 82fcde
elf_machine_load_address (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Compute the difference between the runtime address of _DYNAMIC as seen
Packit Service 82fcde
     by a GOTOFF reference, and the link-time address found in the special
Packit Service 82fcde
     unrelocated first GOT entry.  */
Packit Service 82fcde
Packit Service 82fcde
  Elf32_Addr dyn;
Packit Service 82fcde
  __asm__ __volatile__ (
Packit Service 82fcde
    "addik %0,r20,_DYNAMIC@GOTOFF"
Packit Service 82fcde
    : "=r"(dyn)
Packit Service 82fcde
    );
Packit Service 82fcde
  return dyn - 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__ ((always_inline))
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 (Elf32_Word);
Packit Service 82fcde
  extern void _dl_runtime_profile (Elf32_Word);
Packit Service 82fcde
Packit Service 82fcde
  return lazy;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* The PLT uses Elf32_Rela relocs.  */
Packit Service 82fcde
#define elf_machine_relplt elf_machine_rela
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	0x80000000UL
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
	.text\n\
Packit Service 82fcde
	.globl _start\n\
Packit Service 82fcde
	.type _start,@function\n\
Packit Service 82fcde
_start:\n\
Packit Service 82fcde
	addk  r5,r0,r1\n\
Packit Service 82fcde
	addk  r3,r0,r0\n\
Packit Service 82fcde
1:\n\
Packit Service 82fcde
	addik r5,r5,4\n\
Packit Service 82fcde
	lw    r4,r5,r0\n\
Packit Service 82fcde
	bneid r4,1b\n\
Packit Service 82fcde
	addik r3,r3,1\n\
Packit Service 82fcde
	addik r3,r3,-1\n\
Packit Service 82fcde
	addk  r5,r0,r1\n\
Packit Service 82fcde
	sw    r3,r5,r0\n\
Packit Service 82fcde
	addik r1,r1,-24\n\
Packit Service 82fcde
	sw    r15,r1,r0\n\
Packit Service 82fcde
	brlid r15,_dl_start\n\
Packit Service 82fcde
	nop\n\
Packit Service 82fcde
	/* FALLTHRU.  */\n\
Packit Service 82fcde
\n\
Packit Service 82fcde
	.globl _dl_start_user\n\
Packit Service 82fcde
	.type _dl_start_user,@function\n\
Packit Service 82fcde
_dl_start_user:\n\
Packit Service 82fcde
	mfs   r20,rpc\n\
Packit Service 82fcde
	addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n\
Packit Service 82fcde
	lwi   r4,r20,_dl_skip_args@GOTOFF\n\
Packit Service 82fcde
	lwi   r5,r1,24\n\
Packit Service 82fcde
	rsubk r5,r4,r5\n\
Packit Service 82fcde
	addk  r4,r4,r4\n\
Packit Service 82fcde
	addk  r4,r4,r4\n\
Packit Service 82fcde
	addk  r1,r1,r4\n\
Packit Service 82fcde
	swi   r5,r1,24\n\
Packit Service 82fcde
	swi   r3,r1,20\n\
Packit Service 82fcde
	addk  r6,r5,r0\n\
Packit Service 82fcde
	addk  r5,r5,r5\n\
Packit Service 82fcde
	addk  r5,r5,r5\n\
Packit Service 82fcde
	addik r7,r1,28\n\
Packit Service 82fcde
	addk  r8,r7,r5\n\
Packit Service 82fcde
	addik r8,r8,4\n\
Packit Service 82fcde
	lwi   r5,r20,_rtld_local@GOTOFF\n\
Packit Service 82fcde
	brlid r15,_dl_init\n\
Packit Service 82fcde
	nop\n\
Packit Service 82fcde
	lwi   r5,r1,24\n\
Packit Service 82fcde
	lwi   r3,r1,20\n\
Packit Service 82fcde
	addk  r4,r5,r5\n\
Packit Service 82fcde
	addk  r4,r4,r4\n\
Packit Service 82fcde
	addik r6,r1,28\n\
Packit Service 82fcde
	addk  r7,r6,r4\n\
Packit Service 82fcde
	addik r7,r7,4\n\
Packit Service 82fcde
	addik r15,r20,_dl_fini@GOTOFF\n\
Packit Service 82fcde
	addik r15,r15,-8\n\
Packit Service 82fcde
	brad  r3\n\
Packit Service 82fcde
	addik r1,r1,24\n\
Packit Service 82fcde
	nop\n\
Packit Service 82fcde
	.size _dl_start_user, . - _dl_start_user\n\
Packit Service 82fcde
	.previous");
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
#ifndef RTLD_BOOTSTRAP
Packit Service 82fcde
# define elf_machine_type_class(type) \
Packit Service 82fcde
  (((type) == R_MICROBLAZE_JUMP_SLOT || \
Packit Service 82fcde
    (type) == R_MICROBLAZE_TLSDTPREL32 || \
Packit Service 82fcde
    (type) == R_MICROBLAZE_TLSDTPMOD32 || \
Packit Service 82fcde
    (type) == R_MICROBLAZE_TLSTPREL32) \
Packit Service 82fcde
    * ELF_RTYPE_CLASS_PLT \
Packit Service 82fcde
   | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
Packit Service 82fcde
#else
Packit Service 82fcde
# define elf_machine_type_class(type) \
Packit Service 82fcde
  (((type) == R_MICROBLAZE_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT \
Packit Service 82fcde
   | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
Packit Service 82fcde
#endif
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_MICROBLAZE_JUMP_SLOT
Packit Service 82fcde
Packit Service 82fcde
/* The microblaze never uses Elf32_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
static inline Elf32_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 Elf32_Rela *reloc,
Packit Service 82fcde
		       Elf32_Addr *reloc_addr, Elf32_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. Ignore the addend.  */
Packit Service 82fcde
static inline Elf32_Addr
Packit Service 82fcde
elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
Packit Service 82fcde
		       Elf32_Addr value)
Packit Service 82fcde
{
Packit Service 82fcde
  return value;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif /* !dl_machine_h.  */
Packit Service 82fcde
Packit Service 82fcde
/* Names of the architecture-specific auditing callback functions.  */
Packit Service 82fcde
#define ARCH_LA_PLTENTER microblaze_gnu_pltenter
Packit Service 82fcde
#define ARCH_LA_PLTEXIT microblaze_gnu_pltexit
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
/* Macro to put 32-bit relocation value into 2 words.  */
Packit Service 82fcde
#define PUT_REL_64(rel_addr,val) \
Packit Service 82fcde
  do { \
Packit Service 82fcde
    ((unsigned short *)(rel_addr))[1] = (val) >> 16; \
Packit Service 82fcde
    ((unsigned short *)(rel_addr))[3] = (val) & 0xffff; \
Packit Service 82fcde
  } while (0)
Packit Service 82fcde
Packit Service 82fcde
auto inline void __attribute__ ((always_inline))
Packit Service 82fcde
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
Packit Service 82fcde
		  const Elf32_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
  Elf32_Addr *const reloc_addr = reloc_addr_arg;
Packit Service 82fcde
  const int r_type = ELF32_R_TYPE (reloc->r_info);
Packit Service 82fcde
Packit Service 82fcde
  if (__builtin_expect (r_type == R_MICROBLAZE_64_PCREL, 0))
Packit Service 82fcde
    PUT_REL_64 (reloc_addr, map->l_addr + reloc->r_addend);
Packit Service 82fcde
  else if (r_type == R_MICROBLAZE_REL)
Packit Service 82fcde
    *reloc_addr = map->l_addr + reloc->r_addend;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      const Elf32_Sym *const refsym = sym;
Packit Service 82fcde
      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
Packit Service 82fcde
      Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
Packit Service 82fcde
Packit Service 82fcde
      value += reloc->r_addend;
Packit Service 82fcde
      if (r_type == R_MICROBLAZE_GLOB_DAT ||
Packit Service 82fcde
          r_type == R_MICROBLAZE_JUMP_SLOT ||
Packit Service 82fcde
          r_type == R_MICROBLAZE_32)
Packit Service 82fcde
	{
Packit Service 82fcde
	  *reloc_addr = value;
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (r_type == R_MICROBLAZE_COPY)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (sym != NULL && (sym->st_size > refsym->st_size
Packit Service 82fcde
	      || (sym->st_size < refsym->st_size && GLRO (dl_verbose))) )
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
		  MIN (sym->st_size, refsym->st_size));
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (r_type == R_MICROBLAZE_NONE)
Packit Service 82fcde
	{
Packit Service 82fcde
	}
Packit Service 82fcde
#if !defined RTLD_BOOTSTRAP
Packit Service 82fcde
      else if (r_type == R_MICROBLAZE_TLSDTPMOD32)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (sym_map != NULL)
Packit Service 82fcde
	    *reloc_addr = sym_map->l_tls_modid;
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (r_type == R_MICROBLAZE_TLSDTPREL32)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (sym != NULL)
Packit Service 82fcde
	    *reloc_addr = sym->st_value + reloc->r_addend;
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (r_type == R_MICROBLAZE_TLSTPREL32)
Packit Service 82fcde
	{
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 + sym_map->l_tls_offset + reloc->r_addend;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
#endif
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  _dl_reloc_bad_type (map, r_type, 0);
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
auto inline void
Packit Service 82fcde
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
Packit Service 82fcde
			   void *const reloc_addr_arg)
Packit Service 82fcde
{
Packit Service 82fcde
  Elf32_Addr *const reloc_addr = reloc_addr_arg;
Packit Service 82fcde
  PUT_REL_64 (reloc_addr, l_addr + reloc->r_addend);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
auto inline void
Packit Service 82fcde
elf_machine_lazy_rel (struct link_map *map,
Packit Service 82fcde
		      Elf32_Addr l_addr, const Elf32_Rela *reloc,
Packit Service 82fcde
		      int skip_ifunc)
Packit Service 82fcde
{
Packit Service 82fcde
  Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
Packit Service 82fcde
  if (ELF32_R_TYPE (reloc->r_info) == R_MICROBLAZE_JUMP_SLOT)
Packit Service 82fcde
    *reloc_addr += l_addr;
Packit Service 82fcde
  else
Packit Service 82fcde
    _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif /* RESOLVE_MAP.  */