completely untested tlsdesc for arm (32-bit)

Submitted by Rich Felker on Oct. 1, 2018, 6:37 p.m.

Details

Message ID 20181001183745.GA17110@brightrain.aerifal.cx
State New
Series "completely untested tlsdesc for arm (32-bit)"
Headers show

Commit Message

Rich Felker Oct. 1, 2018, 6:37 p.m.
On Sun, Sep 30, 2018 at 09:52:23PM -0400, Rich Felker wrote:
> Attached in case anyone has time to review before I get a chance to
> test it.

Original had lots of bugs: reversed cmp, wrong scaling <<4 instead of
*4, wrong vfp push/pop copied from sj/lj asm without changing reg,
etc. The attached version seems to work.

Rich
.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:	blx r0          // r0 = tp
	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

Patch hide | download patch | download mbox

diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h
index 4b00bf6..2c2e7f5 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 3ecbddf..2293032 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -458,6 +458,11 @@  static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
 					+ addend;
 #endif
 			}
+#ifdef TLSDESC_BACKWARDS
+			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",