Skip to content

Commit 7fc481e

Browse files
author
Kostya Kortchinsky
committedMay 2, 2017
[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 llvm-svn: 301926
1 parent 6c3d19b commit 7fc481e

File tree

2 files changed

+45
-19
lines changed

2 files changed

+45
-19
lines changed
 

‎compiler-rt/lib/sanitizer_common/sanitizer_linux.h

+40
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,46 @@ bool LibraryNameIs(const char *full_name, const char *base_name);
8888

8989
// Call cb for each region mapped by map.
9090
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
91+
92+
#if SANITIZER_ANDROID
93+
94+
#if defined(__aarch64__)
95+
# define __get_tls() \
96+
({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; })
97+
#elif defined(__arm__)
98+
# define __get_tls() \
99+
({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; })
100+
#elif defined(__mips__)
101+
// On mips32r1, this goes via a kernel illegal instruction trap that's
102+
// optimized for v1.
103+
# define __get_tls() \
104+
({ register void** __v asm("v1"); \
105+
__asm__(".set push\n" \
106+
".set mips32r2\n" \
107+
"rdhwr %0,$29\n" \
108+
".set pop\n" : "=r"(__v)); \
109+
__v; })
110+
#elif defined(__i386__)
111+
# define __get_tls() \
112+
({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; })
113+
#elif defined(__x86_64__)
114+
# define __get_tls() \
115+
({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; })
116+
#else
117+
#error "Unsupported architecture."
118+
#endif
119+
120+
// The Android Bionic team has allocated a TLS slot for TSan starting with N,
121+
// given that Android currently doesn't support ELF TLS. It is used to store
122+
// Sanitizers thread specific data.
123+
static const int TLS_SLOT_TSAN = 8;
124+
125+
ALWAYS_INLINE uptr *get_android_tls_ptr() {
126+
return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_TSAN]);
127+
}
128+
129+
#endif // SANITIZER_ANDROID
130+
91131
} // namespace __sanitizer
92132

93133
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX

‎compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc

+5-19
Original file line numberDiff line numberDiff line change
@@ -341,36 +341,22 @@ void ReplaceSystemMalloc() { }
341341

342342
#if !SANITIZER_GO
343343
#if SANITIZER_ANDROID
344-
345-
#if defined(__aarch64__)
346-
# define __get_tls() \
347-
({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; })
348-
#elif defined(__x86_64__)
349-
# define __get_tls() \
350-
({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; })
351-
#else
352-
#error unsupported architecture
353-
#endif
354-
355-
// On Android, __thread is not supported. So we store the pointer to ThreadState
356-
// in TLS_SLOT_TSAN, which is the tls slot allocated by Android bionic for tsan.
357-
static const int TLS_SLOT_TSAN = 8;
358344
// On Android, one thread can call intercepted functions after
359345
// DestroyThreadState(), so add a fake thread state for "dead" threads.
360346
static ThreadState *dead_thread_state = nullptr;
361347

362348
ThreadState *cur_thread() {
363-
ThreadState* thr = (ThreadState*)__get_tls()[TLS_SLOT_TSAN];
349+
ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
364350
if (thr == nullptr) {
365351
__sanitizer_sigset_t emptyset;
366352
internal_sigfillset(&emptyset);
367353
__sanitizer_sigset_t oldset;
368354
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
369-
thr = reinterpret_cast<ThreadState*>(__get_tls()[TLS_SLOT_TSAN]);
355+
thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
370356
if (thr == nullptr) {
371357
thr = reinterpret_cast<ThreadState*>(MmapOrDie(sizeof(ThreadState),
372358
"ThreadState"));
373-
__get_tls()[TLS_SLOT_TSAN] = thr;
359+
*get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
374360
if (dead_thread_state == nullptr) {
375361
dead_thread_state = reinterpret_cast<ThreadState*>(
376362
MmapOrDie(sizeof(ThreadState), "ThreadState"));
@@ -392,9 +378,9 @@ void cur_thread_finalize() {
392378
internal_sigfillset(&emptyset);
393379
__sanitizer_sigset_t oldset;
394380
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
395-
ThreadState* thr = (ThreadState*)__get_tls()[TLS_SLOT_TSAN];
381+
ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
396382
if (thr != dead_thread_state) {
397-
__get_tls()[TLS_SLOT_TSAN] = dead_thread_state;
383+
*get_android_tls_ptr() = reinterpret_cast<uptr>(dead_thread_state);
398384
UnmapOrDie(thr, sizeof(ThreadState));
399385
}
400386
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));

0 commit comments

Comments
 (0)
Please sign in to comment.