authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-01-17 17:46:48+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-02 21:18:45-07:00
logafd1f7ed47884ca39082287c267fbb9c5d1ebe68
tree52e47163a9a63cd7a4bc70dabc1c3ad7f241d9cd
parent2ac7aefe2ff0d2f1a4d58a2baa49a40dfb670732

Implement segfault handler for macOS x86_64


3 files changed, 57 insertions(+), 7 deletions(-)

lib/std/c/darwin.zig+45
......@@ -478,6 +478,51 @@ pub const SIG = struct {
478478 pub const USR2 = 31;
479479};
480480
481pub const ucontext_t = extern struct {
482 onstack: c_int,
483 sigmask: sigset_t,
484 stack: stack_t,
485 link: ?*ucontext_t,
486 mcsize: u64,
487 mcontext: *mcontext_t,
488};
489
490pub const exception_state = extern struct {
491 trapno: u16,
492 cpu: u16,
493 err: u32,
494 faultvaddr: u64,
495};
496
497pub const thread_state = extern struct {
498 rax: u64,
499 rbx: u64,
500 rcx: u64,
501 rdx: u64,
502 rdi: u64,
503 rsi: u64,
504 rbp: u64,
505 rsp: u64,
506 r8: u64,
507 r9: u64,
508 r10: u64,
509 r11: u64,
510 r12: u64,
511 r13: u64,
512 r14: u64,
513 r15: u64,
514 rip: u64,
515 rflags: u64,
516 cs: u64,
517 fs: u64,
518 gs: u64,
519};
520
521pub const mcontext_t = extern struct {
522 es: exception_state,
523 ss: thread_state,
524};
525
481526pub const siginfo_t = extern struct {
482527 signo: c_int,
483528 errno: c_int,
lib/std/debug.zig+6-3
......@@ -1574,6 +1574,7 @@ fn getDebugInfoAllocator() mem.Allocator {
15741574/// Whether or not the current target can print useful debug information when a segfault occurs.
15751575pub const have_segfault_handling_support = switch (native_os) {
15761576 .linux, .netbsd, .solaris => true,
1577 .macos => native_arch == .x86_64,
15771578 .windows => true,
15781579 .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
15791580 else => false,
......@@ -1601,7 +1602,7 @@ pub fn attachSegfaultHandler() void {
16011602 return;
16021603 }
16031604 var act = os.Sigaction{
1604 .handler = .{ .sigaction = handleSegfaultLinux },
1605 .handler = .{ .sigaction = handleSegfaultPosix },
16051606 .mask = os.empty_sigset,
16061607 .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND),
16071608 };
......@@ -1629,7 +1630,7 @@ fn resetSegfaultHandler() void {
16291630 os.sigaction(os.SIG.BUS, &act, null);
16301631}
16311632
1632fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {
1633fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {
16331634 // Reset to the default handler so that if a segfault happens in this handler it will crash
16341635 // the process. Also when this handler returns, the original instruction will be repeated
16351636 // and the resulting segfault will crash the process rather than continually dump stack traces.
......@@ -1637,7 +1638,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
16371638
16381639 const addr = switch (native_os) {
16391640 .linux => @ptrToInt(info.fields.sigfault.addr),
1640 .freebsd => @ptrToInt(info.addr),
1641 .freebsd, .macos => @ptrToInt(info.addr),
16411642 .netbsd => @ptrToInt(info.info.reason.fault.addr),
16421643 .openbsd => @ptrToInt(info.data.fault.addr),
16431644 .solaris => @ptrToInt(info.reason.fault.addr),
......@@ -1668,12 +1669,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
16681669 .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]),
16691670 .freebsd => @intCast(usize, ctx.mcontext.rip),
16701671 .openbsd => @intCast(usize, ctx.sc_rip),
1672 .macos => @intCast(usize, ctx.mcontext.ss.rip),
16711673 else => unreachable,
16721674 };
16731675 const bp = switch (native_os) {
16741676 .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]),
16751677 .openbsd => @intCast(usize, ctx.sc_rbp),
16761678 .freebsd => @intCast(usize, ctx.mcontext.rbp),
1679 .macos => @intCast(usize, ctx.mcontext.ss.rbp),
16771680 else => unreachable,
16781681 };
16791682 dumpStackTraceFromBase(bp, ip);
src/crash_report.zig+6-4
......@@ -169,7 +169,7 @@ pub fn attachSegfaultHandler() void {
169169 return;
170170 }
171171 var act = os.Sigaction{
172 .handler = .{ .sigaction = handleSegfaultLinux },
172 .handler = .{ .sigaction = handleSegfaultPosix },
173173 .mask = os.empty_sigset,
174174 .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND),
175175 };
......@@ -179,17 +179,17 @@ pub fn attachSegfaultHandler() void {
179179 os.sigaction(os.SIG.BUS, &act, null);
180180}
181181
182fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {
182fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {
183183 // TODO: use alarm() here to prevent infinite loops
184184 PanicSwitch.preDispatch();
185185
186186 const addr = switch (builtin.os.tag) {
187187 .linux => @ptrToInt(info.fields.sigfault.addr),
188 .freebsd => @ptrToInt(info.addr),
188 .freebsd, .macos => @ptrToInt(info.addr),
189189 .netbsd => @ptrToInt(info.info.reason.fault.addr),
190190 .openbsd => @ptrToInt(info.data.fault.addr),
191191 .solaris => @ptrToInt(info.reason.fault.addr),
192 else => @compileError("TODO implement handleSegfaultLinux for new linux OS"),
192 else => @compileError("TODO implement handleSegfaultPosix for new POSIX OS"),
193193 };
194194
195195 var err_buffer: [128]u8 = undefined;
......@@ -213,12 +213,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
213213 .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]),
214214 .freebsd => @intCast(usize, ctx.mcontext.rip),
215215 .openbsd => @intCast(usize, ctx.sc_rip),
216 .macos => @intCast(usize, ctx.mcontext.ss.rip),
216217 else => unreachable,
217218 };
218219 const bp = switch (builtin.os.tag) {
219220 .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]),
220221 .openbsd => @intCast(usize, ctx.sc_rbp),
221222 .freebsd => @intCast(usize, ctx.mcontext.rbp),
223 .macos => @intCast(usize, ctx.mcontext.ss.rbp),
222224 else => unreachable,
223225 };
224226 break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };