Skip to content

Commit

Permalink
[nfc][lsan] Parametrize ScanForPointers with loader (#112803)
Browse files Browse the repository at this point in the history
Use `DirectLoader` which is equivalent to existing
behaviour of loading pointers directly from memory.
  • Loading branch information
vitalybuka authored Oct 18, 2024
1 parent e3b22dc commit d60fdc1
Showing 1 changed file with 49 additions and 21 deletions.
70 changes: 49 additions & 21 deletions compiler-rt/lib/lsan/lsan_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,23 +288,33 @@ static inline bool MaybeUserPointer(uptr p) {
# endif
}

namespace {
struct DirectMemoryAccessor {
void Init(uptr begin, uptr end) {};
void *LoadPtr(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 Accessor>
void ScanForPointers(uptr begin, uptr end, Frontier *frontier,
const char *region_type, ChunkTag tag,
Accessor &accessor) {
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);
accessor.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 = accessor.LoadPtr(pp);
# if SANITIZER_APPLE
p = TransformPointer(p);
# endif
Expand Down Expand Up @@ -339,6 +349,12 @@ void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
}
}

void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
const char *region_type, ChunkTag tag) {
DirectMemoryAccessor accessor;
ScanForPointers(begin, end, frontier, region_type, tag, accessor);
}

// Scans a global range for pointers
void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
uptr allocator_begin = 0, allocator_end = 0;
Expand All @@ -356,14 +372,21 @@ void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
}
}

void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
Frontier *frontier) {
template <class Accessor>
void ScanExtraStack(const InternalMmapVector<Range> &ranges, Frontier *frontier,
Accessor &accessor) {
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, accessor);
}
}

void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
Frontier *frontier) {
DirectMemoryAccessor accessor;
ScanExtraStack(ranges, frontier, accessor);
}

# if SANITIZER_FUCHSIA

// Fuchsia handles all threads together with its own callback.
Expand Down Expand Up @@ -399,10 +422,11 @@ static void ProcessThreadRegistry(Frontier *frontier) {
}

// Scans thread data (stacks and TLS) for heap pointers.
template <class Accessor>
static void ProcessThread(tid_t os_id, uptr sp,
const InternalMmapVector<uptr> &registers,
InternalMmapVector<Range> &extra_ranges,
Frontier *frontier) {
Frontier *frontier, Accessor &accessor) {
// `extra_ranges` is outside of the function and the loop to reused mapped
// memory.
CHECK(extra_ranges.empty());
Expand All @@ -426,8 +450,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, accessor);
}

if (flags()->use_stacks) {
Expand All @@ -451,9 +475,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,
accessor);
GetThreadExtraStackRangesLocked(os_id, &extra_ranges);
ScanExtraStackRanges(extra_ranges, frontier);
ScanExtraStack(extra_ranges, frontier, accessor);
}

if (flags()->use_tls) {
Expand All @@ -463,21 +488,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,
accessor);
} else {
if (tls_begin < cache_begin)
ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
kReachable);
ScanForPointers(tls_begin, cache_begin, frontier, "TLS", kReachable,
accessor);
if (tls_end > cache_end)
ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
ScanForPointers(cache_end, tls_end, frontier, "TLS", kReachable,
accessor);
}
}
# 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, accessor);
};

// FIXME: There might be a race-condition here (and in Bionic) if the
Expand All @@ -492,8 +519,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,
accessor);
}
});
} else {
Expand Down Expand Up @@ -530,7 +557,8 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
if (os_id == caller_tid)
sp = caller_sp;

ProcessThread(os_id, sp, registers, extra_ranges, frontier);
DirectMemoryAccessor accessor;
ProcessThread(os_id, sp, registers, extra_ranges, frontier, accessor);
}

// Add pointers reachable from ThreadContexts
Expand Down

0 comments on commit d60fdc1

Please sign in to comment.