Skip to content

Commit 3142dff

Browse files
[nfc][lsan] Extract significant part of the loop into a function (#112610)
Co-authored-by: thetruestblue <[email protected]>
1 parent 927af63 commit 3142dff

File tree

1 file changed

+108
-101
lines changed

1 file changed

+108
-101
lines changed

compiler-rt/lib/lsan/lsan_common.cpp

Lines changed: 108 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,112 @@ static void ProcessThreadRegistry(Frontier *frontier) {
399399
}
400400

401401
// Scans thread data (stacks and TLS) for heap pointers.
402+
static void ProcessThread(tid_t os_id, uptr sp,
403+
const InternalMmapVector<uptr> &registers,
404+
InternalMmapVector<Range> &extra_ranges,
405+
Frontier *frontier) {
406+
// `extra_ranges` is outside of the function and the loop to reused mapped
407+
// memory.
408+
CHECK(extra_ranges.empty());
409+
LOG_THREADS("Processing thread %llu.\n", os_id);
410+
uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
411+
DTLS *dtls;
412+
bool thread_found =
413+
GetThreadRangesLocked(os_id, &stack_begin, &stack_end, &tls_begin,
414+
&tls_end, &cache_begin, &cache_end, &dtls);
415+
if (!thread_found) {
416+
// If a thread can't be found in the thread registry, it's probably in the
417+
// process of destruction. Log this event and move on.
418+
LOG_THREADS("Thread %llu not found in registry.\n", os_id);
419+
return;
420+
}
421+
422+
if (!sp)
423+
sp = stack_begin;
424+
425+
if (flags()->use_registers) {
426+
uptr registers_begin = reinterpret_cast<uptr>(registers.data());
427+
uptr registers_end =
428+
reinterpret_cast<uptr>(registers.data() + registers.size());
429+
ScanRangeForPointers(registers_begin, registers_end, frontier, "REGISTERS",
430+
kReachable);
431+
}
432+
433+
if (flags()->use_stacks) {
434+
LOG_THREADS("Stack at %p-%p (SP = %p).\n", (void *)stack_begin,
435+
(void *)stack_end, (void *)sp);
436+
if (sp < stack_begin || sp >= stack_end) {
437+
// SP is outside the recorded stack range (e.g. the thread is running a
438+
// signal handler on alternate stack, or swapcontext was used).
439+
// Again, consider the entire stack range to be reachable.
440+
LOG_THREADS("WARNING: stack pointer not in stack range.\n");
441+
uptr page_size = GetPageSizeCached();
442+
int skipped = 0;
443+
while (stack_begin < stack_end &&
444+
!IsAccessibleMemoryRange(stack_begin, 1)) {
445+
skipped++;
446+
stack_begin += page_size;
447+
}
448+
LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n", skipped,
449+
(void *)stack_begin, (void *)stack_end);
450+
} else {
451+
// Shrink the stack range to ignore out-of-scope values.
452+
stack_begin = sp;
453+
}
454+
ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", kReachable);
455+
GetThreadExtraStackRangesLocked(os_id, &extra_ranges);
456+
ScanExtraStackRanges(extra_ranges, frontier);
457+
}
458+
459+
if (flags()->use_tls) {
460+
if (tls_begin) {
461+
LOG_THREADS("TLS at %p-%p.\n", (void *)tls_begin, (void *)tls_end);
462+
// If the tls and cache ranges don't overlap, scan full tls range,
463+
// otherwise, only scan the non-overlapping portions
464+
if (cache_begin == cache_end || tls_end < cache_begin ||
465+
tls_begin > cache_end) {
466+
ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
467+
} else {
468+
if (tls_begin < cache_begin)
469+
ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
470+
kReachable);
471+
if (tls_end > cache_end)
472+
ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
473+
}
474+
}
475+
# if SANITIZER_ANDROID
476+
auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/,
477+
void *arg) -> void {
478+
ScanRangeForPointers(
479+
reinterpret_cast<uptr>(dtls_begin), reinterpret_cast<uptr>(dtls_end),
480+
reinterpret_cast<Frontier *>(arg), "DTLS", kReachable);
481+
};
482+
483+
// FIXME: There might be a race-condition here (and in Bionic) if the
484+
// thread is suspended in the middle of updating its DTLS. IOWs, we
485+
// could scan already freed memory. (probably fine for now)
486+
__libc_iterate_dynamic_tls(os_id, cb, frontier);
487+
# else
488+
if (dtls && !DTLSInDestruction(dtls)) {
489+
ForEachDVT(dtls, [&](const DTLS::DTV &dtv, int id) {
490+
uptr dtls_beg = dtv.beg;
491+
uptr dtls_end = dtls_beg + dtv.size;
492+
if (dtls_beg < dtls_end) {
493+
LOG_THREADS("DTLS %d at %p-%p.\n", id, (void *)dtls_beg,
494+
(void *)dtls_end);
495+
ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS",
496+
kReachable);
497+
}
498+
});
499+
} else {
500+
// We are handling a thread with DTLS under destruction. Log about
501+
// this and continue.
502+
LOG_THREADS("Thread %llu has DTLS under destruction.\n", os_id);
503+
}
504+
# endif
505+
}
506+
}
507+
402508
static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
403509
Frontier *frontier, tid_t caller_tid,
404510
uptr caller_sp) {
@@ -408,7 +514,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
408514
registers.clear();
409515
extra_ranges.clear();
410516

411-
const tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i));
517+
const tid_t os_id = suspended_threads.GetThreadID(i);
412518
uptr sp = 0;
413519
PtraceRegistersStatus have_registers =
414520
suspended_threads.GetRegistersAndSP(i, &registers, &sp);
@@ -421,109 +527,10 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
421527
sp = 0;
422528
}
423529

424-
LOG_THREADS("Processing thread %llu.\n", os_id);
425-
uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
426-
DTLS *dtls;
427-
bool thread_found =
428-
GetThreadRangesLocked(os_id, &stack_begin, &stack_end, &tls_begin,
429-
&tls_end, &cache_begin, &cache_end, &dtls);
430-
if (!thread_found) {
431-
// If a thread can't be found in the thread registry, it's probably in the
432-
// process of destruction. Log this event and move on.
433-
LOG_THREADS("Thread %llu not found in registry.\n", os_id);
434-
continue;
435-
}
436-
437530
if (os_id == caller_tid)
438531
sp = caller_sp;
439532

440-
if (!sp)
441-
sp = stack_begin;
442-
443-
if (flags()->use_registers && have_registers) {
444-
uptr registers_begin = reinterpret_cast<uptr>(registers.data());
445-
uptr registers_end =
446-
reinterpret_cast<uptr>(registers.data() + registers.size());
447-
ScanRangeForPointers(registers_begin, registers_end, frontier,
448-
"REGISTERS", kReachable);
449-
}
450-
451-
if (flags()->use_stacks) {
452-
LOG_THREADS("Stack at %p-%p (SP = %p).\n", (void *)stack_begin,
453-
(void *)stack_end, (void *)sp);
454-
if (sp < stack_begin || sp >= stack_end) {
455-
// SP is outside the recorded stack range (e.g. the thread is running a
456-
// signal handler on alternate stack, or swapcontext was used).
457-
// Again, consider the entire stack range to be reachable.
458-
LOG_THREADS("WARNING: stack pointer not in stack range.\n");
459-
uptr page_size = GetPageSizeCached();
460-
int skipped = 0;
461-
while (stack_begin < stack_end &&
462-
!IsAccessibleMemoryRange(stack_begin, 1)) {
463-
skipped++;
464-
stack_begin += page_size;
465-
}
466-
LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n",
467-
skipped, (void *)stack_begin, (void *)stack_end);
468-
} else {
469-
// Shrink the stack range to ignore out-of-scope values.
470-
stack_begin = sp;
471-
}
472-
ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
473-
kReachable);
474-
GetThreadExtraStackRangesLocked(os_id, &extra_ranges);
475-
ScanExtraStackRanges(extra_ranges, frontier);
476-
}
477-
478-
if (flags()->use_tls) {
479-
if (tls_begin) {
480-
LOG_THREADS("TLS at %p-%p.\n", (void *)tls_begin, (void *)tls_end);
481-
// If the tls and cache ranges don't overlap, scan full tls range,
482-
// otherwise, only scan the non-overlapping portions
483-
if (cache_begin == cache_end || tls_end < cache_begin ||
484-
tls_begin > cache_end) {
485-
ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
486-
} else {
487-
if (tls_begin < cache_begin)
488-
ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
489-
kReachable);
490-
if (tls_end > cache_end)
491-
ScanRangeForPointers(cache_end, tls_end, frontier, "TLS",
492-
kReachable);
493-
}
494-
}
495-
# if SANITIZER_ANDROID
496-
auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/,
497-
void *arg) -> void {
498-
ScanRangeForPointers(reinterpret_cast<uptr>(dtls_begin),
499-
reinterpret_cast<uptr>(dtls_end),
500-
reinterpret_cast<Frontier *>(arg), "DTLS",
501-
kReachable);
502-
};
503-
504-
// FIXME: There might be a race-condition here (and in Bionic) if the
505-
// thread is suspended in the middle of updating its DTLS. IOWs, we
506-
// could scan already freed memory. (probably fine for now)
507-
__libc_iterate_dynamic_tls(os_id, cb, frontier);
508-
# else
509-
if (dtls && !DTLSInDestruction(dtls)) {
510-
ForEachDVT(dtls, [&](const DTLS::DTV &dtv, int id) {
511-
uptr dtls_beg = dtv.beg;
512-
uptr dtls_end = dtls_beg + dtv.size;
513-
if (dtls_beg < dtls_end) {
514-
LOG_THREADS("DTLS %d at %p-%p.\n", id, (void *)dtls_beg,
515-
(void *)dtls_end);
516-
ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS",
517-
kReachable);
518-
}
519-
});
520-
} else {
521-
// We are handling a thread with DTLS under destruction. Log about
522-
// this and continue.
523-
LOG_THREADS("Thread %llu has DTLS under destruction.\n", os_id);
524-
}
525-
# endif
526-
}
533+
ProcessThread(os_id, sp, registers, extra_ranges, frontier);
527534
}
528535

529536
// Add pointers reachable from ThreadContexts

0 commit comments

Comments
 (0)