[llvm-branch-commits] [compiler-rt] dd922bc - [LSan] Introduce a callback mechanism to allow adding data reachable from ThreadContexts to the frontier.

Dan Liew via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jan 22 19:31:39 PST 2021


Author: Dan Liew
Date: 2021-01-22T19:26:02-08:00
New Revision: dd922bc2a62163cef442646974324943c551725e

URL: https://github.com/llvm/llvm-project/commit/dd922bc2a62163cef442646974324943c551725e
DIFF: https://github.com/llvm/llvm-project/commit/dd922bc2a62163cef442646974324943c551725e.diff

LOG: [LSan] Introduce a callback mechanism to allow adding data reachable from ThreadContexts to the frontier.

This mechanism is intended to provide a way to treat the `arg` pointer
of a created (but not yet started) thread as reachable. In future
patches this will be implemented in `GetAdditionalThreadContextPtrs`.

A separate implementation of `GetAdditionalThreadContextPtrs` exists
for ASan and LSan runtimes because they need to be implemented
differently in future patches.

rdar://problem/63537240

Differential Revision: https://reviews.llvm.org/D95183

Added: 
    

Modified: 
    compiler-rt/lib/asan/asan_allocator.cpp
    compiler-rt/lib/lsan/lsan_allocator.cpp
    compiler-rt/lib/lsan/lsan_common.cpp
    compiler-rt/lib/lsan/lsan_common.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 58b496a3ca4b..4da697835870 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -1183,6 +1183,16 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
   m->lsan_tag = __lsan::kIgnored;
   return kIgnoreObjectSuccess;
 }
+
+void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) {
+  // This function can be used to treat memory reachable from `tctx` as live.
+  // This is useful for threads that have been created but not yet started.
+
+  // This is currently a no-op because the ASan `pthread_create()` interceptor
+  // blocks until the child thread starts which keeps the thread's `arg` pointer
+  // live.
+}
+
 }  // namespace __lsan
 
 // ---------------------- Interface ---------------- {{{1

diff  --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp
index d86c3921395c..70422957e6f3 100644
--- a/compiler-rt/lib/lsan/lsan_allocator.cpp
+++ b/compiler-rt/lib/lsan/lsan_allocator.cpp
@@ -309,6 +309,16 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
     return kIgnoreObjectInvalid;
   }
 }
+
+void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) {
+  // This function can be used to treat memory reachable from `tctx` as live.
+  // This is useful for threads that have been created but not yet started.
+
+  // This is currently a no-op because the LSan `pthread_create()` interceptor
+  // blocks until the child thread starts which keeps the thread's `arg` pointer
+  // live.
+}
+
 } // namespace __lsan
 
 using namespace __lsan;

diff  --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp
index ab7500ce32cf..d5b4132b24d5 100644
--- a/compiler-rt/lib/lsan/lsan_common.cpp
+++ b/compiler-rt/lib/lsan/lsan_common.cpp
@@ -253,6 +253,27 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_iterate_dynamic_tls(
     pid_t, void (*cb)(void *, void *, uptr, void *), void *);
 #endif
 
+static void ProcessThreadRegistry(Frontier *frontier) {
+  InternalMmapVector<uptr> ptrs;
+  GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+      GetAdditionalThreadContextPtrs, &ptrs);
+
+  for (uptr i = 0; i < ptrs.size(); ++i) {
+    void *ptr = reinterpret_cast<void *>(ptrs[i]);
+    uptr chunk = PointsIntoChunk(ptr);
+    if (!chunk)
+      continue;
+    LsanMetadata m(chunk);
+    if (!m.allocated())
+      continue;
+
+    // Mark as reachable and add to frontier.
+    LOG_POINTERS("Treating pointer %p from ThreadContext as reachable\n", ptr);
+    m.set_tag(kReachable);
+    frontier->push_back(chunk);
+  }
+}
+
 // Scans thread data (stacks and TLS) for heap pointers.
 static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
                            Frontier *frontier) {
@@ -364,6 +385,9 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
 #endif
     }
   }
+
+  // Add pointers reachable from ThreadContexts
+  ProcessThreadRegistry(frontier);
 }
 
 #endif  // SANITIZER_FUCHSIA

diff  --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h
index 05f380d4a5fa..b0ae6f020b63 100644
--- a/compiler-rt/lib/lsan/lsan_common.h
+++ b/compiler-rt/lib/lsan/lsan_common.h
@@ -50,6 +50,7 @@
 namespace __sanitizer {
 class FlagParser;
 class ThreadRegistry;
+class ThreadContextBase;
 struct DTLS;
 }
 
@@ -142,6 +143,7 @@ InternalMmapVector<RootRegion> const *GetRootRegions();
 void ScanRootRegion(Frontier *frontier, RootRegion const &region,
                     uptr region_begin, uptr region_end, bool is_readable);
 void ForEachExtraStackRangeCb(uptr begin, uptr end, void* arg);
+void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs);
 // Run stoptheworld while holding any platform-specific locks, as well as the
 // allocator and thread registry locks.
 void LockStuffAndStopTheWorld(StopTheWorldCallback callback,


        


More information about the llvm-branch-commits mailing list