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

Dan Liew via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 21 16:18:29 PST 2021


delcypher created this revision.
delcypher added reviewers: kubamracek, yln, kcc, dvyukov, eugenis, vitalybuka, cryptoad, earthdok.
delcypher requested review of this revision.
Herald added a project: Sanitizers.
Herald added a subscriber: Sanitizers.

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 `ForEachRegisteredThreadContextCb`.

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

rdar://problem/63537240


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95183

Files:
  compiler-rt/lib/asan/asan_allocator.cpp
  compiler-rt/lib/lsan/lsan_common.cpp
  compiler-rt/lib/lsan/lsan_common.h
  compiler-rt/lib/lsan/lsan_thread.cpp


Index: compiler-rt/lib/lsan/lsan_thread.cpp
===================================================================
--- compiler-rt/lib/lsan/lsan_thread.cpp
+++ compiler-rt/lib/lsan/lsan_thread.cpp
@@ -112,4 +112,13 @@
   return thread_registry;
 }
 
+void ForEachRegisteredThreadContextCb(ThreadContextBase *tctx, void *arg) {
+  // 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
Index: compiler-rt/lib/lsan/lsan_common.h
===================================================================
--- compiler-rt/lib/lsan/lsan_common.h
+++ compiler-rt/lib/lsan/lsan_common.h
@@ -20,6 +20,7 @@
 #include "sanitizer_common/sanitizer_platform.h"
 #include "sanitizer_common/sanitizer_stoptheworld.h"
 #include "sanitizer_common/sanitizer_symbolizer.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
 
 // LeakSanitizer relies on some Glibc's internals (e.g. TLS machinery) on Linux.
 // Also, LSan doesn't like 32 bit architectures
@@ -142,6 +143,7 @@
 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 ForEachRegisteredThreadContextCb(ThreadContextBase *tctx, void *arg);
 // Run stoptheworld while holding any platform-specific locks, as well as the
 // allocator and thread registry locks.
 void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
Index: compiler-rt/lib/lsan/lsan_common.cpp
===================================================================
--- compiler-rt/lib/lsan/lsan_common.cpp
+++ compiler-rt/lib/lsan/lsan_common.cpp
@@ -520,6 +520,11 @@
   ForEachChunk(MarkInvalidPCCb, &arg);
 }
 
+void ProcessThreadRegistry(Frontier *frontier) {
+  GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+      ForEachRegisteredThreadContextCb, frontier);
+}
+
 // Sets the appropriate tag on each chunk.
 static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads,
                               Frontier *frontier) {
@@ -532,6 +537,7 @@
   ForEachChunk(CollectIgnoredCb, frontier);
   ProcessGlobalRegions(frontier);
   ProcessThreads(suspended_threads, frontier);
+  ProcessThreadRegistry(frontier);
   ProcessRootRegions(frontier);
   FloodFillTag(frontier, kReachable);
 
Index: compiler-rt/lib/asan/asan_allocator.cpp
===================================================================
--- compiler-rt/lib/asan/asan_allocator.cpp
+++ compiler-rt/lib/asan/asan_allocator.cpp
@@ -1124,6 +1124,15 @@
   return 0;
 }
 
+void ForEachRegisteredThreadContextCb(ThreadContextBase *tctx, void *arg) {
+  // 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.
+}
+
 uptr GetUserBegin(uptr chunk) {
   __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk);
   return m ? m->Beg() : 0;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D95183.318348.patch
Type: text/x-patch
Size: 3384 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210122/a12de637/attachment.bin>


More information about the llvm-commits mailing list