Commit 53ca4118bd
Changed files (4)
std
std/os/windows/bits.zig
@@ -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;
std/os/windows/kernel32.zig
@@ -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;
std/special/start.zig
@@ -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();
}
std/debug.zig
@@ -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,
+ }
+}