mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
189 lines
4.9 KiB
Plaintext
189 lines
4.9 KiB
Plaintext
module std::os::win32 @if(env::WIN32);
|
|
|
|
import std::io;
|
|
|
|
const EXCEPTION_MAXIMUM_PARAMETERS = 15;
|
|
|
|
struct ExceptionRecord
|
|
{
|
|
Win32_DWORD exception_code;
|
|
Win32_DWORD exception_flags;
|
|
ExceptionRecord* exception_record;
|
|
void* exception_address;
|
|
Win32_DWORD number_parameters;
|
|
Win32_ULONG_PTR[EXCEPTION_MAXIMUM_PARAMETERS] exception_information;
|
|
}
|
|
|
|
struct ExceptionContext @align(16)
|
|
{
|
|
Win32_DWORD64 p1_home;
|
|
Win32_DWORD64 p2_home;
|
|
Win32_DWORD64 p3_home;
|
|
Win32_DWORD64 p4_home;
|
|
Win32_DWORD64 p5_home;
|
|
Win32_DWORD64 p6_home;
|
|
|
|
Win32_DWORD context_flags;
|
|
Win32_DWORD mx_csr;
|
|
|
|
Win32_WORD seg_cs;
|
|
Win32_WORD seg_ds;
|
|
Win32_WORD seg_es;
|
|
Win32_WORD seg_fs;
|
|
Win32_WORD seg_gs;
|
|
Win32_WORD seg_ss;
|
|
Win32_DWORD eflags;
|
|
|
|
Win32_DWORD64 dr0;
|
|
Win32_DWORD64 dr1;
|
|
Win32_DWORD64 dr2;
|
|
Win32_DWORD64 dr3;
|
|
Win32_DWORD64 dr6;
|
|
Win32_DWORD64 dr7;
|
|
|
|
Win32_DWORD64 rax;
|
|
Win32_DWORD64 rcx;
|
|
Win32_DWORD64 rdx;
|
|
Win32_DWORD64 rbx;
|
|
Win32_DWORD64 rsp;
|
|
Win32_DWORD64 rbp;
|
|
Win32_DWORD64 rsi;
|
|
Win32_DWORD64 rdi;
|
|
Win32_DWORD64 r8;
|
|
Win32_DWORD64 r9;
|
|
Win32_DWORD64 r10;
|
|
Win32_DWORD64 r11;
|
|
Win32_DWORD64 r12;
|
|
Win32_DWORD64 r13;
|
|
Win32_DWORD64 r14;
|
|
Win32_DWORD64 r15;
|
|
|
|
Win32_DWORD64 rip;
|
|
|
|
union
|
|
{
|
|
struct flt_save @align(16)
|
|
{
|
|
Win32_WORD control_word;
|
|
Win32_WORD status_word;
|
|
Win32_BYTE tag_word;
|
|
Win32_BYTE reserved1;
|
|
Win32_WORD error_opcode;
|
|
Win32_DWORD error_offset;
|
|
Win32_WORD error_selector;
|
|
Win32_WORD reserved2;
|
|
Win32_DWORD data_offset;
|
|
Win32_WORD data_selector;
|
|
Win32_WORD reserved3;
|
|
Win32_DWORD mx_csr;
|
|
Win32_DWORD mx_csr_mask;
|
|
|
|
Win32_M128A[16] xmm_registers;
|
|
Win32_BYTE[96] reserved4;
|
|
}
|
|
struct
|
|
{
|
|
Win32_M128A[2] header;
|
|
Win32_M128A[8] legacy;
|
|
Win32_M128A xmm0;
|
|
Win32_M128A xmm1;
|
|
Win32_M128A xmm2;
|
|
Win32_M128A xmm3;
|
|
Win32_M128A xmm4;
|
|
Win32_M128A xmm5;
|
|
Win32_M128A xmm6;
|
|
Win32_M128A xmm7;
|
|
Win32_M128A xmm8;
|
|
Win32_M128A xmm9;
|
|
Win32_M128A xmm10;
|
|
Win32_M128A xmm11;
|
|
Win32_M128A xmm12;
|
|
Win32_M128A xmm13;
|
|
Win32_M128A xmm14;
|
|
Win32_M128A xmm15;
|
|
}
|
|
}
|
|
|
|
Win32_M128A[26] vector_registers;
|
|
Win32_DWORD64 vector_control;
|
|
|
|
Win32_DWORD64 debug_control;
|
|
Win32_DWORD64 last_branch_to_rip;
|
|
Win32_DWORD64 last_branch_from_rip;
|
|
Win32_DWORD64 last_exception_to_rip;
|
|
Win32_DWORD64 last_exception_from_rip;
|
|
}
|
|
|
|
struct ExceptionPointers
|
|
{
|
|
ExceptionRecord* exception_record;
|
|
ExceptionContext* context_record;
|
|
}
|
|
|
|
alias UnhandledExceptionFilter = fn Win32_LONG (ExceptionPointers* exception_info);
|
|
const EXCEPTION_EXECUTE_HANDLER = 1;
|
|
|
|
extern fn void debugBreak() @extern("DebugBreak") @if(env::WIN32);
|
|
extern fn bool isDebuggerPresent() @extern("IsDebuggerPresent") @if(env::WIN32);
|
|
extern fn UnhandledExceptionFilter setUnhandledExceptionFilter(UnhandledExceptionFilter filter) @extern("SetUnhandledExceptionFilter") @if(env::WIN32);
|
|
|
|
UnhandledExceptionFilter previous_filter;
|
|
PanicFn previous_panic;
|
|
bool has_panicked;
|
|
|
|
fn Win32_LONG exception_handler(ExceptionPointers* exception_info)
|
|
{
|
|
if (!has_panicked)
|
|
{
|
|
@stack_mem(2048; Allocator allocator)
|
|
{
|
|
DString s;
|
|
s.init(allocator: allocator);
|
|
Win32_DWORD code = exception_info.exception_record.exception_code;
|
|
void* addr = exception_info.exception_record.exception_address;
|
|
switch (code)
|
|
{
|
|
case 0x80000001: s.appendf("Guard page violation at address %p", addr);
|
|
case 0x80000002: s.appendf("Datatype misalignment at address %p", addr);
|
|
case 0xC0000005: s.appendf("Access Violation at address %p", addr);
|
|
case 0xC0000006: s.appendf("In page error at address %p", addr);
|
|
case 0xC000001D: s.appendf("Illegal instruction at address %p", addr);
|
|
case 0xC000008C: s.appendf("Array bounds exceeded at address %p", addr);
|
|
case 0xC000008D: s.appendf("Flt denormal operand at address %p", addr);
|
|
case 0xC000008E: s.appendf("Flt divide by zero at address %p", addr);
|
|
case 0xC0000090: s.appendf("Flt invalid operation at address %p", addr);
|
|
case 0xC0000094: s.appendf("Integer divide by zero at address %p", addr);
|
|
case 0xC00000FD: s.appendf("Stack overflow at address %p", addr);
|
|
case 0xC0000096: s.appendf("Privileged instruction at address %p", addr);
|
|
case 0xC0000374: s.appendf("Heap corruption detected at address %p", addr);
|
|
case 0xC0000409: s.appendf("Stack buffer overflow at address %p", addr);
|
|
case 0xC00004A2: s.appendf("Enclave violation at address %p", addr);
|
|
default:
|
|
s.appendf("Unhandled exception (%X) at %p", code, addr);
|
|
}
|
|
if (!builtin::print_backtrace(s.str_view(), 8))
|
|
{
|
|
io::eprintfn("\nERROR: %s", s.str_view());
|
|
}
|
|
};
|
|
}
|
|
if (previous_filter)
|
|
{
|
|
return previous_filter(exception_info);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
fn void panic_tracker(String message, String file, String function, uint line)
|
|
{
|
|
has_panicked = true;
|
|
previous_panic(message, file, function, line);
|
|
}
|
|
|
|
fn void init_exception_handler() @init
|
|
{
|
|
previous_filter = setUnhandledExceptionFilter(&exception_handler);
|
|
previous_panic = builtin::panic;
|
|
builtin::panic = &panic_tracker;
|
|
}
|