Index: lib/sanitizer_common/sanitizer_linux.h =================================================================== --- lib/sanitizer_common/sanitizer_linux.h +++ lib/sanitizer_common/sanitizer_linux.h @@ -88,6 +88,46 @@ // Call cb for each region mapped by map. void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); + +#if SANITIZER_ANDROID + +#if defined(__aarch64__) +# define __get_tls() \ + ({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; }) +#elif defined(__arm__) +# define __get_tls() \ + ({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; }) +#elif defined(__mips__) +// On mips32r1, this goes via a kernel illegal instruction trap that's +// optimized for v1. +# define __get_tls() \ + ({ register void** __v asm("v1"); \ + __asm__(".set push\n" \ + ".set mips32r2\n" \ + "rdhwr %0,$29\n" \ + ".set pop\n" : "=r"(__v)); \ + __v; }) +#elif defined(__i386__) +# define __get_tls() \ + ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; }) +#elif defined(__x86_64__) +# define __get_tls() \ + ({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; }) +#else +#error "Unsupported architecture." +#endif + +ALWAYS_INLINE uptr *get_android_tls_ptr() { + return reinterpret_cast(__get_tls()); +} + +// The Android Bionic team has allocated a TLS slot for TSan starting with N, +// given that Android currently doesn't support ELF TLS. It is used to store +// Sanitizers thread specific data. +static const int TLS_SLOT_TSAN = 8; + +#endif // SANITIZER_ANDROID + } // namespace __sanitizer #endif // SANITIZER_FREEBSD || SANITIZER_LINUX Index: lib/tsan/rtl/tsan_platform_linux.cc =================================================================== --- lib/tsan/rtl/tsan_platform_linux.cc +++ lib/tsan/rtl/tsan_platform_linux.cc @@ -341,36 +341,23 @@ #if !SANITIZER_GO #if SANITIZER_ANDROID - -#if defined(__aarch64__) -# define __get_tls() \ - ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; }) -#elif defined(__x86_64__) -# define __get_tls() \ - ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; }) -#else -#error unsupported architecture -#endif - -// On Android, __thread is not supported. So we store the pointer to ThreadState -// in TLS_SLOT_TSAN, which is the tls slot allocated by Android bionic for tsan. -static const int TLS_SLOT_TSAN = 8; // On Android, one thread can call intercepted functions after // DestroyThreadState(), so add a fake thread state for "dead" threads. static ThreadState *dead_thread_state = nullptr; ThreadState *cur_thread() { - ThreadState* thr = (ThreadState*)__get_tls()[TLS_SLOT_TSAN]; + ThreadState* thr = + reinterpret_cast(get_android_tls_ptr()[TLS_SLOT_TSAN]); if (thr == nullptr) { __sanitizer_sigset_t emptyset; internal_sigfillset(&emptyset); __sanitizer_sigset_t oldset; CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset)); - thr = reinterpret_cast(__get_tls()[TLS_SLOT_TSAN]); + thr = reinterpret_cast(get_android_tls_ptr()[TLS_SLOT_TSAN]); if (thr == nullptr) { thr = reinterpret_cast(MmapOrDie(sizeof(ThreadState), "ThreadState")); - __get_tls()[TLS_SLOT_TSAN] = thr; + get_android_tls_ptr()[TLS_SLOT_TSAN] = reinterpret_cast(thr); if (dead_thread_state == nullptr) { dead_thread_state = reinterpret_cast( MmapOrDie(sizeof(ThreadState), "ThreadState")); @@ -392,9 +379,11 @@ internal_sigfillset(&emptyset); __sanitizer_sigset_t oldset; CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset)); - ThreadState* thr = (ThreadState*)__get_tls()[TLS_SLOT_TSAN]; + ThreadState* thr = + reinterpret_cast(get_android_tls_ptr()[TLS_SLOT_TSAN]); if (thr != dead_thread_state) { - __get_tls()[TLS_SLOT_TSAN] = dead_thread_state; + get_android_tls_ptr()[TLS_SLOT_TSAN] = + reinterpret_cast(dead_thread_state); UnmapOrDie(thr, sizeof(ThreadState)); } CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));