diff options
author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2005-03-14 13:25:07 +0000 |
---|---|---|
committer | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2005-03-14 13:25:07 +0000 |
commit | 7d137fcf818e9a157a9f7ed9df61896f6cf97490 (patch) | |
tree | 4cd0201de5e99f8f7fc3e40ac97fe9e44411d29f /ldso/ldso/cris | |
parent | 3b67c539e3f14a7acf59608d6f7a37b710033a5c (diff) |
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__
Diffstat (limited to 'ldso/ldso/cris')
-rw-r--r-- | ldso/ldso/cris/dl-sysdep.h | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/ldso/ldso/cris/dl-sysdep.h b/ldso/ldso/cris/dl-sysdep.h index ab089072f..d12644a2d 100644 --- a/ldso/ldso/cris/dl-sysdep.h +++ b/ldso/ldso/cris/dl-sysdep.h @@ -1,6 +1,6 @@ /* CRIS can never use Elf32_Rel relocations. */ #define ELF_USES_RELOCA - +#include <elf.h> /* Initialization sequence for the GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ { \ @@ -75,3 +75,47 @@ cris_mod(unsigned long m, unsigned long p) ((((((type) == R_CRIS_JUMP_SLOT)) \ || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY)) + +static inline Elf32_Addr +elf_machine_dynamic (void) +{ + /* Don't just set this to an asm variable "r0" since that's not logical + (like, the variable is uninitialized and the register is fixed) and + may make GCC trip over itself doing register allocation. Yes, I'm + paranoid. Why do you ask? */ + Elf32_Addr *got; + + __asm__ ("move.d $r0,%0" : "=rm" (got)); + return *got; +} + +/* Return the run-time load address of the shared object. We do it like + m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry + for it, and peeking into the GOT table, which is set to the link-time + file-relative symbol value (regardless of whether the target is REL or + RELA). We subtract this link-time file-relative value from the "local" + value we calculate from GOT position and GOT offset. FIXME: Perhaps + there's some other symbol we could use, that we don't *have* to force a + GOT entry for. */ + +static inline Elf32_Addr +elf_machine_load_address (void) +{ + Elf32_Addr gotaddr_diff; + __asm__ ("sub.d [$r0+_dl_boot:GOT16],$r0,%0\n\t" + "add.d _dl_boot:GOTOFF,%0" : "=r" (gotaddr_diff)); + return gotaddr_diff; +} + +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); +} |