odin crash handler
| package crash_handler | |
| import "base:runtime" | |
| import "core:sys/posix" | |
| import "core:sys/windows" | |
| write_crash_message_without_address::proc"contextless"(reason:string){ | |
| runtime.print_string("[CRASH] ") | |
| runtime.print_string(reason) | |
| runtime.print_byte('\n') | |
| } | |
| write_crash_message_with_address::proc"contextless"(reason:string,address:rawptr){ | |
| runtime.print_string("[CRASH] ") | |
| runtime.print_string(reason) | |
| runtime.print_string(": 0x") | |
| buf:[16]u8 | |
| hex_chars:[16]u8="0123456789abcdef" | |
| v:=uintptr(address) | |
| for i:=15;i>=0;i-=1{ | |
| buf[i]=hex_chars[v&0xF] | |
| v>>=4 | |
| } | |
| runtime.print_string(string(buf[:])) | |
| runtime.print_byte('\n') | |
| } | |
| write_crash_message::proc{ | |
| write_crash_message_without_address, | |
| write_crash_message_with_address | |
| } | |
| when ODIN_OS==.Windows{ | |
| _handler:windows.PVECTORED_EXCEPTION_HANDLER:proc"system"(info:^windows.EXCEPTION_POINTERS)->windows.LONG{ | |
| erec:=info.ExceptionRecord | |
| switch erec.ExceptionCode{ | |
| case windows.EXCEPTION_DATATYPE_MISALIGNMENT: | |
| write_crash_message("Datatype misalignment (unaligned memory access)") | |
| case windows.EXCEPTION_BREAKPOINT: | |
| write_crash_message("Breakpoint hit (int 3)") | |
| //TODO? windows.EXCEPTION_CONTINUE_EXECUTION | |
| case windows.EXCEPTION_SINGLE_STEP: | |
| write_crash_message("Hardware single-step / trap") | |
| //TODO? windows.EXCEPTION_CONTINUE_EXECUTION | |
| case windows.EXCEPTION_ACCESS_VIOLATION: | |
| if erec.ExceptionInformation[0]==nil{ | |
| write_crash_message("Memory read violation at address",erec.ExceptionInformation[1]) | |
| }else{ | |
| write_crash_message("Memory write violation at address",erec.ExceptionInformation[1]) | |
| } | |
| case windows.EXCEPTION_IN_PAGE_ERROR: | |
| write_crash_message("In-page I/O error reading address",erec.ExceptionInformation[1]) | |
| case windows.EXCEPTION_ILLEGAL_INSTRUCTION: | |
| write_crash_message("Illegal instruction / operation") | |
| case windows.EXCEPTION_NONCONTINUABLE_EXCEPTION: | |
| write_crash_message("Attempted to continue execution after non-continuable exception") | |
| case windows.EXCEPTION_INVALID_DISPOSITION: | |
| write_crash_message("Invalid disposition returned by exception handler") | |
| case windows.EXCEPTION_ARRAY_BOUNDS_EXCEEDED: | |
| write_crash_message("Array bounds exceeded (hardware BOUND instruction)") | |
| case windows.EXCEPTION_FLT_DENORMAL_OPERAND: | |
| write_crash_message("Floating-point denormal operand") | |
| case windows.EXCEPTION_FLT_DIVIDE_BY_ZERO: | |
| write_crash_message("Floating-point divide-by-zero") | |
| case windows.EXCEPTION_FLT_INEXACT_RESULT: | |
| write_crash_message("Floating-point inexact result") | |
| case windows.EXCEPTION_FLT_INVALID_OPERATION: | |
| write_crash_message("Floating-point invalid operation") | |
| case windows.EXCEPTION_FLT_OVERFLOW: | |
| write_crash_message("Floating-point overflow") | |
| case windows.EXCEPTION_FLT_STACK_CHECK: | |
| write_crash_message("Floating-point stack check (x87 stack overflow/underflow)") | |
| case windows.EXCEPTION_FLT_UNDERFLOW: | |
| write_crash_message("Floating-point underflow") | |
| case windows.EXCEPTION_INT_DIVIDE_BY_ZERO: | |
| write_crash_message("Integer divide-by-zero") | |
| case windows.EXCEPTION_INT_OVERFLOW: | |
| write_crash_message("Integer overflow (hardware INTO instruction)") | |
| case windows.EXCEPTION_PRIV_INSTRUCTION: | |
| write_crash_message("Privileged instruction executed in user-mode") | |
| case windows.EXCEPTION_STACK_OVERFLOW: | |
| write_crash_message("Stack overflow") | |
| case 0x40000015://STATUS_FATAL_APP_EXIT | |
| write_crash_message("Fatal application exit (abort / assert)") | |
| case 0xE06D7363://MSVC C++ throw | |
| write_crash_message("Unhandled C++ exception") | |
| case 0x80000001://EXCEPTION_GUARD_PAGE | |
| write_crash_message("Guard page hit (custom stack/allocator violation)") | |
| case 0xC0000008://STATUS_INVALID_HANDLE | |
| write_crash_message("Invalid handle closed or referenced") | |
| case 0xC0000374://STATUS_HEAP_CORRUPTION | |
| write_crash_message("Heap corruption detected (double free / buffer overflow)") | |
| case 0xC0000420://STATUS_ASSERTION_FAILURE | |
| write_crash_message("OS assertion failure (NT_ASSERT)") | |
| case 0xC0000194://STATUS_POSSIBLE_DEADLOCK | |
| write_crash_message("Critical section deadlock detected (timed out)") | |
| case 0xE0434352://CLR exception | |
| write_crash_message("Unhandled .NET / CLR exception") | |
| case 0x40010006,0x4001000A://DBG_PRINTEXCEPTION_C/W | |
| return windows.EXCEPTION_CONTINUE_SEARCH | |
| case 0x406D1388://SetThreadName | |
| return windows.EXCEPTION_CONTINUE_SEARCH | |
| case 0x40010005://CONTROL_C_EXIT | |
| return windows.EXCEPTION_CONTINUE_SEARCH | |
| case: | |
| write_crash_message("Unknown Exception") | |
| return windows.EXCEPTION_CONTINUE_SEARCH | |
| } | |
| runtime.exit(int(erec.ExceptionCode)) | |
| } | |
| install::proc"contextless"(){ | |
| windows.AddVectoredExceptionHandler(1,_handler) | |
| } | |
| }else when ODIN_OS==.Darwin||ODIN_OS==.Linux||ODIN_OS==.FreeBSD||ODIN_OS==.OpenBSD||ODIN_OS==.NetBSD{ | |
| _handler::proc"c"(sig:posix.Signal,info:^posix.siginfo_t,uctx:rawptr){ | |
| switch sig{ | |
| case .SIGSEGV: | |
| switch info.si_code.segv{ | |
| case .MAPERR: | |
| write_crash_message("Memory read violation at address (unmapped)",info.si_addr) | |
| case .ACCERR: | |
| write_crash_message("Memory access violation (permissions / guard page)",info.si_addr) | |
| case 3://.BNDERR | |
| write_crash_message("Array bounds exceeded (hardware bound violation)",info.si_addr) | |
| case: | |
| write_crash_message("Memory access violation at address",info.si_addr) | |
| } | |
| case .SIGBUS: | |
| switch info.si_code.bus{ | |
| case .ADRALN: | |
| write_crash_message("Datatype misalignment (unaligned memory access)",info.si_addr) | |
| case .ADRERR,.OBJERR: | |
| write_crash_message("In-page I/O error reading address",info.si_addr) | |
| case: | |
| write_crash_message("Bus error at address", info.si_addr) | |
| } | |
| case .SIGILL: | |
| switch info.si_code.ill{ | |
| case .PRVOPC,.PRVREG: | |
| write_crash_message("Privileged instruction executed in user-mode") | |
| case .BADSTK: | |
| write_crash_message("Internal stack fault") | |
| case .ILLOPC,.ILLOPN,.ILLADR,.ILLTRP,.COPROC: | |
| fallthrough | |
| case: | |
| write_crash_message("Illegal instruction / operation") | |
| } | |
| case .SIGFPE: | |
| switch info.si_code.fpe{ | |
| case .INTDIV: | |
| write_crash_message("Integer divide-by-zero") | |
| case .INTOVF: | |
| write_crash_message("Integer overflow (hardware INTO instruction)") | |
| case .FLTDIV: | |
| write_crash_message("Floating-point divide-by-zero") | |
| case .FLTOVF: | |
| write_crash_message("Floating-point overflow") | |
| case .FLTUND: | |
| write_crash_message("Floating-point underflow") | |
| case .FLTRES: | |
| write_crash_message("Floating-point inexact result") | |
| case .FLTINV: | |
| write_crash_message("Floating-point invalid operation") | |
| case .FLTSUB: | |
| write_crash_message("Floating-point stack check (x87 stack overflow/underflow)") | |
| case: | |
| write_crash_message("Arithmetic exception") | |
| } | |
| case .SIGTRAP: | |
| switch info.si_code.trap{ | |
| case .BRKPT: | |
| write_crash_message("Breakpoint hit (int 3)") | |
| case .TRACE: | |
| write_crash_message("Hardware single-step / trap") | |
| case: | |
| write_crash_message("Breakpoint / trap hit") | |
| } | |
| case .SIGABRT: | |
| write_crash_message("Fatal application exit (abort / assert / panic)") | |
| case .SIGSYS: | |
| write_crash_message("Bad system call (seccomp filter violation)") | |
| case .SIGINT,.SIGTERM,.SIGALRM,.SIGCHLD,.SIGCONT,.SIGHUP,.SIGKILL,.SIGPIPE,.SIGQUIT,.SIGSTOP,.SIGTSTP,.SIGTTIN,.SIGTTOU,.SIGUSR1,.SIGUSR2,.SIGPOLL,.SIGPROF,.SIGURG,.SIGVTALRM,.SIGXCPU,.SIGXFSZ: | |
| fallthrough | |
| case: | |
| write_crash_message("Unknown signal / exception") | |
| return | |
| case .NONE: | |
| write_crash_message("Spurious null signal (signal 0)") | |
| return | |
| } | |
| runtime.exit(int(sig)) | |
| } | |
| @(private)alt_stack_mem:[64*1024]u8 | |
| install::proc"contextless"(){ | |
| alt_stack:=posix.stack_t{ | |
| ss_sp =&alt_stack_mem[0], | |
| ss_size=len(alt_stack_mem) | |
| } | |
| posix.sigaltstack(&alt_stack,nil) | |
| sa:=posix.sigaction_t{ | |
| sa_sigaction=_handler, | |
| sa_flags ={.SIGINFO,.ONSTACK} | |
| } | |
| posix.sigemptyset(&sa.sa_mask) | |
| SIGNALS_TO_CATCH:=[?]posix.Signal{ | |
| .SIGSEGV, | |
| .SIGBUS, | |
| .SIGILL, | |
| .SIGFPE, | |
| .SIGTRAP, | |
| .SIGABRT, | |
| .SIGSYS, | |
| //.SIGINT, | |
| //.SIGTERM, | |
| //.SIGALRM, | |
| //.SIGCHLD, | |
| //.SIGCONT, | |
| //.SIGHUP, | |
| //.SIGKILL, | |
| //.SIGPIPE, | |
| //.SIGQUIT, | |
| //.SIGSTOP, | |
| //.SIGTSTP, | |
| //.SIGTTIN, | |
| //.SIGTTOU, | |
| //.SIGUSR1, | |
| //.SIGUSR2, | |
| //.SIGPOLL, | |
| //.SIGPROF, | |
| //.SIGURG, | |
| //.SIGVTALRM, | |
| //.SIGXCPU, | |
| //.SIGXFSZ | |
| } | |
| for sig in SIGNALS_TO_CATCH{ | |
| posix.sigaction(sig,&sa,nil) | |
| } | |
| } | |
| }else{ | |
| #panic("Unsupported operating system for crash handler") | |
| } |
评论
?
参与讨论