Thread.cpp: Added stack trace and register logging to exception filter (#18564)

This commit is contained in:
luci4
2026-04-13 13:47:44 +01:00
committed by GitHub
parent 72fa4098dc
commit bcd9663349
4 changed files with 73 additions and 13 deletions
+32 -1
View File
@@ -25,6 +25,7 @@
#include <process.h> #include <process.h>
#include <sysinfoapi.h> #include <sysinfoapi.h>
#include "stack_trace.h"
#include "util/dyn_lib.hpp" #include "util/dyn_lib.hpp"
DYNAMIC_IMPORT_RENAME("Kernel32.dll", SetThreadDescriptionImport, "SetThreadDescription", HRESULT(HANDLE hThread, PCWSTR lpThreadDescription)); DYNAMIC_IMPORT_RENAME("Kernel32.dll", SetThreadDescriptionImport, "SetThreadDescription", HRESULT(HANDLE hThread, PCWSTR lpThreadDescription));
@@ -1981,9 +1982,39 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept
} }
fmt::append(msg, "RPCS3 image base: %p.\n", GetModuleHandle(NULL)); fmt::append(msg, "RPCS3 image base: %p.\n", GetModuleHandle(NULL));
#if defined(ARCH_X64)
fmt::append(msg, "RAX: %016llX RBX: %016llX\n", pExp->ContextRecord->Rax, pExp->ContextRecord->Rbx);
fmt::append(msg, "RCX: %016llX RDX: %016llX\n", pExp->ContextRecord->Rcx, pExp->ContextRecord->Rdx);
fmt::append(msg, "RSI: %016llX RDI: %016llX\n", pExp->ContextRecord->Rsi, pExp->ContextRecord->Rdi);
fmt::append(msg, "RBP: %016llX RSP: %016llX\n", pExp->ContextRecord->Rbp, pExp->ContextRecord->Rsp);
fmt::append(msg, "R8: %016llX R9: %016llX\n", pExp->ContextRecord->R8, pExp->ContextRecord->R9);
fmt::append(msg, "R10: %016llX R11: %016llX\n", pExp->ContextRecord->R10, pExp->ContextRecord->R11);
fmt::append(msg, "R12: %016llX R13: %016llX\n", pExp->ContextRecord->R12, pExp->ContextRecord->R13);
fmt::append(msg, "R14: %016llX R15: %016llX\n", pExp->ContextRecord->R14, pExp->ContextRecord->R15);
fmt::append(msg, "RFLAGS: %08X\n", pExp->ContextRecord->EFlags);
#elif defined(ARCH_ARM64)
for (int i = 0; i < 29; i += 2)
{
if (i + 1 < 29)
fmt::append(msg, "X%-2d: %016llX X%-2d: %016llX\n", i, pExp->ContextRecord->X[i], i + 1, pExp->ContextRecord->X[i + 1]);
else
fmt::append(msg, "X%-2d: %016llX\n", i, pExp->ContextRecord->X[i]);
}
fmt::append(msg, "SP: %016llX FP: %016llX LR: %016llX\n", pExp->ContextRecord->Sp, pExp->ContextRecord->Fp, pExp->ContextRecord->Lr);
fmt::append(msg, "CPSR: %08X\n", pExp->ContextRecord->Cpsr);
#endif
// TODO: print registers and the callstack const auto stack_trace = utils::get_backtrace(64, pExp->ContextRecord);
const auto stack_symbols = utils::get_backtrace_symbols(stack_trace);
msg += "Stack Trace:\n";
for (const auto& symbol : stack_symbols)
{
fmt::append(msg, "%s\n", symbol);
}
sys_log.fatal("\n%s", msg); sys_log.fatal("\n%s", msg);
logs::listener::sync_all(); logs::listener::sync_all();
+30 -11
View File
@@ -30,42 +30,61 @@ namespace utils
return out.data(); return out.data();
} }
std::vector<void*> get_backtrace(int max_depth) std::vector<void*> get_backtrace(int max_depth, PCONTEXT ctx)
{ {
static struct sym_initer_t
{
sym_initer_t() noexcept
{
SymInitialize(GetCurrentProcess(), NULL, TRUE);
}
~sym_initer_t() noexcept
{
SymCleanup(GetCurrentProcess());
}
} s_initer{};
std::vector<void*> result = {}; std::vector<void*> result = {};
const auto hProcess = ::GetCurrentProcess(); const auto hProcess = ::GetCurrentProcess();
const auto hThread = ::GetCurrentThread(); const auto hThread = ::GetCurrentThread();
CONTEXT context{}; CONTEXT context{};
RtlCaptureContext(&context); if (ctx)
context = *ctx;
else
RtlCaptureContext(&context);
STACKFRAME64 stack = {}; STACKFRAME64 stack = {};
stack.AddrPC.Mode = AddrModeFlat; stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Mode = AddrModeFlat; stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Mode = AddrModeFlat; stack.AddrFrame.Mode = AddrModeFlat;
#if defined(ARCH_X64) #if defined(ARCH_X64)
const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
stack.AddrPC.Offset = context.Rip; stack.AddrPC.Offset = context.Rip;
stack.AddrStack.Offset = context.Rsp; stack.AddrStack.Offset = context.Rsp;
stack.AddrFrame.Offset = context.Rbp; stack.AddrFrame.Offset = context.Rbp;
#elif defined(ARCH_ARM64) #elif defined(ARCH_ARM64)
const DWORD machineType = IMAGE_FILE_MACHINE_ARM64;
stack.AddrPC.Offset = context.Pc; stack.AddrPC.Offset = context.Pc;
stack.AddrStack.Offset = context.Sp; stack.AddrStack.Offset = context.Sp;
stack.AddrFrame.Offset = context.Fp; stack.AddrFrame.Offset = context.Fp;
#else
#error "Unsupported architecture"
#endif #endif
while (max_depth--) while (max_depth--)
{ {
if (!StackWalk64( if (!StackWalk64(
IMAGE_FILE_MACHINE_AMD64, machineType,
hProcess, hProcess,
hThread, hThread,
&stack, &stack,
&context, &context,
NULL, NULL,
SymFunctionTableAccess64, SymFunctionTableAccess64,
SymGetModuleBase64, SymGetModuleBase64,
NULL)) NULL))
{ {
break; break;
} }
+10
View File
@@ -2,6 +2,11 @@
#include <util/types.hpp> #include <util/types.hpp>
#include <util/logs.hpp> #include <util/logs.hpp>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
namespace utils namespace utils
{ {
namespace stack_trace namespace stack_trace
@@ -30,7 +35,12 @@ namespace utils
}; };
} }
#ifdef _WIN32
std::vector<void*> get_backtrace(int max_depth = 255, PCONTEXT ctx = nullptr);
#else
std::vector<void*> get_backtrace(int max_depth = 255); std::vector<void*> get_backtrace(int max_depth = 255);
#endif
std::vector<std::string> get_backtrace_symbols(const std::vector<void*>& stack); std::vector<std::string> get_backtrace_symbols(const std::vector<void*>& stack);
FORCE_INLINE void print_trace(stack_trace::Logger auto& logger, int max_depth = 255) FORCE_INLINE void print_trace(stack_trace::Logger auto& logger, int max_depth = 255)
+1 -1
View File
@@ -161,7 +161,7 @@ if(WIN32)
Audio/XAudio2/xaudio2_enumerator.cpp Audio/XAudio2/xaudio2_enumerator.cpp
) )
target_compile_definitions(rpcs3_emu PRIVATE UNICODE _UNICODE _WIN32_WINNT=0x0A00) target_compile_definitions(rpcs3_emu PRIVATE UNICODE _UNICODE _WIN32_WINNT=0x0A00)
target_link_libraries(rpcs3_emu PRIVATE pdh bcrypt) target_link_libraries(rpcs3_emu PRIVATE pdh bcrypt dbghelp)
endif() endif()
# Cell # Cell