mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-11-30 14:25:36 +08:00
win crash printer
This commit is contained in:
parent
57e7dbebde
commit
fcfda3ddd2
15
crash_printer/crash_printer/win.hpp
Normal file
15
crash_printer/crash_printer/win.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef _CRASH_PRINTER_WIN
|
||||
#define _CRASH_PRINTER_WIN
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace crash_printer {
|
||||
|
||||
bool init(const std::wstring &log_file);
|
||||
|
||||
void deinit();
|
||||
|
||||
}
|
||||
|
||||
#endif // _CRASH_PRINTER_WIN
|
151
crash_printer/win.cpp
Normal file
151
crash_printer/win.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
#include "crash_printer/common.hpp"
|
||||
#include "crash_printer/win.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <DbgHelp.h>
|
||||
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER originalExceptionFilter = nullptr;
|
||||
|
||||
static std::wstring logs_filepath{};
|
||||
|
||||
static void print_stacktrace(std::ofstream &file, CONTEXT* context) {
|
||||
auto this_proc = GetCurrentProcess();
|
||||
auto this_thread = GetCurrentThread();
|
||||
|
||||
if (!SymInitialize(this_proc, NULL, TRUE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
STACKFRAME stack_frame{};
|
||||
|
||||
#ifdef _WIN64
|
||||
constexpr DWORD machine_type = IMAGE_FILE_MACHINE_AMD64;
|
||||
DWORD64 symbol_displacement = 0;
|
||||
|
||||
stack_frame.AddrPC.Offset = context->Rip;
|
||||
stack_frame.AddrFrame.Offset = context->Rsp;
|
||||
stack_frame.AddrStack.Offset = context->Rsp;
|
||||
#else
|
||||
constexpr DWORD machine_type = IMAGE_FILE_MACHINE_I386;
|
||||
DWORD symbol_displacement = 0;
|
||||
|
||||
stack_frame.AddrPC.Offset = context->Eip;
|
||||
stack_frame.AddrFrame.Offset = context->Esp; // EBP may not be used by module
|
||||
stack_frame.AddrStack.Offset = context->Esp;
|
||||
#endif
|
||||
|
||||
stack_frame.AddrPC.Mode = ADDRESS_MODE::AddrModeFlat;
|
||||
stack_frame.AddrFrame.Mode = ADDRESS_MODE::AddrModeFlat;
|
||||
stack_frame.AddrStack.Mode = ADDRESS_MODE::AddrModeFlat;
|
||||
|
||||
crash_printer::write(file, "*********** Stack trace ***********");
|
||||
std::vector<std::string> symbols{};
|
||||
while (true) {
|
||||
BOOL res = StackWalk(
|
||||
machine_type,
|
||||
this_proc, this_thread,
|
||||
&stack_frame,
|
||||
context,
|
||||
NULL, SymFunctionTableAccess, SymGetModuleBase, NULL);
|
||||
if (!res) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool print_symbol = false;
|
||||
IMAGEHLP_SYMBOL *symbol = (IMAGEHLP_SYMBOL *)_malloca(sizeof(IMAGEHLP_SYMBOL) + MAX_PATH);
|
||||
if (symbol) {
|
||||
symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
|
||||
symbol->MaxNameLength = MAX_PATH - 1; // "in characters, not including the null-terminating character"
|
||||
|
||||
symbol_displacement = 0;
|
||||
|
||||
if (SymGetSymFromAddr(this_proc, stack_frame.AddrPC.Offset, &symbol_displacement, symbol)) {
|
||||
print_symbol = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss{};
|
||||
ss << "0x" << std::hex << (void *)stack_frame.AddrPC.Offset << " | ";
|
||||
if (print_symbol) {
|
||||
ss << symbol->Name;
|
||||
} else {
|
||||
ss << "<unknown function>";
|
||||
}
|
||||
symbols.push_back(ss.str());
|
||||
|
||||
if (symbol) {
|
||||
_freea(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
SymCleanup(this_proc);
|
||||
|
||||
auto idx = symbols.size();
|
||||
for (const auto &s : symbols) {
|
||||
std::stringstream ss{};
|
||||
ss << "[frame " << std::dec << (idx - 1) << "]: "
|
||||
<< s;
|
||||
crash_printer::write(file, ss.str());
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
|
||||
static void log_exception(LPEXCEPTION_POINTERS ex_pointers)
|
||||
{
|
||||
if (!crash_printer::create_dir(logs_filepath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ofstream file(logs_filepath, std::ios::app);
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto t_now = std::chrono::system_clock::to_time_t(now);
|
||||
auto gm_time = std::gmtime(&t_now);
|
||||
auto time = std::string(std::asctime(gm_time));
|
||||
time.pop_back(); // remove the trailing '\n' added by asctime
|
||||
crash_printer::write(file, "[" + time + "]");
|
||||
{
|
||||
std::stringstream ss{};
|
||||
ss << "Unhandled exception:" << std::endl
|
||||
<< " code: 0x" << std::hex << ex_pointers->ExceptionRecord->ExceptionCode << std::endl
|
||||
<< " @address = 0x" << std::hex << ex_pointers->ExceptionRecord->ExceptionAddress;
|
||||
crash_printer::write(file, ss.str());
|
||||
}
|
||||
|
||||
print_stacktrace(file, ex_pointers->ContextRecord);
|
||||
crash_printer::write(file, "**********************************\n");
|
||||
file.close();
|
||||
}
|
||||
|
||||
static LONG WINAPI exception_handler(LPEXCEPTION_POINTERS ex_pointers)
|
||||
{
|
||||
log_exception(ex_pointers);
|
||||
|
||||
if (originalExceptionFilter) {
|
||||
return originalExceptionFilter(ex_pointers);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
|
||||
bool crash_printer::init(const std::wstring &log_file)
|
||||
{
|
||||
logs_filepath = log_file;
|
||||
|
||||
originalExceptionFilter = SetUnhandledExceptionFilter(exception_handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void crash_printer::deinit()
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user