Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 48 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,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
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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());
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
Loading