summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
authorKhem Raj <kraj@mvista.com>2006-10-07 06:32:44 +0000
committerKhem Raj <kraj@mvista.com>2006-10-07 06:32:44 +0000
commit2785c5d58d8b8cbf3ba0355a19bf497995bd5a39 (patch)
tree8b5e1cff4518364377292cd86edea30fc25b4d05 /ldso
parentb9950f0c0f08ded31e8b041e483693619b6750fb (diff)
Don't use r10 to find PIC base. In GCC 4.1.1 onwards ARM PIC handling uses pseudo register for PIC base so load and relocate it.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/ldso/arm/dl-sysdep.h34
1 files changed, 29 insertions, 5 deletions
diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h
index 5935738e1..c8e1b9851 100644
--- a/ldso/ldso/arm/dl-sysdep.h
+++ b/ldso/ldso/arm/dl-sysdep.h
@@ -69,15 +69,39 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
| (((type) == R_ARM_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. */
+ first element of the GOT. We used to use the PIC register to do this
+ without a constant pool reference, but GCC 4.2 will use a pseudo-register
+ for the PIC base, so it may not be in r10. */
static inline Elf32_Addr __attribute__ ((unused))
elf_machine_dynamic (void)
{
- register Elf32_Addr *got asm ("r10");
- return *got;
-}
+ Elf32_Addr dynamic;
+#if !defined __thumb__
+ asm ("ldr %0, 2f\n"
+ "1: ldr %0, [pc, %0]\n"
+ "b 3f\n"
+ "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
+ "3:" : "=r" (dynamic));
+#else
+ int tmp;
+ asm (".align 2\n"
+ "bx pc\n"
+ "nop\n"
+ ".arm\n"
+ "ldr %0, 2f\n"
+ "1: ldr %0, [pc, %0]\n"
+ "b 3f\n"
+ "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
+ "3:"
+ ".align 2\n"
+ "orr %1, pc, #1\n"
+ "bx %1\n"
+ ".force_thumb\n"
+ : "=r" (dynamic), "=&r" (tmp));
+#endif
+ return dynamic;
+}
/* Return the run-time load address of the shared object. */
static inline Elf32_Addr __attribute__ ((unused))