/* elf reloc code for the or1k platform, based on glibc 2.3.6, dl-machine.h */
/*
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, see . */
/* Use reloca */
#define ELF_USES_RELOCA
#include
/* Initialise the GOT */
#define INIT_GOT(GOT_BASE,MODULE) \
do { \
GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
GOT_BASE[1] = (unsigned long) MODULE; \
} while(0)
/* Here we define the magic numbers that this dynamic loader should accept */
#define MAGIC1 EM_OR1K
#undef MAGIC2
/* Used for error messages */
#define ELF_TARGET "or1k"
#define elf_machine_type_class(type) \
(((type) == R_OR1K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT \
| ((type) == R_OR1K_COPY) * ELF_RTYPE_CLASS_COPY)
static inline Elf32_Addr *
or1k_get_got (void)
{
Elf32_Addr *got;
Elf32_Addr linkreg;
__asm__("l.ori %0, r9, 0\n"
"l.jal .LPC1\n"
#ifndef __OR1K_NODELAY__
"l.nop\n"
#endif
".LPC1:\n"
"l.movhi %1, gotpchi(_GLOBAL_OFFSET_TABLE_+(.-.LPC1))\n"
"l.ori %1, %1, gotpclo(_GLOBAL_OFFSET_TABLE_+(.-.LPC1))\n"
"l.add %1, %1, r9\n"
"l.ori r9, %0, 0\n"
: "=r" (linkreg), "=r" (got));
return got;
}
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
first element of the GOT. */
static inline Elf32_Addr
elf_machine_dynamic (void)
{
Elf32_Addr *got = or1k_get_got();
return *got;
}
/* Return the run-time load address of the shared object. */
static inline Elf32_Addr
elf_machine_load_address (void)
{
/* Compute the difference between the runtime address of _DYNAMIC as seen
by a GOTOFF reference, and the link-time address found in the special
unrelocated first GOT entry. */
Elf32_Addr dyn;
Elf32_Addr *got = or1k_get_got();
__asm__ __volatile__ (
"l.movhi %0, gotoffhi(_DYNAMIC);"
"l.ori %0, %0, gotofflo(_DYNAMIC);"
"l.add %0, %0, %1;"
: "=r"(dyn), "=r"(got)
);
return dyn - *got;
}
static __always_inline void
elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
Elf32_Word relative_count)
{
Elf32_Rela * rpnt = (void *) rel_addr;
--rpnt;
do {
Elf32_Addr *const reloc_addr = (void *) (load_off +
(++rpnt)->r_offset);
*reloc_addr += load_off;
} while (--relative_count);
}