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 {...@@ -2311,23 +2311,31 @@ fn getDebugInfoAllocator() *mem.Allocator {
2311}2311}
23122312
2313/// Whether or not the current target can print useful debug information when a segfault occurs.2313/// 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
2316/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");2316/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");
2317pub fn attachSegfaultHandler() void {2317pub fn attachSegfaultHandler() void {
2318 if (!have_segfault_handling_support) {2318 if (!have_segfault_handling_support) {
2319 @compileError("segfault handler not supported for this target");2319 @compileError("segfault handler not supported for this target");
2320 }2320 }
2321 var act = os.Sigaction{2321 switch (builtin.os) {
2322 .sigaction = handleSegfault,2322 .linux => {
2323 .mask = os.empty_sigset,2323 var act = os.Sigaction{
2324 .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),2324 .sigaction = handleSegfaultLinux,
2325 };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 }
2328}2336}
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 {
2331 // Reset to the default handler so that if a segfault happens in this handler it will crash2339 // Reset to the default handler so that if a segfault happens in this handler it will crash
2332 // the process. Also when this handler returns, the original instruction will be repeated2340 // the process. Also when this handler returns, the original instruction will be repeated
2333 // and the resulting segfault will crash the process rather than continually dump stack traces.2341 // 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_...@@ -2350,3 +2358,14 @@ extern fn handleSegfault(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_
2350 // the segfault. So we simply abort here.2358 // the segfault. So we simply abort here.
2351 os.abort();2359 os.abort();
2352}2360}
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;...@@ -539,3 +539,25 @@ pub const FORMAT_MESSAGE_FROM_STRING = 0x00000400;
539pub const FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;539pub const FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
540pub const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;540pub const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
541pub const FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;541pub 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 @@...@@ -1,5 +1,7 @@
1usingnamespace @import("bits.zig");1usingnamespace @import("bits.zig");
22
3pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void;
4
3pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;5pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;
46
5pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;7pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;
std/special/start.zig+14-7
...@@ -24,6 +24,16 @@ comptime {...@@ -24,6 +24,16 @@ comptime {
24 }24 }
25}25}
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
27extern fn wasm_freestanding_start() void {37extern fn wasm_freestanding_start() void {
28 _ = callMain();38 _ = callMain();
29}39}
...@@ -61,6 +71,9 @@ extern fn WinMainCRTStartup() noreturn {...@@ -61,6 +71,9 @@ extern fn WinMainCRTStartup() noreturn {
61 if (!builtin.single_threaded) {71 if (!builtin.single_threaded) {
62 _ = @import("start_windows_tls.zig");72 _ = @import("start_windows_tls.zig");
63 }73 }
74
75 enableSegfaultHandler();
76
64 std.os.windows.kernel32.ExitProcess(callMain());77 std.os.windows.kernel32.ExitProcess(callMain());
65}78}
6679
...@@ -100,13 +113,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {...@@ -100,13 +113,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
100 std.os.argv = argv[0..argc];113 std.os.argv = argv[0..argc];
101 std.os.environ = envp;114 std.os.environ = envp;
102115
103 const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))116 enableSegfaultHandler();
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 }
110117
111 return callMain();118 return callMain();
112}119}