mirror of
https://github.com/ziglang/zig.git
synced 2026-02-16 06:18:32 +00:00
added segfault handler support for windows
This commit is contained in:
parent
a1359ac3ab
commit
53ca4118bd
@ -2311,23 +2311,31 @@ fn getDebugInfoAllocator() *mem.Allocator {
|
||||
}
|
||||
|
||||
/// Whether or not the current target can print useful debug information when a segfault occurs.
|
||||
pub const have_segfault_handling_support = builtin.arch == .x86_64 and builtin.os == .linux;
|
||||
pub const have_segfault_handling_support = (builtin.arch == .x86_64 and builtin.os == .linux) or builtin.os == .windows;
|
||||
|
||||
/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");
|
||||
pub fn attachSegfaultHandler() void {
|
||||
if (!have_segfault_handling_support) {
|
||||
@compileError("segfault handler not supported for this target");
|
||||
}
|
||||
var act = os.Sigaction{
|
||||
.sigaction = handleSegfault,
|
||||
.mask = os.empty_sigset,
|
||||
.flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
|
||||
};
|
||||
switch (builtin.os) {
|
||||
.linux => {
|
||||
var act = os.Sigaction{
|
||||
.sigaction = handleSegfaultLinux,
|
||||
.mask = os.empty_sigset,
|
||||
.flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
|
||||
};
|
||||
|
||||
os.sigaction(os.SIGSEGV, &act, null);
|
||||
os.sigaction(os.SIGSEGV, &act, null);
|
||||
},
|
||||
.windows => {
|
||||
_ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
extern fn handleSegfault(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
|
||||
extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
|
||||
// Reset to the default handler so that if a segfault happens in this handler it will crash
|
||||
// the process. Also when this handler returns, the original instruction will be repeated
|
||||
// and the resulting segfault will crash the process rather than continually dump stack traces.
|
||||
@ -2350,3 +2358,14 @@ extern fn handleSegfault(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_
|
||||
// the segfault. So we simply abort here.
|
||||
os.abort();
|
||||
}
|
||||
|
||||
stdcallcc fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) c_long {
|
||||
const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
|
||||
switch (info.ExceptionRecord.ExceptionCode) {
|
||||
windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access"),
|
||||
windows.EXCEPTION_ACCESS_VIOLATION => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", info.ExceptionRecord.ExceptionInformation[1]),
|
||||
windows.EXCEPTION_ILLEGAL_INSTRUCTION => panicExtra(null, exception_address, "Illegal Instruction"),
|
||||
windows.EXCEPTION_STACK_OVERFLOW => panicExtra(null, exception_address, "Stack Overflow"),
|
||||
else => return windows.EXCEPTION_CONTINUE_SEARCH,
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,3 +539,25 @@ pub const FORMAT_MESSAGE_FROM_STRING = 0x00000400;
|
||||
pub const FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
|
||||
pub const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
|
||||
pub const FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;
|
||||
|
||||
pub const EXCEPTION_DATATYPE_MISALIGNMENT = 0x80000002;
|
||||
pub const EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
|
||||
pub const EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d;
|
||||
pub const EXCEPTION_STACK_OVERFLOW = 0xc00000fd;
|
||||
pub const EXCEPTION_CONTINUE_SEARCH = 0;
|
||||
|
||||
pub const EXCEPTION_RECORD = extern struct {
|
||||
ExceptionCode: u32,
|
||||
ExceptionFlags: u32,
|
||||
ExceptionRecord: *EXCEPTION_RECORD,
|
||||
ExceptionAddress: *c_void,
|
||||
NumberParameters: u32,
|
||||
ExceptionInformation: [15]usize,
|
||||
};
|
||||
|
||||
pub const EXCEPTION_POINTERS = extern struct {
|
||||
ExceptionRecord: *EXCEPTION_RECORD,
|
||||
ContextRecord: *c_void,
|
||||
};
|
||||
|
||||
pub const VECTORED_EXCEPTION_HANDLER = stdcallcc fn (ExceptionInfo: *EXCEPTION_POINTERS) c_long;
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
usingnamespace @import("bits.zig");
|
||||
|
||||
pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;
|
||||
|
||||
pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
|
||||
|
||||
@ -24,6 +24,16 @@ comptime {
|
||||
}
|
||||
}
|
||||
|
||||
fn enableSegfaultHandler() void {
|
||||
const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
|
||||
root.enable_segfault_handler
|
||||
else
|
||||
std.debug.runtime_safety and std.debug.have_segfault_handling_support;
|
||||
if (enable_segfault_handler) {
|
||||
std.debug.attachSegfaultHandler();
|
||||
}
|
||||
}
|
||||
|
||||
extern fn wasm_freestanding_start() void {
|
||||
_ = callMain();
|
||||
}
|
||||
@ -61,6 +71,9 @@ extern fn WinMainCRTStartup() noreturn {
|
||||
if (!builtin.single_threaded) {
|
||||
_ = @import("start_windows_tls.zig");
|
||||
}
|
||||
|
||||
enableSegfaultHandler();
|
||||
|
||||
std.os.windows.kernel32.ExitProcess(callMain());
|
||||
}
|
||||
|
||||
@ -100,13 +113,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
|
||||
std.os.argv = argv[0..argc];
|
||||
std.os.environ = envp;
|
||||
|
||||
const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
|
||||
root.enable_segfault_handler
|
||||
else
|
||||
std.debug.runtime_safety and std.debug.have_segfault_handling_support;
|
||||
if (enable_segfault_handler) {
|
||||
std.debug.attachSegfaultHandler();
|
||||
}
|
||||
enableSegfaultHandler();
|
||||
|
||||
return callMain();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user