diff --git a/compiler-rt/lib/asan/asan_thread.cpp b/compiler-rt/lib/asan/asan_thread.cpp --- a/compiler-rt/lib/asan/asan_thread.cpp +++ b/compiler-rt/lib/asan/asan_thread.cpp @@ -321,7 +321,8 @@ void AsanThread::ClearShadowForThreadStackAndTLS() { if (stack_top_ != stack_bottom_) - PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); + PoisonShadow(stack_bottom_, + RoundUpTo(stack_top_ - stack_bottom_, SHADOW_GRANULARITY), 0); if (tls_begin_ != tls_end_) { uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY); uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY); 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 @@ -329,73 +329,46 @@ return val; } -// The offset at which pointer to self is located in the thread descriptor. -const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16); - -uptr ThreadSelfOffset() { - return kThreadSelfOffset; -} - -#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 -// TlsPreTcbSize includes size of struct pthread_descr and size of tcb -// head structure. It lies before the static tls blocks. -static uptr TlsPreTcbSize() { -#if defined(__mips__) - const uptr kTcbHead = 16; // sizeof (tcbhead_t) -#elif defined(__powerpc64__) - const uptr kTcbHead = 88; // sizeof (tcbhead_t) -#elif SANITIZER_RISCV64 - const uptr kTcbHead = 16; // sizeof (tcbhead_t) -#endif - const uptr kTlsAlign = 16; - const uptr kTlsPreTcbSize = - RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign); - return kTlsPreTcbSize; +#if !SANITIZER_GO +static int GetStaticTlsRangeCB(struct dl_phdr_info *info, size_t size, + void *data) { + if (!info->dlpi_tls_data) + return 0; + uptr *range = (uptr *)data; + uptr begin = (uptr)info->dlpi_tls_data, end = begin, align = 0; + for (int i = 0; i != info->dlpi_phnum; ++i) + if (info->dlpi_phdr[i].p_type == PT_TLS) { + end = begin + info->dlpi_phdr[i].p_memsz; + align = info->dlpi_phdr[i].p_align; + break; + } + if (range[0] == 0) { + range[0] = begin; + range[1] = end; + } else if (range[1] <= begin && begin < range[1] + align) { + // Extend the right boundary. This must be the TLS above TP case. + range[1] = end; + } else if (end <= range[0] && range[0] < end + align) { + // Extend the left boundary. This must be the TLS below TP case. + range[0] = begin; + } else { + // We assume dl_iterate_phdr iterated program headers are consecutive. Once + // we cannot extend the boundaries, we should have processed all the static + // TLS modules. + return 1; + } + return 0; } -#endif -uptr ThreadSelf() { - uptr descr_addr; -#if defined(__i386__) - asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); -#elif defined(__x86_64__) - asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); -#elif defined(__mips__) - // MIPS uses TLS variant I. The thread pointer (in hardware register $29) - // points to the end of the TCB + 0x7000. The pthread_descr structure is - // immediately in front of the TCB. TlsPreTcbSize() includes the size of the - // TCB and the size of pthread_descr. - const uptr kTlsTcbOffset = 0x7000; - uptr thread_pointer; - asm volatile(".set push;\ - .set mips64r2;\ - rdhwr %0,$29;\ - .set pop" : "=r" (thread_pointer)); - descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize(); -#elif defined(__aarch64__) || defined(__arm__) - descr_addr = reinterpret_cast(__builtin_thread_pointer()) - - ThreadDescriptorSize(); -#elif SANITIZER_RISCV64 - // https://github.com/riscv/riscv-elf-psabi-doc/issues/53 - uptr thread_pointer = reinterpret_cast(__builtin_thread_pointer()); - descr_addr = thread_pointer - TlsPreTcbSize(); -#elif defined(__s390__) - descr_addr = reinterpret_cast(__builtin_thread_pointer()); -#elif defined(__powerpc64__) - // PPC64LE uses TLS variant I. The thread pointer (in GPR 13) - // points to the end of the TCB + 0x7000. The pthread_descr structure is - // immediately in front of the TCB. TlsPreTcbSize() includes the size of the - // TCB and the size of pthread_descr. - const uptr kTlsTcbOffset = 0x7000; - uptr thread_pointer; - asm("addi %0,13,%1" : "=r"(thread_pointer) : "I"(-kTlsTcbOffset)); - descr_addr = thread_pointer - TlsPreTcbSize(); -#else -#error "unsupported CPU arch" -#endif - return descr_addr; +static void GetStaticTlsRange(uptr *addr, uptr *size) { + uptr range[2] = {0, 0}; + dl_iterate_phdr(GetStaticTlsRangeCB, range); + *addr = range[0]; + *size = range[1] - range[0]; } -#endif // (x86_64 || i386 || MIPS) && SANITIZER_LINUX +#endif // !SANITIZER_GO +#endif // (x86_64 || i386 || mips || ...) && SANITIZER_LINUX && + // !SANITIZER_ANDROID #if SANITIZER_FREEBSD static void **ThreadSelfSegbase() { @@ -467,18 +440,18 @@ *size = 0; } #elif SANITIZER_LINUX + GetStaticTlsRange(addr, size); + // Extend the range to include the thread control block: lsan needs the + // pointer to the array of thread-specific data keys. #if defined(__x86_64__) || defined(__i386__) || defined(__s390__) - *addr = ThreadSelf(); - *size = GetTlsSize(); - *addr -= *size; - *addr += ThreadDescriptorSize(); -#elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) || \ - defined(__arm__) || SANITIZER_RISCV64 - *addr = ThreadSelf(); - *size = GetTlsSize(); + *size += ThreadDescriptorSize(); #else - *addr = 0; - *size = 0; + // arm and aarch64 reserve two words at TP, so this underestimates the range. + // However, this is sufficient for the purpose of finding the pointer to + // thread-specific data keys. + const uptr tcb_size = ThreadDescriptorSize(); + *addr -= tcb_size; + *size += tcb_size; #endif #elif SANITIZER_FREEBSD void** segbase = ThreadSelfSegbase(); @@ -519,17 +492,11 @@ #if !SANITIZER_GO uptr GetTlsSize() { -#if SANITIZER_FREEBSD || SANITIZER_ANDROID || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS +#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_ANDROID || \ + SANITIZER_NETBSD || SANITIZER_SOLARIS uptr addr, size; GetTls(&addr, &size); return size; -#elif SANITIZER_GLIBC -#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 - return RoundUpTo(g_tls_size + TlsPreTcbSize(), 16); -#else - return g_tls_size; -#endif #else return 0; #endif @@ -552,10 +519,8 @@ if (!main) { // If stack and tls intersect, make them non-intersecting. if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) { - CHECK_GT(*tls_addr + *tls_size, *stk_addr); CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size); - *stk_size -= *tls_size; - *tls_addr = *stk_addr + *stk_size; + *stk_size = *tls_addr - *stk_addr; } } #endif