[llvm-branch-commits] [compiler-rt] [tsan] Use DlSymAllocator (PR #108920)
Vitaly Buka via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Sep 17 10:52:35 PDT 2024
https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/108920
>From 28b3ccb28062cfcd83a2cf2f8df92c905e3a0865 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Mon, 16 Sep 2024 20:52:04 -0700
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.4
[skip ci]
---
.../sanitizer_linux_libcdep.cpp | 142 ++++++++++--------
1 file changed, 77 insertions(+), 65 deletions(-)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
index a5101291904430..53add5a9b16423 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -200,21 +200,6 @@ bool SetEnv(const char *name, const char *value) {
}
# endif
-__attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
- int *patch) {
-# if SANITIZER_GLIBC
- const char *p = gnu_get_libc_version();
- *major = internal_simple_strtoll(p, &p, 10);
- // Caller does not expect anything else.
- CHECK_EQ(*major, 2);
- *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
- *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
- return true;
-# else
- return false;
-# endif
-}
-
// True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ
// #19826) so dlpi_tls_data cannot be used.
//
@@ -224,11 +209,22 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
__attribute__((unused)) static int g_use_dlpi_tls_data;
# if SANITIZER_GLIBC && !SANITIZER_GO
+
+static void GetGLibcVersion(int *major, int *minor, int *patch) {
+ const char *p = gnu_get_libc_version();
+ *major = internal_simple_strtoll(p, &p, 10);
+ // Caller does not expect anything else.
+ CHECK_EQ(*major, 2);
+ *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
+ *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
+}
+
__attribute__((unused)) static size_t g_tls_size;
+
void InitTlsSize() {
int major, minor, patch;
- g_use_dlpi_tls_data =
- GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;
+ GetGLibcVersion(&major, &minor, &patch);
+ g_use_dlpi_tls_data = major == 2 && minor >= 25;
# if defined(__aarch64__) || defined(__x86_64__) || \
defined(__powerpc64__) || defined(__loongarch__)
@@ -244,73 +240,85 @@ void InitTlsSize() {}
// On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
// of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
// to get the pointer to thread-specific data keys in the thread control block.
-# if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
- !SANITIZER_ANDROID && !SANITIZER_GO
+# if (SANITIZER_FREEBSD || SANITIZER_GLIBC) && !SANITIZER_GO
// sizeof(struct pthread) from glibc.
static atomic_uintptr_t thread_descriptor_size;
+// FIXME: Implementation is very GLIBC specific, but it's used by FREEBSD.
static uptr ThreadDescriptorSizeFallback() {
-# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
+# if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \
+ SANITIZER_RISCV64
+# if SANITIZER_GLIBC
int major;
int minor;
int patch;
- if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
- /* sizeof(struct pthread) values from various glibc versions. */
- if (SANITIZER_X32)
- return 1728; // Assume only one particular version for x32.
- // For ARM sizeof(struct pthread) changed in Glibc 2.23.
- if (SANITIZER_ARM)
- return minor <= 22 ? 1120 : 1216;
- if (minor <= 3)
- return FIRST_32_SECOND_64(1104, 1696);
- if (minor == 4)
- return FIRST_32_SECOND_64(1120, 1728);
- if (minor == 5)
- return FIRST_32_SECOND_64(1136, 1728);
- if (minor <= 9)
- return FIRST_32_SECOND_64(1136, 1712);
- if (minor == 10)
- return FIRST_32_SECOND_64(1168, 1776);
- if (minor == 11 || (minor == 12 && patch == 1))
- return FIRST_32_SECOND_64(1168, 2288);
- if (minor <= 14)
- return FIRST_32_SECOND_64(1168, 2304);
- if (minor < 32) // Unknown version
- return FIRST_32_SECOND_64(1216, 2304);
- // minor == 32
- return FIRST_32_SECOND_64(1344, 2496);
- }
+ GetGLibcVersion(&major, &minor, &patch);
+# else // SANITIZER_GLIBC
return 0;
-# elif defined(__s390__) || defined(__sparc__)
+# endif // SANITIZER_GLIBC
+# endif
+
+# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
+ /* sizeof(struct pthread) values from various glibc versions. */
+ if (SANITIZER_X32)
+ return 1728; // Assume only one particular version for x32.
+ // For ARM sizeof(struct pthread) changed in Glibc 2.23.
+ if (SANITIZER_ARM)
+ return minor <= 22 ? 1120 : 1216;
+ if (minor <= 3)
+ return FIRST_32_SECOND_64(1104, 1696);
+ if (minor == 4)
+ return FIRST_32_SECOND_64(1120, 1728);
+ if (minor == 5)
+ return FIRST_32_SECOND_64(1136, 1728);
+ if (minor <= 9)
+ return FIRST_32_SECOND_64(1136, 1712);
+ if (minor == 10)
+ return FIRST_32_SECOND_64(1168, 1776);
+ if (minor == 11 || (minor == 12 && patch == 1))
+ return FIRST_32_SECOND_64(1168, 2288);
+ if (minor <= 14)
+ return FIRST_32_SECOND_64(1168, 2304);
+ if (minor < 32) // Unknown version
+ return FIRST_32_SECOND_64(1216, 2304);
+ // minor == 32
+ return FIRST_32_SECOND_64(1344, 2496);
+# endif
+
+# if SANITIZER_RISCV64
+ // TODO: consider adding an optional runtime check for an unknown (untested)
+ // glibc version
+ if (minor <= 28) // WARNING: the highest tested version is 2.29
+ return 1772; // no guarantees for this one
+ if (minor <= 31)
+ return 1772; // tested against glibc 2.29, 2.31
+ return 1936; // tested against glibc 2.32
+# endif
+
+# if defined(__s390__) || defined(__sparc__)
// The size of a prefix of TCB including pthread::{specific_1stblock,specific}
// suffices. Just return offsetof(struct pthread, specific_used), which hasn't
// changed since 2007-05. Technically this applies to i386/x86_64 as well but
// we call _dl_get_tls_static_info and need the precise size of struct
// pthread.
return FIRST_32_SECOND_64(524, 1552);
-# elif defined(__mips__)
+# endif
+
+# if defined(__mips__)
// TODO(sagarthakur): add more values as per different glibc versions.
return FIRST_32_SECOND_64(1152, 1776);
-# elif SANITIZER_LOONGARCH64
+# endif
+
+# if SANITIZER_LOONGARCH64
return 1856; // from glibc 2.36
-# elif SANITIZER_RISCV64
- int major;
- int minor;
- int patch;
- if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
- // TODO: consider adding an optional runtime check for an unknown (untested)
- // glibc version
- if (minor <= 28) // WARNING: the highest tested version is 2.29
- return 1772; // no guarantees for this one
- if (minor <= 31)
- return 1772; // tested against glibc 2.29, 2.31
- return 1936; // tested against glibc 2.32
- }
- return 0;
-# elif defined(__aarch64__)
+# endif
+
+# if defined(__aarch64__)
// The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
return 1776;
-# elif defined(__powerpc64__)
+# endif
+
+# if defined(__powerpc64__)
return 1776; // from glibc.ppc64le 2.20-8.fc21
# endif
}
@@ -351,6 +359,10 @@ static uptr TlsPreTcbSize() {
}
# endif
+# endif
+
+# if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
+ !SANITIZER_ANDROID && !SANITIZER_GO
namespace {
struct TlsBlock {
uptr begin, end, align;
>From 19fbf2135d7ed48f7e9673a7b0833f86bc8d4afa Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Mon, 16 Sep 2024 21:27:00 -0700
Subject: [PATCH 2/2] keep in_symbolizer
Created using spr 1.3.4
---
.../lib/tsan/rtl/tsan_interceptors_posix.cpp | 39 ++++++++++++-------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 924339191df133..eaa0f6d0de60c2 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -254,9 +254,12 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
#endif
+// FIXME: Use for `in_symbolizer()` as well. As-is we can't use
+// `DlSymAllocator`, because it uses the primary allocator only. Symbolizer
+// requires support of the secondary allocator for larger blocks.
struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
static bool UseImpl() {
- return in_symbolizer() || (ctx && !ctx->initialized);
+ return (ctx && !ctx->initialized);
}
};
@@ -667,6 +670,8 @@ TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
#if !SANITIZER_APPLE
TSAN_INTERCEPTOR(void*, malloc, uptr size) {
+ if (in_symbolizer())
+ return InternalAlloc(size);
if (DlsymAlloc::Use())
return DlsymAlloc::Allocate(size);
void *p = 0;
@@ -686,7 +691,9 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
return user_memalign(thr, pc, align, sz);
}
-TSAN_INTERCEPTOR(void*, calloc, uptr n, uptr size) {
+TSAN_INTERCEPTOR(void *, calloc, uptr n, uptr size) {
+ if (in_symbolizer())
+ return InternalCalloc(n, size);
if (DlsymAlloc::Use())
return DlsymAlloc::Callocate(n, size);
void *p = 0;
@@ -699,6 +706,8 @@ TSAN_INTERCEPTOR(void*, calloc, uptr n, uptr size) {
}
TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
+ if (in_symbolizer())
+ return InternalRealloc(p, size);
if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(p))
return DlsymAlloc::Realloc(p, size);
if (p)
@@ -711,9 +720,9 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
return p;
}
-TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr n, uptr size) {
- if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(p))
- return DlsymAlloc::ReallocArray(p, n, size);
+TSAN_INTERCEPTOR(void *, reallocarray, void *p, uptr n, uptr size) {
+ if (in_symbolizer())
+ return InternalReallocArray(p, n, size);
if (p)
invoke_free_hook(p);
{
@@ -727,6 +736,8 @@ TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr n, uptr size) {
TSAN_INTERCEPTOR(void, free, void *p) {
if (UNLIKELY(!p))
return;
+ if (in_symbolizer())
+ return InternalFree(p);
if (DlsymAlloc::PointerIsMine(p))
return DlsymAlloc::Free(p);
invoke_free_hook(p);
@@ -737,6 +748,8 @@ TSAN_INTERCEPTOR(void, free, void *p) {
TSAN_INTERCEPTOR(void, cfree, void *p) {
if (UNLIKELY(!p))
return;
+ if (in_symbolizer())
+ return InternalFree(p);
if (DlsymAlloc::PointerIsMine(p))
return DlsymAlloc::Free(p);
invoke_free_hook(p);
@@ -826,15 +839,15 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
#if !SANITIZER_APPLE
TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
- if (DlsymAlloc::Use())
- return DlsymAlloc::Allocate(sz, align);
+ if (in_symbolizer())
+ return InternalAlloc(sz, nullptr, align);
SCOPED_INTERCEPTOR_RAW(aligned_alloc, align, sz);
return user_aligned_alloc(thr, pc, align, sz);
}
TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
- if (DlsymAlloc::Use())
- return DlsymAlloc::Allocate(sz, GetPageSizeCached());
+ if (in_symbolizer())
+ return InternalAlloc(sz, nullptr, GetPageSizeCached());
SCOPED_INTERCEPTOR_RAW(valloc, sz);
return user_valloc(thr, pc, sz);
}
@@ -842,10 +855,10 @@ TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
#if SANITIZER_LINUX
TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
- if (DlsymAlloc::Use()) {
+ if (in_symbolizer()) {
uptr PageSize = GetPageSizeCached();
sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
- return DlsymAlloc::Allocate(sz, PageSize);
+ return InternalAlloc(sz, nullptr, PageSize);
}
SCOPED_INTERCEPTOR_RAW(pvalloc, sz);
return user_pvalloc(thr, pc, sz);
@@ -857,8 +870,8 @@ TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
#if !SANITIZER_APPLE
TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
- if (DlsymAlloc::Use()) {
- void *p = DlsymAlloc::Allocate(sz, align);
+ if (in_symbolizer()) {
+ void *p = InternalAlloc(sz, nullptr, align);
if (!p)
return errno_ENOMEM;
*memptr = p;
More information about the llvm-branch-commits
mailing list