diff options
-rw-r--r-- | arch/arm/reloc.h | 4 | ||||
-rw-r--r-- | ldso/dynlink.c | 7 | ||||
-rw-r--r-- | src/ldso/arm/tlsdesc.S | 62 |
3 files changed, 72 insertions, 1 deletions
diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h index 4b00bf64..2c2e7f58 100644 --- a/arch/arm/reloc.h +++ b/arch/arm/reloc.h @@ -26,7 +26,9 @@ #define REL_DTPMOD R_ARM_TLS_DTPMOD32 #define REL_DTPOFF R_ARM_TLS_DTPOFF32 #define REL_TPOFF R_ARM_TLS_TPOFF32 -//#define REL_TLSDESC R_ARM_TLS_DESC +#define REL_TLSDESC R_ARM_TLS_DESC + +#define TLSDESC_BACKWARDS #define CRTJMP(pc,sp) __asm__ __volatile__( \ "mov sp,%1 ; bx %0" : : "r"(pc), "r"(sp) : "memory" ) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 3ecbddfa..c2892b90 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -458,6 +458,13 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + addend; #endif } +#ifdef TLSDESC_BACKWARDS + /* Some archs (32-bit ARM at least) invert the order of + * the descriptor members. Fix them up here. */ + size_t tmp = reloc_addr[0]; + reloc_addr[0] = reloc_addr[1]; + reloc_addr[1] = tmp; +#endif break; default: error("Error relocating %s: unsupported relocation type %d", diff --git a/src/ldso/arm/tlsdesc.S b/src/ldso/arm/tlsdesc.S new file mode 100644 index 00000000..f3d67fce --- /dev/null +++ b/src/ldso/arm/tlsdesc.S @@ -0,0 +1,62 @@ +.syntax unified + +.text +.global __tlsdesc_static +.hidden __tlsdesc_static +.type __tlsdesc_static,%function +__tlsdesc_static: + ldr r0,[r0] + bx lr + +.hidden __tls_get_new + +.global __tlsdesc_dynamic +.hidden __tlsdesc_dynamic +.type __tlsdesc_dynamic,%function +__tlsdesc_dynamic: + push {r2,r3,ip,lr} + ldr r1,[r0] + ldr r2,[r1,#4] // r2 = offset + ldr r1,[r1] // r1 = modid + + ldr r0,1f + add r0,r0,pc + ldr r0,[r0] +2: +#if __ARM_ARCH >= 5 + blx r0 // r0 = tp +#else + mov lr,pc + bx r0 +#endif + ldr r3,[r0,#-4] // r3 = dtv + ldr ip,[r3] // ip = dtv slot count + cmp r1,ip + bhi 3f + ldr ip,[r3,r1,LSL #2] + sub r0,ip,r0 + add r0,r0,r2 // r0 = r3[r1]-r0+r2 +4: +#if __ARM_ARCH >= 5 + pop {r2,r3,ip,pc} +#else + pop {r2,r3,ip,lr} + bx lr +#endif + +3: +#if __ARM_PCS_VFP || !__SOFTFP__ + vpush {d0-d7} +#endif + push {r0-r3} + add r0,sp,#4 + bl __tls_get_new + pop {r1-r3,ip} +#if __ARM_PCS_VFP || !__SOFTFP__ + vpop {d0-d7} +#endif + sub r0,r0,r1 // r0 = retval-tp + b 4b + + .align 2 +1: .word __a_gettp_ptr - 2b |