diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -29,16 +29,13 @@ // To enable LeakSanitizer on a new architecture, one needs to implement the // internal_clone function as well as (probably) adjust the TLS machinery for // the new architecture inside the sanitizer library. -#if (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC) && \ - (SANITIZER_WORDSIZE == 64) && \ +#if (SANITIZER_LINUX || SANITIZER_MAC) && (SANITIZER_WORDSIZE == 64) && \ (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \ defined(__powerpc64__) || defined(__s390x__)) #define CAN_SANITIZE_LEAKS 1 -#elif defined(__i386__) && \ - (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC) +#elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_MAC) #define CAN_SANITIZE_LEAKS 1 -#elif defined(__arm__) && \ - SANITIZER_LINUX && !SANITIZER_ANDROID +#elif defined(__arm__) && SANITIZER_LINUX #define CAN_SANITIZE_LEAKS 1 #elif SANITIZER_NETBSD || SANITIZER_FUCHSIA #define CAN_SANITIZE_LEAKS 1 diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -28,6 +28,15 @@ extern "C" const char *__lsan_current_stage = "unknown"; #if CAN_SANITIZE_LEAKS + +#if SANITIZER_ANDROID + +// Bionic provides an API to iterate through DTLS chunk. +SANITIZER_WEAK_ATTRIBUTE void __libc_iterate_dynamic_tls( + pid_t, void (*cb)(void *, void *, size_t, void *), void *); + +#endif + namespace __lsan { // This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and @@ -299,6 +308,16 @@ kReachable); } } +#if SANITIZER_ANDROID + auto dtls_visitor = [&](void* dtls_begin, + void* dtls_end, + size_t /*dso_id unused*/, + void* /*arg unused*/))->void { + ScanRangeForPointers(dtls_begin, dtls_end, frontier, "DTLS", + kReachable); + }; + __libc_iterate_dynamic_tls(os_id, dtls_visitor, nullptr); +#else if (dtls && !DTLSInDestruction(dtls)) { for (uptr j = 0; j < dtls->dtv_size; ++j) { uptr dtls_beg = dtls->dtv[j].beg; @@ -314,6 +333,7 @@ // this and continue. LOG_THREADS("Thread %d has DTLS under destruction.\n", os_id); } +#endif } } } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -64,6 +64,7 @@ #if SANITIZER_ANDROID #include +#include #if !defined(CPU_COUNT) && !defined(__aarch64__) #include #include @@ -74,7 +75,8 @@ char d_name[]; }; #endif -#endif + +#endif // SANITIZER_ANDROID #if !SANITIZER_ANDROID #include @@ -86,6 +88,13 @@ SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act, void *oldact); +#if SANITIZER_ANDROID + +// Bionic provides an API for querying TLS bounds. +SANITIZER_WEAK_ATTRIBUTE void __libc_get_static_tls_bounds(void **, void **); + +#endif // SANITIZER_ANDROID + int internal_sigaction(int signum, const void *act, void *oldact) { #if !SANITIZER_GO if (&real_sigaction) @@ -427,7 +436,17 @@ #if !SANITIZER_GO static void GetTls(uptr *addr, uptr *size) { -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_ANDROID + *addr = 0; + *size = 0; + + void *start_addr; + void *end_addr; + __libc_get_static_tls_bounds(&start_addr, &end_addr); + *addr = reinterpret_cast(start_addr); + *size = + reinterpret_cast(end_addr) - reinterpret_cast(start_addr) + 1; +#elif SANITIZER_LINUX && !SANITIZER_ANDROID # if defined(__x86_64__) || defined(__i386__) || defined(__s390__) *addr = ThreadSelf(); *size = GetTlsSize(); @@ -471,9 +490,6 @@ #elif SANITIZER_OPENBSD *addr = 0; *size = 0; -#elif SANITIZER_ANDROID - *addr = 0; - *size = 0; #elif SANITIZER_SOLARIS // FIXME *addr = 0;