Skip to content

[nfc][lsan] Parametrize ScanForPointers with loader #112803

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

Conversation

vitalybuka
Copy link
Collaborator

Use DirectLoader which is equivalent to existing
behaviour of loading pointers directly from memory.

Created using spr 1.3.4
@llvmbot
Copy link
Member

llvmbot commented Oct 18, 2024

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

Author: Vitaly Buka (vitalybuka)

Changes

Use DirectLoader which is equivalent to existing
behaviour of loading pointers directly from memory.


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

1 Files Affected:

  • (modified) compiler-rt/lib/lsan/lsan_common.cpp (+48-21)
diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp
index 721db7872cce83..79da3e132ecc8d 100644
--- a/compiler-rt/lib/lsan/lsan_common.cpp
+++ b/compiler-rt/lib/lsan/lsan_common.cpp
@@ -288,23 +288,32 @@ static inline bool MaybeUserPointer(uptr p) {
 #  endif
 }
 
+namespace {
+struct DirectLoader {
+  void Init(uptr begin, uptr end) {};
+  void *operator()(uptr p) const { return *reinterpret_cast<void **>(p); }
+};
+}  // namespace
+
 // Scans the memory range, looking for byte patterns that point into allocator
 // chunks. Marks those chunks with |tag| and adds them to |frontier|.
 // There are two usage modes for this function: finding reachable chunks
 // (|tag| = kReachable) and finding indirectly leaked chunks
 // (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
 // so |frontier| = 0.
-void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
-                          const char *region_type, ChunkTag tag) {
+template <class S>
+void ScanForPointers(uptr begin, uptr end, Frontier *frontier,
+                     const char *region_type, ChunkTag tag, S &scanner) {
   CHECK(tag == kReachable || tag == kIndirectlyLeaked);
   const uptr alignment = flags()->pointer_alignment();
   LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, (void *)begin,
                (void *)end);
+  scanner.Init(begin, end);
   uptr pp = begin;
   if (pp % alignment)
     pp = pp + alignment - pp % alignment;
   for (; pp + sizeof(void *) <= end; pp += alignment) {
-    void *p = *reinterpret_cast<void **>(pp);
+    void *p = scanner(pp);
 #  if SANITIZER_APPLE
     p = TransformPointer(p);
 #  endif
@@ -339,6 +348,12 @@ void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
   }
 }
 
+void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
+                          const char *region_type, ChunkTag tag) {
+  DirectLoader scanner;
+  ScanForPointers(begin, end, frontier, region_type, tag, scanner);
+}
+
 // Scans a global range for pointers
 void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
   uptr allocator_begin = 0, allocator_end = 0;
@@ -356,14 +371,21 @@ void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
   }
 }
 
-void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
-                          Frontier *frontier) {
+template <class S>
+void ScanExtraStack(const InternalMmapVector<Range> &ranges, Frontier *frontier,
+                    S &scanner) {
   for (uptr i = 0; i < ranges.size(); i++) {
-    ScanRangeForPointers(ranges[i].begin, ranges[i].end, frontier, "FAKE STACK",
-                         kReachable);
+    ScanForPointers(ranges[i].begin, ranges[i].end, frontier, "FAKE STACK",
+                    kReachable, scanner);
   }
 }
 
+void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
+                          Frontier *frontier) {
+  DirectLoader scanner;
+  ScanExtraStack(ranges, frontier, scanner);
+}
+
 #  if SANITIZER_FUCHSIA
 
 // Fuchsia handles all threads together with its own callback.
@@ -399,10 +421,11 @@ static void ProcessThreadRegistry(Frontier *frontier) {
 }
 
 // Scans thread data (stacks and TLS) for heap pointers.
+template <class S>
 static void ProcessThread(tid_t os_id, uptr sp,
                           const InternalMmapVector<uptr> &registers,
                           InternalMmapVector<Range> &extra_ranges,
-                          Frontier *frontier) {
+                          Frontier *frontier, S &scanner) {
   // `extra_ranges` is outside of the function and the loop to reused mapped
   // memory.
   CHECK(extra_ranges.empty());
@@ -426,8 +449,8 @@ static void ProcessThread(tid_t os_id, uptr sp,
     uptr registers_begin = reinterpret_cast<uptr>(registers.data());
     uptr registers_end =
         reinterpret_cast<uptr>(registers.data() + registers.size());
-    ScanRangeForPointers(registers_begin, registers_end, frontier, "REGISTERS",
-                         kReachable);
+    ScanForPointers(registers_begin, registers_end, frontier, "REGISTERS",
+                    kReachable, scanner);
   }
 
   if (flags()->use_stacks) {
@@ -451,9 +474,10 @@ static void ProcessThread(tid_t os_id, uptr sp,
       // Shrink the stack range to ignore out-of-scope values.
       stack_begin = sp;
     }
-    ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", kReachable);
+    ScanForPointers(stack_begin, stack_end, frontier, "STACK", kReachable,
+                    scanner);
     GetThreadExtraStackRangesLocked(os_id, &extra_ranges);
-    ScanExtraStackRanges(extra_ranges, frontier);
+    ScanExtraStack(extra_ranges, frontier, scanner);
   }
 
   if (flags()->use_tls) {
@@ -463,21 +487,23 @@ static void ProcessThread(tid_t os_id, uptr sp,
       // otherwise, only scan the non-overlapping portions
       if (cache_begin == cache_end || tls_end < cache_begin ||
           tls_begin > cache_end) {
-        ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
+        ScanForPointers(tls_begin, tls_end, frontier, "TLS", kReachable,
+                        scanner);
       } else {
         if (tls_begin < cache_begin)
-          ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
-                               kReachable);
+          ScanForPointers(tls_begin, cache_begin, frontier, "TLS", kReachable,
+                          scanner);
         if (tls_end > cache_end)
-          ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
+          ScanForPointers(cache_end, tls_end, frontier, "TLS", kReachable,
+                          scanner);
       }
     }
 #    if SANITIZER_ANDROID
     auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/,
                    void *arg) -> void {
-      ScanRangeForPointers(
+      ScanForPointers(
           reinterpret_cast<uptr>(dtls_begin), reinterpret_cast<uptr>(dtls_end),
-          reinterpret_cast<Frontier *>(arg), "DTLS", kReachable);
+          reinterpret_cast<Frontier *>(arg), "DTLS", kReachable, scanner);
     };
 
     // FIXME: There might be a race-condition here (and in Bionic) if the
@@ -492,8 +518,8 @@ static void ProcessThread(tid_t os_id, uptr sp,
         if (dtls_beg < dtls_end) {
           LOG_THREADS("DTLS %d at %p-%p.\n", id, (void *)dtls_beg,
                       (void *)dtls_end);
-          ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS",
-                               kReachable);
+          ScanForPointers(dtls_beg, dtls_end, frontier, "DTLS", kReachable,
+                          scanner);
         }
       });
     } else {
@@ -530,7 +556,8 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
     if (os_id == caller_tid)
       sp = caller_sp;
 
-    ProcessThread(os_id, sp, registers, extra_ranges, frontier);
+    DirectLoader scanner;
+    ProcessThread(os_id, sp, registers, extra_ranges, frontier, scanner);
   }
 
   // Add pointers reachable from ThreadContexts

Created using spr 1.3.4
@vitalybuka vitalybuka requested a review from fmayer October 18, 2024 01:14
Created using spr 1.3.4
@vitalybuka vitalybuka merged commit d60fdc1 into main Oct 18, 2024
7 checks passed
@vitalybuka vitalybuka deleted the users/vitalybuka/spr/nfclsan-parametrize-scanforpointers-with-loader branch October 18, 2024 18:42
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