summaryrefslogtreecommitdiff
path: root/ldso/ldso/i386
diff options
context:
space:
mode:
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>2005-03-14 13:25:07 +0000
committerJoakim Tjernlund <joakim.tjernlund@transmode.se>2005-03-14 13:25:07 +0000
commit7d137fcf818e9a157a9f7ed9df61896f6cf97490 (patch)
tree4cd0201de5e99f8f7fc3e40ac97fe9e44411d29f /ldso/ldso/i386
parent3b67c539e3f14a7acf59608d6f7a37b710033a5c (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/i386')
-rw-r--r--ldso/ldso/i386/dl-sysdep.h41
1 files changed, 40 insertions, 1 deletions
diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h
index a534110e7..b0edee369 100644
--- a/ldso/ldso/i386/dl-sysdep.h
+++ b/ldso/ldso/i386/dl-sysdep.h
@@ -7,7 +7,7 @@
/* Define this if the system uses RELOCA. */
#undef ELF_USES_RELOCA
-
+#include <elf.h>
/* Initialization sequence for the GOT. */
#define INIT_GOT(GOT_BASE,MODULE) \
do { \
@@ -40,3 +40,42 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent
#define elf_machine_type_class(type) \
((((type) == R_386_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_386_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 ("%ebx");
+ return *got;
+}
+
+
+/* Return the run-time load address of the shared object. */
+static inline Elf32_Addr __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+ /* It doesn't matter what variable this is, the reference never makes
+ it to assembly. We need a dummy reference to some global variable
+ via the GOT to make sure the compiler initialized %ebx in time. */
+ extern int _dl_argc;
+ Elf32_Addr addr;
+ asm ("leal _dl_boot@GOTOFF(%%ebx), %0\n"
+ "subl _dl_boot@GOT(%%ebx), %0"
+ : "=r" (addr) : "m" (_dl_argc) : "cc");
+ return addr;
+}
+
+static inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rel * rpnt = (void *) (rel_addr + load_off);
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off;
+ } while (--relative_count);
+}