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")
}
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论