aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorJohn Schmidt <john.schmidt.h@gmail.com>2022-01-17 17:46:48 +0100
committerAndrew Kelley <andrew@ziglang.org>2022-01-18 15:10:49 -0500
commit305a7def136580e7a05652a95c1d2ff338541607 (patch)
tree56018e77d507252d36a393d6fbe81abd55751a48 /lib/std
parentf423b5949b8722d4b290f57c3d06d015e39217b0 (diff)
downloadzig-305a7def136580e7a05652a95c1d2ff338541607.tar.gz
zig-305a7def136580e7a05652a95c1d2ff338541607.zip
Implement segfault handler for macOS x86_64
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/c/darwin.zig45
-rw-r--r--lib/std/debug.zig9
2 files changed, 51 insertions, 3 deletions
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
index 2a4541ea74..b10b582dc2 100644
--- a/lib/std/c/darwin.zig
+++ b/lib/std/c/darwin.zig
@@ -478,6 +478,51 @@ pub const SIG = struct {
pub const USR2 = 31;
};
+pub const ucontext_t = extern struct {
+ onstack: c_int,
+ sigmask: sigset_t,
+ stack: stack_t,
+ link: ?*ucontext_t,
+ mcsize: u64,
+ mcontext: *mcontext_t,
+};
+
+pub const exception_state = extern struct {
+ trapno: u16,
+ cpu: u16,
+ err: u32,
+ faultvaddr: u64,
+};
+
+pub const thread_state = extern struct {
+ rax: u64,
+ rbx: u64,
+ rcx: u64,
+ rdx: u64,
+ rdi: u64,
+ rsi: u64,
+ rbp: u64,
+ rsp: u64,
+ r8: u64,
+ r9: u64,
+ r10: u64,
+ r11: u64,
+ r12: u64,
+ r13: u64,
+ r14: u64,
+ r15: u64,
+ rip: u64,
+ rflags: u64,
+ cs: u64,
+ fs: u64,
+ gs: u64,
+};
+
+pub const mcontext_t = extern struct {
+ es: exception_state,
+ ss: thread_state,
+};
+
pub const siginfo_t = extern struct {
signo: c_int,
errno: c_int,
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index 6c09b71451..517176c900 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -1574,6 +1574,7 @@ 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 = switch (native_os) {
.linux, .netbsd, .solaris => true,
+ .macos => native_arch == .x86_64,
.windows => true,
.freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
else => false,
@@ -1601,7 +1602,7 @@ pub fn attachSegfaultHandler() void {
return;
}
var act = os.Sigaction{
- .handler = .{ .sigaction = handleSegfaultLinux },
+ .handler = .{ .sigaction = handleSegfaultPosix },
.mask = os.empty_sigset,
.flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND),
};
@@ -1629,7 +1630,7 @@ fn resetSegfaultHandler() void {
os.sigaction(os.SIG.BUS, &act, null);
}
-fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {
+fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) 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.
@@ -1637,7 +1638,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
const addr = switch (native_os) {
.linux => @ptrToInt(info.fields.sigfault.addr),
- .freebsd => @ptrToInt(info.addr),
+ .freebsd, .macos => @ptrToInt(info.addr),
.netbsd => @ptrToInt(info.info.reason.fault.addr),
.openbsd => @ptrToInt(info.data.fault.addr),
.solaris => @ptrToInt(info.reason.fault.addr),
@@ -1668,12 +1669,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
.linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]),
.freebsd => @intCast(usize, ctx.mcontext.rip),
.openbsd => @intCast(usize, ctx.sc_rip),
+ .macos => @intCast(usize, ctx.mcontext.ss.rip),
else => unreachable,
};
const bp = switch (native_os) {
.linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]),
.openbsd => @intCast(usize, ctx.sc_rbp),
.freebsd => @intCast(usize, ctx.mcontext.rbp),
+ .macos => @intCast(usize, ctx.mcontext.ss.rbp),
else => unreachable,
};
dumpStackTraceFromBase(bp, ip);