diff options
Diffstat (limited to 'packages/uclibc/uclibc-0.9.28/thumb-resolve.patch')
-rw-r--r-- | packages/uclibc/uclibc-0.9.28/thumb-resolve.patch | 130 |
1 files changed, 102 insertions, 28 deletions
diff --git a/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch b/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch index 9d1db384ab..0a99a7d9bc 100644 --- a/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch +++ b/packages/uclibc/uclibc-0.9.28/thumb-resolve.patch @@ -5,7 +5,7 @@ # count (faster in caller and callee, and slightly easier to understand). # --- uClibc-0.9.28/.pc/thumb-resolve.patch/ldso/ldso/arm/elfinterp.c 2005-08-17 15:49:41.000000000 -0700 -+++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2005-09-07 20:10:36.231602806 -0700 ++++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2005-09-17 12:55:26.379172744 -0700 @@ -55,7 +55,7 @@ rel_addr = (ELF_RELOC *) tpnt->dynamic_info[DT_JMPREL]; @@ -15,9 +15,19 @@ reloc_type = ELF32_R_TYPE(this_reloc->r_info); symtab_index = ELF32_R_SYM(this_reloc->r_info); +@@ -84,7 +84,9 @@ + _dl_exit(1); + }; + #if defined (__SUPPORT_LD_DEBUG__) ++#if !defined __SUPPORT_LD_DEBUG_EARLY__ + if ((unsigned long) got_addr < 0x40000000) ++#endif + { + if (_dl_debug_bindings) + { --- uClibc-0.9.28/.pc/thumb-resolve.patch/ldso/ldso/arm/resolve.S 2005-08-17 15:49:41.000000000 -0700 -+++ uClibc-0.9.28/ldso/ldso/arm/resolve.S 2005-09-08 09:54:03.536608499 -0700 -@@ -1,43 +1,121 @@ ++++ uClibc-0.9.28/ldso/ldso/arm/resolve.S 2005-09-17 11:02:27.860627464 -0700 +@@ -1,43 +1,163 @@ /* - * This function is _not_ called directly. It is jumped to (so no return - * address is on the stack) when attempting to use a symbol that has not yet @@ -127,16 +137,19 @@ + * that linux/uclibc seems to be using r10 - sl - as a PIC base register - see + * dl-startup.c). */ - +- -#define sl r10 -#define fp r11 -#define ip r12 -- ++#include <sys/syscall.h> + .text ++.align 4 @ 16 byte boundary and there are 32 bytes below (arm case) ++#if !defined(__thumb__) ++.arm .globl _dl_linux_resolve .type _dl_linux_resolve,%function -.align 4; -+.align 4 @ 16 byte boundary and there are 32 bytes below _dl_linux_resolve: - stmdb sp!, {r0, r1, r2, r3, sl, fp} @@ -169,18 +182,59 @@ +#else + mov pc, ip +#endif ++.size _dl_linux_resolve, .-_dl_linux_resolve ++#else ++ @ In the thumb case _dl_linux_resolver is thumb. If a bl is used ++ @ from arm code the linker will insert a stub call which, with ++ @ binutils 2.16, is not PIC. Since this code is accessed by an ++ @ ldr pc the reasonable fix is to make _dl_linux_resolve thumb too. ++.thumb ++.globl _dl_linux_resolve ++.thumb_func ++.type _dl_linux_resolve,%function ++ ++_dl_linux_resolve: ++ @ _dl_linux_resolver is a standard subroutine call, therefore it ++ @ preserves everything except r0-r3 (a1-a4), ip and lr. This ++ @ function must branch to the real function, and that expects ++ @ r0-r3 and lr to be as they were before the whole PLT stuff - ++ @ ip can be trashed. ++ push {r0-r3} ++ mov r1, lr @ &GOT_TABLE[2] ++ sub r0, r1, #4 ++ mov r2, ip @ &GOT[n] ++ ldr r0, [r0] @ r0 := GOT_TABLE[1] ++ @ for the function call r1 := n-3 ++ sub r1, r2 ++ asr r1, r1, #2 ++ mvn r1, r1 @ exactly as in the arm code above ++ ++ bl _dl_linux_resolver ++ ++ @ r0 contains the branch address, the return address is above ++ @ the saved r0..r3 ++ mov ip, r0 ++ ldr r1, [sp, #16] ++ mov lr, r1 ++ pop {r0-r3} ++ add sp, #4 ++ bx ip ++ .size _dl_linux_resolve, .-_dl_linux_resolve ---- uClibc/ldso/ldso/dl-hash.c 2005-09-08 13:54:30.124416436 -0700 -+++ uClibc/ldso/ldso/dl-hash.c 2005-09-08 14:17:44.828179610 -0700 -@@ -186,11 +186,19 @@ ++#endif +--- uClibc-0.9.28/.pc/thumb-resolve.patch/ldso/ldso/dl-hash.c 2005-08-17 15:49:41.000000000 -0700 ++++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2005-09-21 18:56:31.181689732 -0700 +@@ -182,28 +182,52 @@ + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + + for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) { ++ char *result; + sym = &symtab[si]; - if (type_class & (sym->st_shndx == SHN_UNDEF)) +- if (type_class & (sym->st_shndx == SHN_UNDEF)) ++ if (sym->st_shndx == SHN_UNDEF) continue; - if (_dl_strcmp(strtab + sym->st_name, name) != 0) -- continue; - if (sym->st_value == 0) - continue; -- if (ELF_ST_TYPE(sym->st_info) > STT_FUNC) + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC +#if defined(__arm__) || defined(__thumb__) + /* On ARM (only) STT_ARM_TFUNC is a function @@ -190,26 +244,46 @@ + && ELF_ST_TYPE(sym->st_info) != STT_ARM_TFUNC +#endif + ) -+ continue; + continue; +- if (sym->st_value == 0) + if (_dl_strcmp(strtab + sym->st_name, name) != 0) continue; +- if (ELF_ST_TYPE(sym->st_info) > STT_FUNC) ++#if 0 ++ /* I don't know how to write this test - need to test shndx ++ * to see if it is the PLT for this module. ++ */ ++ if ((type_class & ELF_RTYPE_CLASS_PLT) && some test) + continue; ++#endif - switch (ELF_ST_BIND(sym->st_info)) { -@@ -203,7 +211,17 @@ - break; - #endif - case STB_GLOBAL: +#if defined(__arm__) || defined(__thumb__) -+ /* On ARM the caller needs to know that STT_ARM_TFUNC -+ * is a thumb function call, this is now indicated by -+ * setting the low bit of the value (and newer binutils -+ * will do this and record STT_FUNC). -+ */ -+ return (char*)tpnt->loadaddr + (sym->st_value | -+ (ELF_ST_TYPE(sym->st_info) == STT_ARM_TFUNC)); ++ /* On ARM the caller needs to know that STT_ARM_TFUNC ++ * is a thumb function call, this is now indicated by ++ * setting the low bit of the value (and newer binutils ++ * will do this and record STT_FUNC). ++ */ ++ result = (char*)tpnt->loadaddr + (sym->st_value | ++ (ELF_ST_TYPE(sym->st_info) == STT_ARM_TFUNC)); +#else - return (char*)tpnt->loadaddr + sym->st_value; ++ result = (char*)tpnt->loadaddr + sym->st_value; +#endif + switch (ELF_ST_BIND(sym->st_info)) { + case STB_WEAK: +-#if 0 +-/* Perhaps we should support old style weak symbol handling +- * per what glibc does when you export LD_DYNAMIC_WEAK */ ++ /* Record for use later if we can't find a global. */ + if (!weak_result) +- weak_result = (char *)tpnt->loadaddr + sym->st_value; ++ weak_result = result; + break; +-#endif ++ + case STB_GLOBAL: +- return (char*)tpnt->loadaddr + sym->st_value; ++ return result; ++ default: /* Local symbols not handled here */ break; } |