diff options
author | Kostya Kortchinsky <kostyak@google.com> | 2017-05-02 15:13:36 +0000 |
---|---|---|
committer | Kostya Kortchinsky <kostyak@google.com> | 2017-05-02 15:13:36 +0000 |
commit | 89fac7a414ac95fe9c389e96ce5c0cd21c168e02 (patch) | |
tree | 913696c9e77f04dcfea344b7905278551f188bb3 | |
parent | a09710f1e54c089241210527d2814f588d73b0be (diff) |
[compiler-rt] move tsan's Android __get_tls() to sanitizer_common
Summary:
TSan's Android `__get_tls()` and `TLS_SLOT_TSAN` can be used by other sanitizers as well (see D32649), this change moves them to sanitizer_common.
I picked sanitizer_linux.h as their new home.
In the process, add the 32-bit versions for ARM, i386 & MIPS.
Can the address of `__get_tls()[TLS_SLOT_TSAN]` change in between the calls?
I am not sure if there is a need to repeat the construct as opposed to using a variable. So I left things as they were.
Testing on my side was restricted to a successful cross-compilation.
Reviewers: dvyukov, kubamracek
Reviewed By: dvyukov
Subscribers: aemerson, rengolin, srhines, dberris, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D32705
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@301926 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux.h | 40 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_platform_linux.cc | 24 |
2 files changed, 45 insertions, 19 deletions
diff --git a/lib/sanitizer_common/sanitizer_linux.h b/lib/sanitizer_common/sanitizer_linux.h index 14047b480..ee336f7dd 100644 --- a/lib/sanitizer_common/sanitizer_linux.h +++ b/lib/sanitizer_common/sanitizer_linux.h @@ -88,6 +88,46 @@ bool LibraryNameIs(const char *full_name, const char *base_name); // 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 + +// 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; + +ALWAYS_INLINE uptr *get_android_tls_ptr() { + return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_TSAN]); +} + +#endif // SANITIZER_ANDROID + } // namespace __sanitizer #endif // SANITIZER_FREEBSD || SANITIZER_LINUX diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index 3313288a7..2d488cadd 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -341,36 +341,22 @@ void ReplaceSystemMalloc() { } #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<ThreadState*>(*get_android_tls_ptr()); 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<ThreadState*>(__get_tls()[TLS_SLOT_TSAN]); + thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr()); if (thr == nullptr) { thr = reinterpret_cast<ThreadState*>(MmapOrDie(sizeof(ThreadState), "ThreadState")); - __get_tls()[TLS_SLOT_TSAN] = thr; + *get_android_tls_ptr() = reinterpret_cast<uptr>(thr); if (dead_thread_state == nullptr) { dead_thread_state = reinterpret_cast<ThreadState*>( MmapOrDie(sizeof(ThreadState), "ThreadState")); @@ -392,9 +378,9 @@ void cur_thread_finalize() { 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<ThreadState*>(*get_android_tls_ptr()); if (thr != dead_thread_state) { - __get_tls()[TLS_SLOT_TSAN] = dead_thread_state; + *get_android_tls_ptr() = reinterpret_cast<uptr>(dead_thread_state); UnmapOrDie(thr, sizeof(ThreadState)); } CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr)); |