diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -19,7 +19,9 @@ #include "hwasan_thread.h" #include "interception/interception.h" #include "sanitizer_common/sanitizer_linux.h" +#include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_stackdepot.h" +#include "sanitizer_common/sanitizer_tls_get_addr.h" #if !SANITIZER_FUCHSIA @@ -241,6 +243,37 @@ #undef SIG_BLOCK #undef SIG_SETMASK +// Adapted from sanitizer_common/sanitizer_common_interceptors.inc +// S390 and PowerPPC are left as an exercise for the reader. +#if SANITIZER_INTERCEPT_TLS_GET_ADDR +#if !SANITIZER_S390 && !SANITIZER_PPC +// If you see any crashes around this functions, there are 2 known issues with +// it: 1. __tls_get_addr can be called with mis-aligned stack due to: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 +// 2. It can be called recursively if sanitizer code uses __tls_get_addr +// to access thread local variables (it should not happen normally, +// because sanitizers use initial-exec tls model). +INTERCEPTOR(void *, __tls_get_addr, void *arg) { + void *res = REAL(__tls_get_addr)(arg); + uptr tls_begin, tls_end; + + if (Thread *t = GetCurrentThread()) { + tls_begin = t->tls_begin(); + tls_end = t->tls_end(); + } else { + tls_begin = tls_end = 0; + } + + DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end); + if (dtv) { + // New DTLS block has been allocated. + // Nothing to do for now - memory was allocated with malloc + } + return res; +} +#endif +#endif + # endif // HWASAN_WITH_INTERCEPTORS namespace __hwasan { @@ -271,6 +304,11 @@ #endif // __linux__ INTERCEPT_FUNCTION(pthread_create); INTERCEPT_FUNCTION(pthread_join); +#if SANITIZER_INTERCEPT_TLS_GET_ADDR +#if !SANITIZER_S390 && !SANITIZER_PPC + INTERCEPT_FUNCTION(__tls_get_addr); +#endif +#endif // SANITIZER_INTERCEPT_TLS_GET_ADDR # endif inited = 1; diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp @@ -6,7 +6,10 @@ // UNSUPPORTED: i386-linux // Do not intercept __tls_get_addr -// UNSUPPORTED: hwasan, lsan, ubsan, android +// UNSUPPORTED: lsan, ubsan, android + +// Does not intercept __tls_get_addr +// UNSUPPORTED: hwasan && target={{(powerpc64|s390x).*}} // FIXME: Investigate // UNSUPPORTED: target=powerpc64{{.*}}