[llvm-branch-commits] [lsan] Process non-suspended threads (PR #112807)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Oct 17 18:24:13 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Vitaly Buka (vitalybuka)

<details>
<summary>Changes</summary>

For such threads we have no registers, so no exact
stack range, and no guaranties that stack is mapped
at all.

To avoid crashes on unmapped memory,
 `MemCpyAccessible` copies intersting range into
 temporarily buffer, and we search for pointers there.


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


2 Files Affected:

- (modified) compiler-rt/lib/lsan/lsan_common.cpp (+40) 
- (modified) compiler-rt/lib/lsan/lsan_flags.inc (+2) 


``````````diff
diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp
index 9aed36b96ce929..05f1edae0f05c1 100644
--- a/compiler-rt/lib/lsan/lsan_common.cpp
+++ b/compiler-rt/lib/lsan/lsan_common.cpp
@@ -293,6 +293,27 @@ struct DirectMemoryAccessor {
   void Init(uptr begin, uptr end) {};
   void *LoadPtr(uptr p) const { return *reinterpret_cast<void **>(p); }
 };
+
+struct CopyLoader {
+  void Init(uptr begin, uptr end) {
+    buffer.clear();
+    buffer.resize(end - begin);
+    offset = reinterpret_cast<uptr>(buffer.data()) - begin;
+
+    // Need a partial data?
+    MemCpyAccessible(buffer.data(), reinterpret_cast<void *>(begin),
+                     buffer.size());
+  };
+  void *LoadPtr(uptr p) const {
+    CHECK_LE(p + offset + sizeof(void *),
+             reinterpret_cast<uptr>(buffer.data() + buffer.size()));
+    return *reinterpret_cast<void **>(p + offset);
+  }
+
+ private:
+  uptr offset;
+  InternalMmapVector<char> buffer;
+};
 }  // namespace
 
 // Scans the memory range, looking for byte patterns that point into allocator
@@ -535,6 +556,7 @@ static void ProcessThread(tid_t os_id, uptr sp,
 static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
                            Frontier *frontier, tid_t caller_tid,
                            uptr caller_sp) {
+  InternalMmapVector<tid_t> done_threads;
   InternalMmapVector<uptr> registers;
   InternalMmapVector<Range> extra_ranges;
   for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) {
@@ -559,6 +581,24 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
 
     DirectMemoryAccessor accessor;
     ProcessThread(os_id, sp, registers, extra_ranges, frontier, accessor);
+    done_threads.push_back(os_id);
+  }
+
+  if (flags()->use_detached) {
+    CopyLoader accessor;
+    InternalMmapVector<tid_t> known_threads;
+    GetRunningThreadsLocked(&known_threads);
+    Sort(done_threads.data(), done_threads.size());
+    for (tid_t os_id : known_threads) {
+      registers.clear();
+      extra_ranges.clear();
+
+      uptr i = InternalLowerBound(done_threads, os_id);
+      if (i >= done_threads.size() || done_threads[i] != os_id) {
+        uptr sp = (os_id == caller_tid) ? caller_sp : 0;
+        ProcessThread(os_id, sp, registers, extra_ranges, frontier, accessor);
+      }
+    }
   }
 
   // Add pointers reachable from ThreadContexts
diff --git a/compiler-rt/lib/lsan/lsan_flags.inc b/compiler-rt/lib/lsan/lsan_flags.inc
index c97b021ba5c02f..09d759302fdd5d 100644
--- a/compiler-rt/lib/lsan/lsan_flags.inc
+++ b/compiler-rt/lib/lsan/lsan_flags.inc
@@ -41,6 +41,8 @@ LSAN_FLAG(bool, use_ld_allocations, true,
 LSAN_FLAG(bool, use_unaligned, false, "Consider unaligned pointers valid.")
 LSAN_FLAG(bool, use_poisoned, false,
           "Consider pointers found in poisoned memory to be valid.")
+LSAN_FLAG(bool, use_detached, false,
+          "Scan threads even attaching to them failed.")
 LSAN_FLAG(bool, log_pointers, false, "Debug logging")
 LSAN_FLAG(bool, log_threads, false, "Debug logging")
 LSAN_FLAG(int, tries, 1, "Debug option to repeat leak checking multiple times")

``````````

</details>


https://github.com/llvm/llvm-project/pull/112807


More information about the llvm-branch-commits mailing list