#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; Logger::FlushQueue(); logged_exceptions.insert(trace_hash); } if (IsBadReadPtr(reinterpret_cast(exception_info->ContextRecord->Rip), 8)) { auto return_address_ptr = (uint64_t*)exception_info->ContextRecord->Rsp; if (IsBadReadPtr(reinterpret_cast(return_address_ptr), 8)) { LOG(FATAL) << "Cannot resume execution, crashing"; return EXCEPTION_CONTINUE_SEARCH; } else { exception_info->ContextRecord->Rip = *return_address_ptr; exception_info->ContextRecord->Rsp += 8; } } else { hde64s opcode{}; hde64_disasm(reinterpret_cast(exception_info->ContextRecord->Rip), &opcode); if (opcode.flags & F_ERROR) { LOG(FATAL) << "Cannot resume execution, crashing"; return EXCEPTION_CONTINUE_SEARCH; } exception_info->ContextRecord->Rip += opcode.len; } return EXCEPTION_CONTINUE_EXECUTION; } }