diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp index 30ba812afc4b0..f1b2a157c3538 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp @@ -43,10 +43,47 @@ void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { trace_buffer[0] = pc; } -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wframe-larger-than=" -#endif +PVOID CALLBACK FallbackFunctionTableAccess(HANDLE hProcess, + DWORD64 dwAddrBase) { + // First try DbgHelp's function. + if (PVOID pResult = + __sanitizer::SymFunctionTableAccess64(hProcess, dwAddrBase)) { + return pResult; + } + + // Fall back to RtlLookupFunctionEntry for dynamic code. + // Function registered with RtlAddFunctionTable is not necessarily registered + // with DbgHelp, so this is required to cover some edge cases (e.g. JIT + // compilers can use Rtl* functions). +# if SANITIZER_WINDOWS64 + DWORD64 dw64ImageBase = 0; + return RtlLookupFunctionEntry(dwAddrBase, &dw64ImageBase, nullptr); +# else + return nullptr; +# endif +} + +DWORD64 CALLBACK FallbackGetModuleBase(HANDLE hProcess, DWORD64 dwAddr) { + if (DWORD64 dwResult = __sanitizer::SymGetModuleBase64(hProcess, dwAddr)) { + return dwResult; + } + + // Both GetModuleBase and FunctionTableAccess must provide this fallback, + // otherwise dynamic functions won't be properly unwound. +# if SANITIZER_WINDOWS64 + DWORD64 dw64ImageBase = 0; + if (RtlLookupFunctionEntry(dwAddr, &dw64ImageBase, nullptr)) { + return dw64ImageBase; + } +# endif + + return 0; +} + +# ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wframe-larger-than=" +# endif void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { CHECK(context); CHECK_GE(max_depth, 2); @@ -91,8 +128,8 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { stack_frame.AddrFrame.Mode = AddrModeFlat; stack_frame.AddrStack.Mode = AddrModeFlat; while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), - &stack_frame, &ctx, NULL, SymFunctionTableAccess64, - SymGetModuleBase64, NULL) && + &stack_frame, &ctx, NULL, FallbackFunctionTableAccess, + FallbackGetModuleBase, NULL) && size < Min(max_depth, kStackTraceMax)) { trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; }