Skip to content

[tsan] Use DlSymAllocator #108920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 17, 2024

Conversation

vitalybuka
Copy link
Collaborator

@vitalybuka vitalybuka commented Sep 17, 2024

DlSymAllocator allows early allocations, when
tsan is not yet initialized, e.g. from dlsym.

All other sanitizers with interceptors already use
DlSymAllocator.

Existing in_symbolizer() tsan logic is very similar.
However, we need to keep both as DlSymAllocator
does not support large allocations, needed for Symolizer.

@llvmbot
Copy link
Member

llvmbot commented Sep 17, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Vitaly Buka (vitalybuka)

Changes

Existing in_symbolizer() tsan logic does almost
the same.

Not exactly NFC: DlSymAllocator does not allow
large allocation, which probably unlikely here
anyway. Large allocations will go to secondary
allocator, which use slow PointerIsMine.


Full diff: https://github.com/llvm/llvm-project/pull/108920.diff

2 Files Affected:

  • (modified) compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp (+32-24)
  • (modified) compiler-rt/test/sanitizer_common/TestCases/dlsym_alloc.c (-2)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 460cbacf3408cf..924339191df133 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -12,9 +12,11 @@
 // sanitizer_common/sanitizer_common_interceptors.inc
 //===----------------------------------------------------------------------===//
 
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_errno.h"
 #include "sanitizer_common/sanitizer_glibc_version.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_linux.h"
 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
@@ -252,6 +254,12 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
 SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
 #endif
 
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+  static bool UseImpl() {
+    return in_symbolizer() || (ctx && !ctx->initialized);
+  }
+};
+
 }  // namespace __tsan
 
 static ThreadSignalContext *SigCtx(ThreadState *thr) {
@@ -659,8 +667,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;
   {
     SCOPED_INTERCEPTOR_RAW(malloc, size);
@@ -678,9 +686,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) {
-  if (in_symbolizer())
-    return InternalCalloc(n, size);
+TSAN_INTERCEPTOR(void*, calloc, uptr n, uptr size) {
+  if (DlsymAlloc::Use())
+    return DlsymAlloc::Callocate(n, size);
   void *p = 0;
   {
     SCOPED_INTERCEPTOR_RAW(calloc, n, size);
@@ -691,8 +699,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)
     invoke_free_hook(p);
   {
@@ -703,9 +711,9 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
   return p;
 }
 
-TSAN_INTERCEPTOR(void *, reallocarray, void *p, uptr n, uptr size) {
-  if (in_symbolizer())
-    return InternalReallocArray(p, n, size);
+TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr n, uptr size) {
+  if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(p))
+    return DlsymAlloc::ReallocArray(p, n, size);
   if (p)
     invoke_free_hook(p);
   {
@@ -717,20 +725,20 @@ TSAN_INTERCEPTOR(void *, reallocarray, void *p, uptr n, uptr size) {
 }
 
 TSAN_INTERCEPTOR(void, free, void *p) {
-  if (p == 0)
+  if (UNLIKELY(!p))
     return;
-  if (in_symbolizer())
-    return InternalFree(p);
+  if (DlsymAlloc::PointerIsMine(p))
+    return DlsymAlloc::Free(p);
   invoke_free_hook(p);
   SCOPED_INTERCEPTOR_RAW(free, p);
   user_free(thr, pc, p);
 }
 
 TSAN_INTERCEPTOR(void, cfree, void *p) {
-  if (p == 0)
+  if (UNLIKELY(!p))
     return;
-  if (in_symbolizer())
-    return InternalFree(p);
+  if (DlsymAlloc::PointerIsMine(p))
+    return DlsymAlloc::Free(p);
   invoke_free_hook(p);
   SCOPED_INTERCEPTOR_RAW(cfree, p);
   user_free(thr, pc, p);
@@ -818,15 +826,15 @@ TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
 
 #if !SANITIZER_APPLE
 TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
-  if (in_symbolizer())
-    return InternalAlloc(sz, nullptr, align);
+  if (DlsymAlloc::Use())
+    return DlsymAlloc::Allocate(sz, align);
   SCOPED_INTERCEPTOR_RAW(aligned_alloc, align, sz);
   return user_aligned_alloc(thr, pc, align, sz);
 }
 
 TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
-  if (in_symbolizer())
-    return InternalAlloc(sz, nullptr, GetPageSizeCached());
+  if (DlsymAlloc::Use())
+    return DlsymAlloc::Allocate(sz, GetPageSizeCached());
   SCOPED_INTERCEPTOR_RAW(valloc, sz);
   return user_valloc(thr, pc, sz);
 }
@@ -834,10 +842,10 @@ TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
 
 #if SANITIZER_LINUX
 TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
-  if (in_symbolizer()) {
+  if (DlsymAlloc::Use()) {
     uptr PageSize = GetPageSizeCached();
     sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
-    return InternalAlloc(sz, nullptr, PageSize);
+    return DlsymAlloc::Allocate(sz, PageSize);
   }
   SCOPED_INTERCEPTOR_RAW(pvalloc, sz);
   return user_pvalloc(thr, pc, sz);
@@ -849,8 +857,8 @@ TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
 
 #if !SANITIZER_APPLE
 TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
-  if (in_symbolizer()) {
-    void *p = InternalAlloc(sz, nullptr, align);
+  if (DlsymAlloc::Use()) {
+    void *p = DlsymAlloc::Allocate(sz, align);
     if (!p)
       return errno_ENOMEM;
     *memptr = p;
diff --git a/compiler-rt/test/sanitizer_common/TestCases/dlsym_alloc.c b/compiler-rt/test/sanitizer_common/TestCases/dlsym_alloc.c
index 7b5b9cf34a90f9..4aa87afe47f4ea 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/dlsym_alloc.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/dlsym_alloc.c
@@ -1,7 +1,5 @@
 // RUN: %clang -O0 %s -o %t && %run %t
 
-// FIXME: TSAN does not use DlsymAlloc.
-// UNSUPPORTED: tsan
 // FIXME: investigate why this fails on macos
 // UNSUPPORTED: darwin
 

Copy link

github-actions bot commented Sep 17, 2024

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff 270b2b588470237729dfd3b6013fe95adfe41480 c8ac0d1cca8cd793246c2b6353f471f0f0f7ce47 --extensions cpp,c -- compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp compiler-rt/test/sanitizer_common/TestCases/dlsym_alloc.c
View the diff from clang-format here.
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index eaa0f6d0de..07930e0c95 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -12,6 +12,9 @@
 // sanitizer_common/sanitizer_common_interceptors.inc
 //===----------------------------------------------------------------------===//
 
+#include <stdarg.h>
+
+#include "interception/interception.h"
 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_errno.h"
@@ -19,22 +22,19 @@
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
-#include "sanitizer_common/sanitizer_placement_new.h"
 #include "sanitizer_common/sanitizer_posix.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 #include "sanitizer_common/sanitizer_tls_get_addr.h"
-#include "interception/interception.h"
+#include "tsan_fd.h"
 #include "tsan_interceptors.h"
 #include "tsan_interface.h"
+#include "tsan_mman.h"
 #include "tsan_platform.h"
-#include "tsan_suppressions.h"
 #include "tsan_rtl.h"
-#include "tsan_mman.h"
-#include "tsan_fd.h"
-
-#include <stdarg.h>
+#include "tsan_suppressions.h"
 
 using namespace __tsan;
 
@@ -258,9 +258,7 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
 // `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 (ctx && !ctx->initialized);
-  }
+  static bool UseImpl() { return (ctx && !ctx->initialized); }
 };
 
 }  // namespace __tsan

Created using spr 1.3.4
@vitalybuka vitalybuka changed the title [tsan] Switch to DlSymAllocator [tsan] Use DlSymAllocator Sep 17, 2024
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
@vitalybuka vitalybuka changed the base branch from users/vitalybuka/spr/main.tsan-switch-to-dlsymallocator to main September 17, 2024 17:52
Created using spr 1.3.4
@vitalybuka vitalybuka merged commit 71a91c1 into main Sep 17, 2024
2 of 5 checks passed
@vitalybuka vitalybuka deleted the users/vitalybuka/spr/tsan-switch-to-dlsymallocator branch September 17, 2024 18:06
hamphet pushed a commit to hamphet/llvm-project that referenced this pull request Sep 18, 2024
`DlSymAllocator` allows early allocations, when
tsan is not yet initialized, e.g. from `dlsym`.

All other sanitizers with interceptors already use
`DlSymAllocator`.

Existing `in_symbolizer()` tsan logic is very similar.
However, we need to keep both as `DlSymAllocator`
does not support large allocations, needed for Symolizer.
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
`DlSymAllocator` allows early allocations, when
tsan is not yet initialized, e.g. from `dlsym`.

All other sanitizers with interceptors already use
`DlSymAllocator`.

Existing `in_symbolizer()` tsan logic is very similar.
However, we need to keep both as `DlSymAllocator`
does not support large allocations, needed for Symolizer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants