__set_thread_area.c raw

   1  #include <stdint.h>
   2  #include <elf.h>
   3  #include "pthread_impl.h"
   4  #include "libc.h"
   5  
   6  #define HWCAP_TLS (1 << 15)
   7  
   8  extern hidden const unsigned char
   9  	__a_barrier_oldkuser[], __a_barrier_v6[], __a_barrier_v7[],
  10  	__a_cas_v6[], __a_cas_v7[],
  11  	__a_gettp_cp15[];
  12  
  13  #define __a_barrier_kuser 0xffff0fa0
  14  #define __a_barrier_oldkuser (uintptr_t)__a_barrier_oldkuser
  15  #define __a_barrier_v6 (uintptr_t)__a_barrier_v6
  16  #define __a_barrier_v7 (uintptr_t)__a_barrier_v7
  17  
  18  #define __a_cas_kuser 0xffff0fc0
  19  #define __a_cas_v6 (uintptr_t)__a_cas_v6
  20  #define __a_cas_v7 (uintptr_t)__a_cas_v7
  21  
  22  #define __a_gettp_kuser 0xffff0fe0
  23  #define __a_gettp_cp15 (uintptr_t)__a_gettp_cp15
  24  
  25  extern hidden uintptr_t __a_barrier_ptr, __a_cas_ptr, __a_gettp_ptr;
  26  
  27  int __set_thread_area(void *p)
  28  {
  29  #if !__ARM_ARCH_7A__ && !__ARM_ARCH_7R__ && __ARM_ARCH < 7
  30  	if (__hwcap & HWCAP_TLS) {
  31  		size_t *aux;
  32  		__a_cas_ptr = __a_cas_v7;
  33  		__a_barrier_ptr = __a_barrier_v7;
  34  		for (aux=libc.auxv; *aux; aux+=2) {
  35  			if (*aux != AT_PLATFORM) continue;
  36  			const char *s = (void *)aux[1];
  37  			if (s[0]!='v' || s[1]!='6' || s[2]-'0'<10u) break;
  38  			__a_cas_ptr = __a_cas_v6;
  39  			__a_barrier_ptr = __a_barrier_v6;
  40  			break;
  41  		}
  42  	} else {
  43  		int ver = *(int *)0xffff0ffc;
  44  		__a_gettp_ptr = __a_gettp_kuser;
  45  		__a_cas_ptr = __a_cas_kuser;
  46  		__a_barrier_ptr = __a_barrier_kuser;
  47  		if (ver < 2) a_crash();
  48  		if (ver < 3) __a_barrier_ptr = __a_barrier_oldkuser;
  49  	}
  50  #endif
  51  	return __syscall(0xf0005, p);
  52  }
  53