[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