llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-compiler-rt-sanitizer Author: Vitaly Buka (vitalybuka) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/112610.diff 1 Files Affected: - (modified) compiler-rt/lib/lsan/lsan_common.cpp (+108-101) ``````````diff diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index a1a15bf98a1183..721db7872cce83 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -399,6 +399,112 @@ static void ProcessThreadRegistry(Frontier *frontier) { } // Scans thread data (stacks and TLS) for heap pointers. +static void ProcessThread(tid_t os_id, uptr sp, + const InternalMmapVector<uptr> ®isters, + InternalMmapVector<Range> &extra_ranges, + Frontier *frontier) { + // `extra_ranges` is outside of the function and the loop to reused mapped + // memory. + CHECK(extra_ranges.empty()); + LOG_THREADS("Processing thread %llu.\n", os_id); + uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end; + DTLS *dtls; + bool thread_found = + GetThreadRangesLocked(os_id, &stack_begin, &stack_end, &tls_begin, + &tls_end, &cache_begin, &cache_end, &dtls); + if (!thread_found) { + // If a thread can't be found in the thread registry, it's probably in the + // process of destruction. Log this event and move on. + LOG_THREADS("Thread %llu not found in registry.\n", os_id); + return; + } + + if (!sp) + sp = stack_begin; + + if (flags()->use_registers) { + 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); + } + + if (flags()->use_stacks) { + LOG_THREADS("Stack at %p-%p (SP = %p).\n", (void *)stack_begin, + (void *)stack_end, (void *)sp); + if (sp < stack_begin || sp >= stack_end) { + // SP is outside the recorded stack range (e.g. the thread is running a + // signal handler on alternate stack, or swapcontext was used). + // Again, consider the entire stack range to be reachable. + LOG_THREADS("WARNING: stack pointer not in stack range.\n"); + uptr page_size = GetPageSizeCached(); + int skipped = 0; + while (stack_begin < stack_end && + !IsAccessibleMemoryRange(stack_begin, 1)) { + skipped++; + stack_begin += page_size; + } + LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n", skipped, + (void *)stack_begin, (void *)stack_end); + } else { + // Shrink the stack range to ignore out-of-scope values. + stack_begin = sp; + } + ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", kReachable); + GetThreadExtraStackRangesLocked(os_id, &extra_ranges); + ScanExtraStackRanges(extra_ranges, frontier); + } + + if (flags()->use_tls) { + if (tls_begin) { + LOG_THREADS("TLS at %p-%p.\n", (void *)tls_begin, (void *)tls_end); + // If the tls and cache ranges don't overlap, scan full tls range, + // 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); + } else { + if (tls_begin < cache_begin) + ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", + kReachable); + if (tls_end > cache_end) + ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable); + } + } +# if SANITIZER_ANDROID + auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/, + void *arg) -> void { + ScanRangeForPointers( + reinterpret_cast<uptr>(dtls_begin), reinterpret_cast<uptr>(dtls_end), + reinterpret_cast<Frontier *>(arg), "DTLS", kReachable); + }; + + // FIXME: There might be a race-condition here (and in Bionic) if the + // thread is suspended in the middle of updating its DTLS. IOWs, we + // could scan already freed memory. (probably fine for now) + __libc_iterate_dynamic_tls(os_id, cb, frontier); +# else + if (dtls && !DTLSInDestruction(dtls)) { + ForEachDVT(dtls, [&](const DTLS::DTV &dtv, int id) { + uptr dtls_beg = dtv.beg; + uptr dtls_end = dtls_beg + dtv.size; + 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); + } + }); + } else { + // We are handling a thread with DTLS under destruction. Log about + // this and continue. + LOG_THREADS("Thread %llu has DTLS under destruction.\n", os_id); + } +# endif + } +} + static void ProcessThreads(SuspendedThreadsList const &suspended_threads, Frontier *frontier, tid_t caller_tid, uptr caller_sp) { @@ -408,7 +514,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, registers.clear(); extra_ranges.clear(); - const tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i)); + const tid_t os_id = suspended_threads.GetThreadID(i); uptr sp = 0; PtraceRegistersStatus have_registers = suspended_threads.GetRegistersAndSP(i, ®isters, &sp); @@ -421,109 +527,10 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, sp = 0; } - LOG_THREADS("Processing thread %llu.\n", os_id); - uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end; - DTLS *dtls; - bool thread_found = - GetThreadRangesLocked(os_id, &stack_begin, &stack_end, &tls_begin, - &tls_end, &cache_begin, &cache_end, &dtls); - if (!thread_found) { - // If a thread can't be found in the thread registry, it's probably in the - // process of destruction. Log this event and move on. - LOG_THREADS("Thread %llu not found in registry.\n", os_id); - continue; - } - if (os_id == caller_tid) sp = caller_sp; - if (!sp) - sp = stack_begin; - - if (flags()->use_registers && have_registers) { - 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); - } - - if (flags()->use_stacks) { - LOG_THREADS("Stack at %p-%p (SP = %p).\n", (void *)stack_begin, - (void *)stack_end, (void *)sp); - if (sp < stack_begin || sp >= stack_end) { - // SP is outside the recorded stack range (e.g. the thread is running a - // signal handler on alternate stack, or swapcontext was used). - // Again, consider the entire stack range to be reachable. - LOG_THREADS("WARNING: stack pointer not in stack range.\n"); - uptr page_size = GetPageSizeCached(); - int skipped = 0; - while (stack_begin < stack_end && - !IsAccessibleMemoryRange(stack_begin, 1)) { - skipped++; - stack_begin += page_size; - } - LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n", - skipped, (void *)stack_begin, (void *)stack_end); - } else { - // Shrink the stack range to ignore out-of-scope values. - stack_begin = sp; - } - ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", - kReachable); - GetThreadExtraStackRangesLocked(os_id, &extra_ranges); - ScanExtraStackRanges(extra_ranges, frontier); - } - - if (flags()->use_tls) { - if (tls_begin) { - LOG_THREADS("TLS at %p-%p.\n", (void *)tls_begin, (void *)tls_end); - // If the tls and cache ranges don't overlap, scan full tls range, - // 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); - } else { - if (tls_begin < cache_begin) - ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", - kReachable); - if (tls_end > cache_end) - ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", - kReachable); - } - } -# if SANITIZER_ANDROID - auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/, - void *arg) -> void { - ScanRangeForPointers(reinterpret_cast<uptr>(dtls_begin), - reinterpret_cast<uptr>(dtls_end), - reinterpret_cast<Frontier *>(arg), "DTLS", - kReachable); - }; - - // FIXME: There might be a race-condition here (and in Bionic) if the - // thread is suspended in the middle of updating its DTLS. IOWs, we - // could scan already freed memory. (probably fine for now) - __libc_iterate_dynamic_tls(os_id, cb, frontier); -# else - if (dtls && !DTLSInDestruction(dtls)) { - ForEachDVT(dtls, [&](const DTLS::DTV &dtv, int id) { - uptr dtls_beg = dtv.beg; - uptr dtls_end = dtls_beg + dtv.size; - 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); - } - }); - } else { - // We are handling a thread with DTLS under destruction. Log about - // this and continue. - LOG_THREADS("Thread %llu has DTLS under destruction.\n", os_id); - } -# endif - } + ProcessThread(os_id, sp, registers, extra_ranges, frontier); } // Add pointers reachable from ThreadContexts `````````` </details> https://github.com/llvm/llvm-project/pull/112610 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits