From 7d137fcf818e9a157a9f7ed9df61896f6cf97490 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Mon, 14 Mar 2005 13:25:07 +0000 Subject: Generalize optimized relative reloc procesing. Add elf_machine_dynamic() and elf_machine_load_address() for all archs. elf_machine_dynamic() replaces the #ifdef mess to get at the GOT. elf_machine_load_address() is needed to execute ldso directly, this is not complete yet. I probably broke one or two archs(only tested PPC) so please try and report problems. For a report to be useful you need to enable __SUPPORT_LD_DEBUG_EARLY__ and __SUPPORT_LD_DEBUG__ --- ldso/ldso/sh/dl-sysdep.h | 78 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) (limited to 'ldso/ldso/sh') diff --git a/ldso/ldso/sh/dl-sysdep.h b/ldso/ldso/sh/dl-sysdep.h index 134e901c7..b332cc1ac 100644 --- a/ldso/ldso/sh/dl-sysdep.h +++ b/ldso/ldso/sh/dl-sysdep.h @@ -5,7 +5,7 @@ /* Define this if the system uses RELOCA. */ #define ELF_USES_RELOCA - +#include /* * Initialization sequence for a GOT. */ @@ -96,3 +96,79 @@ _dl_urem(unsigned int n, unsigned int base) #define elf_machine_type_class(type) \ ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static inline Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + register Elf32_Addr *got; + asm ("mov r12,%0" :"=r" (got)); + return *got; +} + +/* Return the run-time load address of the shared object. */ +static inline Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + Elf32_Addr addr; + asm ("mov.l 1f,r0\n\ + mov.l 3f,r2\n\ + add r12,r2\n\ + mov.l @(r0,r12),r0\n\ + bra 2f\n\ + sub r0,r2\n\ + .align 2\n\ + 1: .long _dl_boot@GOT\n\ + 3: .long _dl_boot@GOTOFF\n\ + 2: mov r2,%0" + : "=r" (addr) : : "r0", "r1", "r2"); + return addr; +} + +#define COPY_UNALIGNED_WORD(swp, twp, align) \ + { \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + switch ((align)) \ + { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ + } + +static inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Addr value; + Elf32_Rela * rpnt = (void *) (rel_addr + load_off); + + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + rpnt->r_offset); + + if (rpnt->r_addend) + value = load_off + rpnt->r_addend; + else { + COPY_UNALIGNED_WORD (reloc_addr, &value, (int) reloc_addr & 3); + value += load_off; + } + COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3); + rpnt++; + } while (--relative_count); +#undef COPY_UNALIGNED_WORD +} -- cgit v1.2.3