authorgravatar for emekankurumeh@outlook.comemekoi <emekankurumeh@outlook.com> 2019-07-03 10:16:52-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-03 14:02:48-04:00
log53ca4118bdd3908092a53b6b4c59762a85b78dfc
tree62dfc2d29502bb0eb259903c19cc9c354c17bae1
parenta1359ac3abbb83f30719f596180f1e923da3a8f2

added segfault handler support for windows


4 files changed, 65 insertions(+), 15 deletions(-)

std/debug.zig+27-8
......@@ -2311,23 +2311,31 @@ fn getDebugInfoAllocator() *mem.Allocator {
23112311}
23122312
23132313/// Whether or not the current target can print useful debug information when a segfault occurs.
2314pub const have_segfault_handling_support = builtin.arch == .x86_64 and builtin.os == .linux;
2314pub const have_segfault_handling_support = (builtin.arch == .x86_64 and builtin.os == .linux) or builtin.os == .windows;
23152315
23162316/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");
23172317pub fn attachSegfaultHandler() void {
23182318 if (!have_segfault_handling_support) {
23192319 @compileError("segfault handler not supported for this target");
23202320 }
2321 var act = os.Sigaction{
2322 .sigaction = handleSegfault,
2323 .mask = os.empty_sigset,
2324 .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
2325 };
2321 switch (builtin.os) {
2322 .linux => {
2323 var act = os.Sigaction{
2324 .sigaction = handleSegfaultLinux,
2325 .mask = os.empty_sigset,
2326 .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
2327 };
23262328
2327 os.sigaction(os.SIGSEGV, &act, null);
2329 os.sigaction(os.SIGSEGV, &act, null);
2330 },
2331 .windows => {
2332 _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
2333 },
2334 else => unreachable,
2335 }
23282336}
23292337
2330extern fn handleSegfault(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
2338extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
23312339 // Reset to the default handler so that if a segfault happens in this handler it will crash
23322340 // the process. Also when this handler returns, the original instruction will be repeated
23332341 // 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_
23502358 // the segfault. So we simply abort here.
23512359 os.abort();
23522360}
2361
2362stdcallcc fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) c_long {
2363 const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
2364 switch (info.ExceptionRecord.ExceptionCode) {
2365 windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access"),
2366 windows.EXCEPTION_ACCESS_VIOLATION => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", info.ExceptionRecord.ExceptionInformation[1]),
2367 windows.EXCEPTION_ILLEGAL_INSTRUCTION => panicExtra(null, exception_address, "Illegal Instruction"),
2368 windows.EXCEPTION_STACK_OVERFLOW => panicExtra(null, exception_address, "Stack Overflow"),
2369 else => return windows.EXCEPTION_CONTINUE_SEARCH,
2370 }
2371}
std/os/windows/bits.zig+22
......@@ -539,3 +539,25 @@ pub const FORMAT_MESSAGE_FROM_STRING = 0x00000400;
539539pub const FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
540540pub const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
541541pub const FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;
542
543pub const EXCEPTION_DATATYPE_MISALIGNMENT = 0x80000002;
544pub const EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
545pub const EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d;
546pub const EXCEPTION_STACK_OVERFLOW = 0xc00000fd;
547pub const EXCEPTION_CONTINUE_SEARCH = 0;
548
549pub const EXCEPTION_RECORD = extern struct {
550 ExceptionCode: u32,
551 ExceptionFlags: u32,
552 ExceptionRecord: *EXCEPTION_RECORD,
553 ExceptionAddress: *c_void,
554 NumberParameters: u32,
555 ExceptionInformation: [15]usize,
556};
557
558pub const EXCEPTION_POINTERS = extern struct {
559 ExceptionRecord: *EXCEPTION_RECORD,
560 ContextRecord: *c_void,
561};
562
563pub const VECTORED_EXCEPTION_HANDLER = stdcallcc fn (ExceptionInfo: *EXCEPTION_POINTERS) c_long;
std/os/windows/kernel32.zig+2
......@@ -1,5 +1,7 @@
11usingnamespace @import("bits.zig");
22
3pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void;
4
35pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;
46
57pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
std/special/start.zig+14-7
......@@ -24,6 +24,16 @@ comptime {
2424 }
2525}
2626
27fn enableSegfaultHandler() void {
28 const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
29 root.enable_segfault_handler
30 else
31 std.debug.runtime_safety and std.debug.have_segfault_handling_support;
32 if (enable_segfault_handler) {
33 std.debug.attachSegfaultHandler();
34 }
35}
36
2737extern fn wasm_freestanding_start() void {
2838 _ = callMain();
2939}
......@@ -61,6 +71,9 @@ extern fn WinMainCRTStartup() noreturn {
6171 if (!builtin.single_threaded) {
6272 _ = @import("start_windows_tls.zig");
6373 }
74
75 enableSegfaultHandler();
76
6477 std.os.windows.kernel32.ExitProcess(callMain());
6578}
6679
......@@ -100,13 +113,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
100113 std.os.argv = argv[0..argc];
101114 std.os.environ = envp;
102115
103 const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
104 root.enable_segfault_handler
105 else
106 std.debug.runtime_safety and std.debug.have_segfault_handling_support;
107 if (enable_segfault_handler) {
108 std.debug.attachSegfaultHandler();
109 }
116 enableSegfaultHandler();
110117
111118 return callMain();
112119}