mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:16:43 +00:00
[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
This commit is contained in:
parent
6c3d19ba45
commit
7fc481e561
@ -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
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user