Thread.cpp: Added stack trace and register logging to exception filter (#18564)
This commit is contained in:
+32
-1
@@ -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));
|
||||||
@@ -1982,7 +1983,37 @@ 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));
|
||||||
|
|
||||||
// TODO: print registers and the callstack
|
#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
|
||||||
|
|
||||||
|
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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user