[sanitizer] Simplify GetTls with dl_iterate_phdr on Linux
authorFangrui Song <i@maskray.me>
Sun, 4 Apr 2021 22:35:53 +0000 (15:35 -0700)
committerFangrui Song <i@maskray.me>
Sun, 4 Apr 2021 22:35:53 +0000 (15:35 -0700)
commitec575e3b0a462ff7a3d23d0f39a22147606050de
treeaf502c487337b50b44a9359d4e2ddc5b0fcd0297
parent9abff04e506fe0b86485909434d4dc3b6011c463
[sanitizer] Simplify GetTls with dl_iterate_phdr on Linux

This was reverted by f176803ef1f4050a350e01868d64fe09a674d3bf due to
Ubuntu 16.04 x86-64 glibc 2.23 problems.
This commit additionally calls `__tls_get_addr({modid,0})` to work around the
dlpi_tls_data==NULL issues for glibc<2.25
(https://sourceware.org/bugzilla/show_bug.cgi?id=19826)

GetTls is the range of

* thread control block and optional TLS_PRE_TCB_SIZE
* static TLS blocks plus static TLS surplus

On glibc, lsan requires the range to include
`pthread::{specific_1stblock,specific}` so that allocations only referenced by
`pthread_setspecific` can be scanned.

This patch uses `dl_iterate_phdr` to collect TLS blocks. Find the one
with `dlpi_tls_modid==1` as one of the initially loaded module, then find
consecutive ranges. The boundaries give us addr and size.

This allows us to drop the glibc internal `_dl_get_tls_static_info` and
`InitTlsSize` entirely. Use the simplified method with non-Android Linux for
now, but in theory this can be used with *BSD and potentially other ELF OSes.

This simplification enables D99566 for TLS Variant I architectures.

See https://reviews.llvm.org/D93972#2480556 for analysis on GetTls usage
across various sanitizers.

Differential Revision: https://reviews.llvm.org/D98926
18 files changed:
compiler-rt/lib/asan/asan_rtl.cpp
compiler-rt/lib/asan/asan_thread.cpp
compiler-rt/lib/hwasan/hwasan.cpp
compiler-rt/lib/lsan/lsan.cpp
compiler-rt/lib/memprof/memprof_rtl.cpp
compiler-rt/lib/msan/msan.cpp
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
compiler-rt/lib/sanitizer_common/sanitizer_linux.h
compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
compiler-rt/lib/sanitizer_common/sanitizer_rtems.cpp
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cpp
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
compiler-rt/test/asan/TestCases/Linux/static_tls.cpp