Index: lib/sanitizer_common/sanitizer_linux.h =================================================================== --- lib/sanitizer_common/sanitizer_linux.h +++ lib/sanitizer_common/sanitizer_linux.h @@ -34,7 +34,6 @@ struct sigaltstack* oss); uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); -void internal_sigfillset(__sanitizer_sigset_t *set); // Linux-only syscalls. #if SANITIZER_LINUX Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -618,10 +618,6 @@ #endif } -void internal_sigfillset(__sanitizer_sigset_t *set) { - internal_memset(set, 0xff, sizeof(*set)); -} - #if SANITIZER_LINUX void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { signum -= 1; Index: lib/sanitizer_common/sanitizer_posix.h =================================================================== --- lib/sanitizer_common/sanitizer_posix.h +++ lib/sanitizer_common/sanitizer_posix.h @@ -16,6 +16,7 @@ // ----------- ATTENTION ------------- // This header should NOT include any other headers from sanitizer runtime. #include "sanitizer_internal_defs.h" +#include "sanitizer_platform_limits_posix.h" #if !SANITIZER_POSIX // Make it hard to accidentally use any of functions declared in this file: @@ -78,6 +79,7 @@ int my_pthread_attr_getstack(void *attr, void **addr, uptr *size); int internal_sigaction(int signum, const void *act, void *oldact); +void internal_sigfillset(__sanitizer_sigset_t *set); } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_posix.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix.cc +++ lib/sanitizer_common/sanitizer_posix.cc @@ -321,6 +321,10 @@ return SignalContext(context, addr, pc, sp, bp); } +void internal_sigfillset(__sanitizer_sigset_t *set) { + internal_memset(set, 0xff, sizeof(*set)); +} + } // namespace __sanitizer #endif // SANITIZER_POSIX Index: lib/tsan/rtl/tsan_interceptors.h =================================================================== --- lib/tsan/rtl/tsan_interceptors.h +++ lib/tsan/rtl/tsan_interceptors.h @@ -32,7 +32,7 @@ Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ Die(); \ } \ - if (thr->ignore_interceptors || thr->in_ignored_lib) \ + if (!thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib) \ return REAL(func)(__VA_ARGS__); \ /**/ Index: lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- lib/tsan/rtl/tsan_interceptors.cc +++ lib/tsan/rtl/tsan_interceptors.cc @@ -48,6 +48,13 @@ #define __libc_realloc REAL(realloc) #define __libc_calloc REAL(calloc) #define __libc_free REAL(free) +#elif SANITIZER_ANDROID +#define __errno_location __errno +#define __libc_malloc REAL(malloc) +#define __libc_realloc REAL(realloc) +#define __libc_calloc REAL(calloc) +#define __libc_free REAL(free) +#define mallopt(a, b) #endif #if SANITIZER_LINUX || SANITIZER_FREEBSD @@ -94,8 +101,6 @@ DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); -// REAL(sigfillset) defined in common interceptors. -DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set) DECLARE_REAL(int, fflush, __sanitizer_FILE *fp) DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) @@ -103,10 +108,12 @@ extern "C" void _exit(int status); extern "C" int *__errno_location(); extern "C" int fileno_unlocked(void *stream); +#if !SANITIZER_ANDROID extern "C" void *__libc_calloc(uptr size, uptr n); extern "C" void *__libc_realloc(void *ptr, uptr size); +#endif extern "C" int dirfd(void *dirp); -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID extern "C" int mallopt(int param, int value); #endif extern __sanitizer_FILE *stdout, *stderr; @@ -149,6 +156,17 @@ typedef void (*sighandler_t)(int sig); typedef void (*sigactionhandler_t)(int sig, my_siginfo_t *siginfo, void *uctx); +#if SANITIZER_ANDROID +struct sigaction_t { + u32 sa_flags; + union { + sighandler_t sa_handler; + sigactionhandler_t sa_sigaction; + }; + __sanitizer_sigset_t sa_mask; + void (*sa_restorer)(); +}; +#else struct sigaction_t { #ifdef __mips__ u32 sa_flags; @@ -171,6 +189,7 @@ void (*sa_restorer)(); #endif }; +#endif // SANITIZER_ANDROID const sighandler_t SIG_DFL = (sighandler_t)0; const sighandler_t SIG_IGN = (sighandler_t)1; @@ -204,6 +223,9 @@ atomic_uintptr_t in_blocking_func; atomic_uintptr_t have_pending_signals; SignalDesc pending_signals[kSigCount]; + // emptyset and oldset are too big for stack. + __sanitizer_sigset_t emptyset; + __sanitizer_sigset_t oldset; }; // The object is 64-byte aligned, because we want hot data to be located in @@ -245,10 +267,11 @@ : thr_(thr) , pc_(pc) , in_ignored_lib_(false) { - if (!thr_->ignore_interceptors) { - Initialize(thr); + Initialize(thr); + if (!thr_->is_inited) + return; + if (!thr_->ignore_interceptors) FuncEntry(thr, pc); - } DPrintf("#%d: intercept %s()\n", thr_->tid, fname); if (!thr_->in_ignored_lib && libignore()->IsIgnored(pc)) { in_ignored_lib_ = true; @@ -258,6 +281,8 @@ } ScopedInterceptor::~ScopedInterceptor() { + if (!thr_->is_inited) + return; if (in_ignored_lib_) { thr_->in_ignored_lib = false; ThreadIgnoreEnd(thr_, pc_); @@ -353,6 +378,7 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), void *arg, void *dso); +#if !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, atexit, void (*f)()) { if (cur_thread()->in_symbolizer) return 0; @@ -361,6 +387,7 @@ SCOPED_INTERCEPTOR_RAW(atexit, f); return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0); } +#endif TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) { if (cur_thread()->in_symbolizer) @@ -1350,7 +1377,7 @@ return 0; } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1362,7 +1389,7 @@ #endif TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID SCOPED_TSAN_INTERCEPTOR(stat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(stat)(path, buf); @@ -1373,7 +1400,7 @@ #endif } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1384,7 +1411,7 @@ #define TSAN_MAYBE_INTERCEPT___XSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1395,7 +1422,7 @@ #define TSAN_MAYBE_INTERCEPT_STAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1407,7 +1434,7 @@ #endif TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(lstat)(path, buf); @@ -1418,7 +1445,7 @@ #endif } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1429,7 +1456,7 @@ #define TSAN_MAYBE_INTERCEPT___LXSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1440,7 +1467,7 @@ #define TSAN_MAYBE_INTERCEPT_LSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1453,7 +1480,7 @@ #endif TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); @@ -1466,7 +1493,7 @@ #endif } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1478,7 +1505,7 @@ #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) @@ -1703,7 +1730,7 @@ #endif // glibc guts -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); int fds[64]; @@ -1935,10 +1962,8 @@ return; atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed); atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed); - // These are too big for stack. - static THREADLOCAL __sanitizer_sigset_t emptyset, oldset; - CHECK_EQ(0, REAL(sigfillset)(&emptyset)); - CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &emptyset, &oldset)); + internal_sigfillset(&sctx->emptyset); + CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sctx->emptyset, &sctx->oldset)); for (int sig = 0; sig < kSigCount; sig++) { SignalDesc *signal = &sctx->pending_signals[sig]; if (signal->armed) { @@ -1947,7 +1972,7 @@ &signal->siginfo, &signal->ctx); } } - CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &oldset, 0)); + CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sctx->oldset, 0)); atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed); } @@ -2041,7 +2066,7 @@ #endif sigaction_t newact; internal_memcpy(&newact, act, sizeof(newact)); - REAL(sigfillset)(&newact.sa_mask); + internal_sigfillset(&newact.sa_mask); if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) { if (newact.sa_flags & SA_SIGINFO) newact.sa_sigaction = rtl_sigaction; @@ -2169,7 +2194,7 @@ return WRAP(fork)(fake); } -#if !SANITIZER_MAC +#if !SANITIZER_MAC && !SANITIZER_ANDROID typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { @@ -2491,7 +2516,7 @@ Die(); } -#if !SANITIZER_MAC +#if !SANITIZER_MAC && !SANITIZER_ANDROID static void unreachable() { Report("FATAL: ThreadSanitizer: unreachable called\n"); Die(); @@ -2656,12 +2681,14 @@ TSAN_INTERCEPT(fork); TSAN_INTERCEPT(vfork); +#if !SANITIZER_ANDROID TSAN_INTERCEPT(dl_iterate_phdr); +#endif TSAN_INTERCEPT(on_exit); TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); -#if !SANITIZER_MAC +#if !SANITIZER_MAC && !SANITIZER_ANDROID // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; Index: lib/tsan/rtl/tsan_new_delete.cc =================================================================== --- lib/tsan/rtl/tsan_new_delete.cc +++ lib/tsan/rtl/tsan_new_delete.cc @@ -23,7 +23,7 @@ DECLARE_REAL(void *, malloc, uptr size) DECLARE_REAL(void, free, void *ptr) -#if SANITIZER_MAC +#if SANITIZER_MAC || SANITIZER_ANDROID #define __libc_malloc REAL(malloc) #define __libc_free REAL(free) #endif Index: lib/tsan/rtl/tsan_platform.h =================================================================== --- lib/tsan/rtl/tsan_platform.h +++ lib/tsan/rtl/tsan_platform.h @@ -91,6 +91,42 @@ static const uptr kVdsoBeg = 0xfffff00000ull; }; #elif defined(__aarch64__) + +#if SANITIZER_ANDROID +/* +C/C++ on android/aarch64 (39-bit VMA) +On Android, the executable file is shared library, so it is loaded +to address space near TASK_SIZE*2/3. Vdso area is not guaranteed +to be higher than stack, so disable it. +2000 0000 00 - 4000 0000 00: shadow memory +4000 0000 00 - 5000 0000 00: metainfo +5000 0000 00 - 5500 0000 00: - +5500 0000 00 - 5700 0000 00: main binary +5700 0000 00 - 6000 0000 00: - +6000 0000 00 - 6200 0000 00: traces +6200 0000 00 - 7d00 0000 00: - +7d00 0000 00 - 7e00 0000 00: heap +7e00 0000 00 - 8000 0000 00: modules and main thread stack +*/ +struct Mapping { + static const uptr kShadowBeg = 0x2000000000ull; + static const uptr kShadowEnd = 0x4000000000ull; + static const uptr kMetaShadowBeg = 0x4000000000ull; + static const uptr kMetaShadowEnd = 0x5000000000ull; + static const uptr kLoAppMemBeg = 0x5500000000ull; + static const uptr kLoAppMemEnd = 0x5700000000ull; + static const uptr kTraceMemBeg = 0x6000000000ull; + static const uptr kTraceMemEnd = 0x6200000000ull; + static const uptr kHeapMemBeg = 0x7d00000000ull; + static const uptr kHeapMemEnd = 0x7e00000000ull; + static const uptr kHiAppMemBeg = 0x7e00000000ull; + static const uptr kHiAppMemEnd = 0x8000000000ull; + static const uptr kVdsoBeg = 0x8000000000ull; + static const uptr kLoAppMemAdd = 0x0300000000ull; + static const uptr kLoAppMemMsk = 0x5000000000ull; + static const uptr kHiAppMemMsk = 0x7000000000ull; +}; +#else // AArch64 supports multiple VMA which leads to multiple address transformation // functions. To support these multiple VMAS transformations and mappings TSAN // runtime for AArch64 uses an external memory read (vmaSize) to select which @@ -161,7 +197,8 @@ // Indicates the runtime will define the memory regions at runtime. #define TSAN_RUNTIME_VMA 1 -#endif +#endif // !SANITIZER_ANDROID +#endif // defined(__aarch64__) #elif defined(SANITIZER_GO) && !SANITIZER_WINDOWS @@ -268,7 +305,7 @@ template uptr MappingArchImpl(void) { -#ifdef __aarch64__ +#if defined(__aarch64__) && !SANITIZER_ANDROID if (vmaSize == 39) return MappingImpl(); else @@ -393,7 +430,7 @@ ALWAYS_INLINE bool IsAppMem(uptr mem) { -#ifdef __aarch64__ +#if defined(__aarch64__) && !SANITIZER_ANDROID if (vmaSize == 39) return IsAppMemImpl(mem); else @@ -412,7 +449,7 @@ ALWAYS_INLINE bool IsShadowMem(uptr mem) { -#ifdef __aarch64__ +#if defined(__aarch64__) && !SANITIZER_ANDROID if (vmaSize == 39) return IsShadowMemImpl(mem); else @@ -431,7 +468,7 @@ ALWAYS_INLINE bool IsMetaMem(uptr mem) { -#ifdef __aarch64__ +#if defined(__aarch64__) && !SANITIZER_ANDROID if (vmaSize == 39) return IsMetaMemImpl(mem); else @@ -454,14 +491,30 @@ #endif } +template +uptr MemToShadowAndroidImpl(uptr x) { + DCHECK(IsAppMem(x)); + if (x <= Mapping::kLoAppMemEnd) + return ((x & ~(Mapping::kLoAppMemMsk | (kShadowCell - 1))) + + Mapping::kLoAppMemAdd) * kShadowCnt; + else + return ((x & ~(Mapping::kHiAppMemMsk | (kShadowCell - 1)))) * kShadowCnt; +} + ALWAYS_INLINE uptr MemToShadow(uptr x) { #ifdef __aarch64__ + +#if SANITIZER_ANDROID + return MemToShadowAndroidImpl(x); +#else if (vmaSize == 39) return MemToShadowImpl(x); else return MemToShadowImpl(x); DCHECK(0); +#endif + #else return MemToShadowImpl(x); #endif @@ -481,14 +534,32 @@ #endif } +template +u32 *MemToMetaAndroidImpl(uptr x) { + DCHECK(IsAppMem(x)); + if (x <= Mapping::kLoAppMemEnd) + return (u32*)((((x & ~(Mapping::kLoAppMemMsk | (kMetaShadowCell - 1))) + + Mapping::kLoAppMemAdd) / kMetaShadowCell * kMetaShadowSize) + | Mapping::kMetaShadowBeg); + else + return (u32*)(((x & ~(Mapping::kHiAppMemMsk | (kMetaShadowCell - 1))) + / kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); +} + ALWAYS_INLINE u32 *MemToMeta(uptr x) { #ifdef __aarch64__ + +#if SANITIZER_ANDROID + return MemToMetaAndroidImpl(x); +#else if (vmaSize == 39) return MemToMetaImpl(x); else return MemToMetaImpl(x); DCHECK(0); +#endif + #else return MemToMetaImpl(x); #endif @@ -514,14 +585,29 @@ #endif } +template +uptr ShadowToMemAndroidImpl(uptr s) { + DCHECK(IsShadowMem(s)); + if (s <= MemToShadow(Mapping::kLoAppMemEnd)) + return ((s / kShadowCnt) - Mapping::kLoAppMemAdd) | Mapping::kLoAppMemMsk; + else + return ((s / kShadowCnt)) | Mapping::kHiAppMemMsk; +} + ALWAYS_INLINE uptr ShadowToMem(uptr s) { #ifdef __aarch64__ + +#if SANITIZER_ANDROID + return ShadowToMemAndroidImpl(s); +#else if (vmaSize == 39) return ShadowToMemImpl(s); else return ShadowToMemImpl(s); DCHECK(0); +#endif + #else return ShadowToMemImpl(s); #endif @@ -543,7 +629,7 @@ ALWAYS_INLINE uptr GetThreadTrace(int tid) { -#ifdef __aarch64__ +#if defined(__aarch64__) && !SANITIZER_ANDROID if (vmaSize == 39) return GetThreadTraceImpl(tid); else @@ -565,7 +651,7 @@ ALWAYS_INLINE uptr GetThreadTraceHeader(int tid) { -#ifdef __aarch64__ +#if defined(__aarch64__) && !SANITIZER_ANDROID if (vmaSize == 39) return GetThreadTraceHeaderImpl(tid); else Index: lib/tsan/rtl/tsan_platform_linux.cc =================================================================== --- lib/tsan/rtl/tsan_platform_linux.cc +++ lib/tsan/rtl/tsan_platform_linux.cc @@ -18,6 +18,8 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_linux.h" +#include "sanitizer_common/sanitizer_platform_limits_posix.h" #include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" #include "sanitizer_common/sanitizer_stoptheworld.h" @@ -300,7 +302,7 @@ // This is required to properly "close" the fds, because we do not see internal // closes within glibc. The code is a pure hack. int ExtractResolvFDs(void *state, int *fds, int nfd) { -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID int cnt = 0; __res_state *statp = (__res_state*)state; for (int i = 0; i < MAXNS && cnt < nfd; i++) { @@ -352,6 +354,68 @@ void ReplaceSystemMalloc() { } #endif + +#ifndef 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 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]; + 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]); + if (thr == nullptr) { + thr = reinterpret_cast(MmapOrDie(sizeof(ThreadState), + "ThreadState")); + __get_tls()[TLS_SLOT_TSAN] = thr; + if (dead_thread_state == nullptr) { + dead_thread_state = reinterpret_cast( + MmapOrDie(sizeof(ThreadState), "ThreadState")); + dead_thread_state->fast_state.SetIgnoreBit(); + dead_thread_state->ignore_interceptors = 1; + dead_thread_state->is_dead = true; + *const_cast(&dead_thread_state->tid) = -1; + CHECK_EQ(0, internal_mprotect(dead_thread_state, sizeof(ThreadState), + PROT_READ)); + } + } + CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr)); + } + return thr; +} + +void cur_thread_finalize() { + __sanitizer_sigset_t emptyset; + internal_sigfillset(&emptyset); + __sanitizer_sigset_t oldset; + CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset)); + ThreadState* thr = (ThreadState*)__get_tls()[TLS_SLOT_TSAN]; + if (thr != dead_thread_state) { + __get_tls()[TLS_SLOT_TSAN] = dead_thread_state; + UnmapOrDie(thr, sizeof(ThreadState)); + } + CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr)); +} +#endif // SANITIZER_ANDROID +#endif // ifndef SANITIZER_GO + } // namespace __tsan #endif // SANITIZER_LINUX || SANITIZER_FREEBSD Index: lib/tsan/rtl/tsan_platform_posix.cc =================================================================== --- lib/tsan/rtl/tsan_platform_posix.cc +++ lib/tsan/rtl/tsan_platform_posix.cc @@ -47,6 +47,10 @@ const uptr kMadviseRangeBeg = 0xff00000000ull; const uptr kMadviseRangeSize = 0x0100000000ull; #elif defined(__aarch64__) +#if SANITIZER_ANDROID + const uptr kMadviseRangeBeg = 0x7d00000000ull; + const uptr kMadviseRangeSize = 0x0300000000ull; +#else uptr kMadviseRangeBeg = 0; uptr kMadviseRangeSize = 0; if (vmaSize == 39) { @@ -58,6 +62,7 @@ } else { DCHECK(0); } +#endif // !SANITIZER_ANDROID #endif NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), kMadviseRangeSize * kShadowMultiplier); @@ -118,9 +123,14 @@ Die(); } +#if defined(__aarch64__) && SANITIZER_ANDROID + ProtectRange(MetaShadowEnd(), LoAppMemBeg()); + ProtectRange(LoAppMemEnd(), TraceMemBeg()); +#else ProtectRange(LoAppMemEnd(), ShadowBeg()); - ProtectRange(ShadowEnd(), MetaShadowBeg()); ProtectRange(MetaShadowEnd(), TraceMemBeg()); +#endif + ProtectRange(ShadowEnd(), MetaShadowBeg()); // Memory for traces is mapped lazily in MapThreadTrace. // Protect the whole range for now, so that user does not map something here. ProtectRange(TraceMemBeg(), TraceMemEnd()); Index: lib/tsan/rtl/tsan_rtl.h =================================================================== --- lib/tsan/rtl/tsan_rtl.h +++ lib/tsan/rtl/tsan_rtl.h @@ -411,7 +411,7 @@ }; #ifndef SANITIZER_GO -#if SANITIZER_MAC +#if SANITIZER_MAC || SANITIZER_ANDROID ThreadState *cur_thread(); void cur_thread_finalize(); #else @@ -421,7 +421,7 @@ return reinterpret_cast(&cur_thread_placeholder); } INLINE void cur_thread_finalize() { } -#endif // SANITIZER_MAC +#endif // SANITIZER_MAC || SANITIZER_ANDROID #endif // SANITIZER_GO class ThreadContext : public ThreadContextBase {