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/sparc/dl-sysdep.h | 60 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) (limited to 'ldso/ldso/sparc') diff --git a/ldso/ldso/sparc/dl-sysdep.h b/ldso/ldso/sparc/dl-sysdep.h index d48120e2d..7559a80d2 100644 --- a/ldso/ldso/sparc/dl-sysdep.h +++ b/ldso/ldso/sparc/dl-sysdep.h @@ -7,7 +7,7 @@ /* Define this if the system uses RELOCA. */ #define ELF_USES_RELOCA - +#include /* * Initialization sequence for a GOT. For the Sparc, this points to the * PLT, and we need to initialize a couple of the slots. The PLT should @@ -110,3 +110,61 @@ sparc_mod(unsigned long m, unsigned long p) /* The SPARC overlaps DT_RELA and DT_PLTREL. */ #define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* We have to do this because elf_machine_{dynamic,load_address} can be + invoked from functions that have no GOT references, and thus the compiler + has no obligation to load the PIC register. */ +#define LOAD_PIC_REG(PIC_REG) \ +do { register Elf32_Addr pc __asm("o7"); \ + __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "call 1f\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \ + "1:\tadd %1, %0, %1" \ + : "=r" (pc), "=r" (PIC_REG)); \ +} while (0) + +/* 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 +elf_machine_dynamic (void) +{ + register Elf32_Addr *got asm ("%l7"); + + LOAD_PIC_REG (got); + + return *got; +} + +/* Return the run-time load address of the shared object. */ +static inline Elf32_Addr +elf_machine_load_address (void) +{ + register Elf32_Addr *pc __asm ("%o7"), *got __asm ("%l7"); + + __asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" + "call 1f\n\t" + " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" + "call _DYNAMIC\n\t" + "call _GLOBAL_OFFSET_TABLE_\n" + "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got)); + + /* got is now l_addr + _GLOBAL_OFFSET_TABLE_ + *got is _DYNAMIC + pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8 + pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12 */ + return (Elf32_Addr) got - *got + (pc[2] - pc[3]) * 4 - 4; +} + +static inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *) (rel_addr + load_off); + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} -- cgit v1.2.3