فهرست منبع

fix __aeabi_read_tp oversight in arm atomics/tls overhaul

calls to __aeabi_read_tp may be generated by the compiler to access
TLS on pre-v6 targets. previously, this function was hard-coded to
call the kuser helper, which would crash on kernels with kuser helper
removed.

to fix the problem most efficiently, the definition of __aeabi_read_tp
is moved so that it's an alias for the new __a_gettp. however, on v7+
targets, code to initialize the runtime choice of thread-pointer
loading code is not even compiled, meaning that defining
__aeabi_read_tp would have caused an immediate crash due to using the
default implementation of __a_gettp with a HCF instruction.

fortunately there is an elegant solution which reduces overall code
size: putting the native thread-pointer loading instruction in the
default code path for __a_gettp, so that separate default/native code
paths are not needed. this function should never be called before
__set_thread_area anyway, and if it is called early on pre-v6
hardware, the old behavior (crashing) is maintained.

ideally __aeabi_read_tp would not be called at all on v7+ targets
anyway -- in fact, prior to the overhaul, the same problem existed,
but it was never caught by users building for v7+ with kuser disabled.
however, it's possible for calls to __aeabi_read_tp to end up in a v7+
binary if some of the object files were built for pre-v7 targets, e.g.
in the case of static libraries that were built separately, so this
case needs to be handled.
Rich Felker 10 سال پیش
والد
کامیت
8cd0b11eaf
3فایلهای تغییر یافته به همراه5 افزوده شده و 10 حذف شده
  1. 1 2
      arch/arm/src/__set_thread_area.c
  2. 4 4
      arch/arm/src/arm/atomics.s
  3. 0 4
      src/thread/arm/tls.s

+ 1 - 2
arch/arm/src/__set_thread_area.c

@@ -9,7 +9,7 @@ extern const unsigned char __attribute__((__visibility__("hidden")))
 	__a_barrier_dummy[], __a_barrier_oldkuser[],
 	__a_barrier_v6[], __a_barrier_v7[],
 	__a_cas_dummy[], __a_cas_v6[], __a_cas_v7[],
-	__a_gettp_dummy[], __a_gettp_native[];
+	__a_gettp_dummy[];
 
 #define __a_barrier_kuser 0xffff0fa0
 #define __a_cas_kuser 0xffff0fc0
@@ -26,7 +26,6 @@ int __set_thread_area(void *p)
 #if !__ARM_ARCH_7A__ && !__ARM_ARCH_7R__ && __ARM_ARCH < 7
 	if (__hwcap & HWCAP_TLS) {
 		size_t *aux;
-		SET(gettp, native);
 		SET(cas, v7);
 		SET(barrier, v7);
 		for (aux=libc.auxv; *aux; aux+=2) {

+ 4 - 4
arch/arm/src/arm/atomics.s

@@ -81,6 +81,10 @@ __a_cas_v7:
 	.word 0xf57ff05b        /* dmb ish */
 	bx lr
 
+.global __aeabi_read_tp
+.type __aeabi_read_tp,%function
+__aeabi_read_tp:
+
 .global __a_gettp
 .hidden __a_gettp
 .type __a_gettp,%function
@@ -92,10 +96,6 @@ __a_gettp:
 .global __a_gettp_dummy
 .hidden __a_gettp_dummy
 __a_gettp_dummy:
-	.word 0xe7fddef1
-.global __a_gettp_native
-.hidden __a_gettp_native
-__a_gettp_native:
 	mrc p15,0,r0,c13,c0,3
 	bx lr
 

+ 0 - 4
src/thread/arm/tls.s

@@ -1,4 +0,0 @@
-.global __aeabi_read_tp
-.type __aeabi_read_tp,%function
-__aeabi_read_tp:
-	ldr pc,=0xffff0fe0