#include "exception_handler.hpp" #include "stack_trace.hpp" #include namespace big { inline auto hash_stack_trace(std::vector stack_trace) { auto data = reinterpret_cast(stack_trace.data()); std::size_t size = stack_trace.size() * sizeof(uint64_t); return std::hash()({ data, size }); } exception_handler::exception_handler() { m_old_error_mode = SetErrorMode(0); m_exception_handler = SetUnhandledExceptionFilter(&vectored_exception_handler); } exception_handler::~exception_handler() { SetErrorMode(m_old_error_mode); SetUnhandledExceptionFilter(reinterpret_cast(m_exception_handler)); } inline static stack_trace trace; LONG vectored_exception_handler(EXCEPTION_POINTERS* exception_info) { const auto exception_code = exception_info->ExceptionRecord->ExceptionCode; if (exception_code == EXCEPTION_BREAKPOINT || exception_code == DBG_PRINTEXCEPTION_C || exception_code == DBG_PRINTEXCEPTION_WIDE_C) return EXCEPTION_CONTINUE_SEARCH; static std::set logged_exceptions; trace.new_stack_trace(exception_info); const auto trace_hash = hash_stack_trace(trace.frame_pointers()); if (const auto it = logged_exceptions.find(trace_hash); it == logged_exceptions.end()) { LOG(FATAL) << trace; logged_exceptions.insert(trace_hash); } ZyanU64 opcode_address = exception_info->ContextRecord->Rip; ZydisDisassembledInstruction instruction; ZydisDisassembleIntel(ZYDIS_MACHINE_MODE_LONG_64, opcode_address, reinterpret_cast(opcode_address), 32, &instruction); exception_info->ContextRecord->Rip += instruction.info.length; return EXCEPTION_CONTINUE_EXECUTION; } }