mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-11-27 05:04:01 +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