| author | |
| committer | |
| log | 305a7def136580e7a05652a95c1d2ff338541607 |
| tree | 56018e77d507252d36a393d6fbe81abd55751a48 |
| parent | f423b5949b8722d4b290f57c3d06d015e39217b0 |
3 files changed, 57 insertions(+), 7 deletions(-)
lib/std/c/darwin.zig+45| ... | @@ -478,6 +478,51 @@ pub const SIG = struct { | ... | @@ -478,6 +478,51 @@ pub const SIG = struct { |
| 478 | pub const USR2 = 31; | 478 | pub const USR2 = 31; |
| 479 | }; | 479 | }; |
| 480 | 480 | ||
| 481 | pub 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 | |||
| 490 | pub const exception_state = extern struct { | ||
| 491 | trapno: u16, | ||
| 492 | cpu: u16, | ||
| 493 | err: u32, | ||
| 494 | faultvaddr: u64, | ||
| 495 | }; | ||
| 496 | |||
| 497 | pub 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 | |||
| 521 | pub const mcontext_t = extern struct { | ||
| 522 | es: exception_state, | ||
| 523 | ss: thread_state, | ||
| 524 | }; | ||
| 525 | |||
| 481 | pub const siginfo_t = extern struct { | 526 | pub const siginfo_t = extern struct { |
| 482 | signo: c_int, | 527 | signo: c_int, |
| 483 | errno: c_int, | 528 | errno: c_int, |
lib/std/debug.zig+6-3| ... | @@ -1574,6 +1574,7 @@ fn getDebugInfoAllocator() mem.Allocator { | ... | @@ -1574,6 +1574,7 @@ fn getDebugInfoAllocator() mem.Allocator { |
| 1574 | /// Whether or not the current target can print useful debug information when a segfault occurs. | 1574 | /// Whether or not the current target can print useful debug information when a segfault occurs. |
| 1575 | pub const have_segfault_handling_support = switch (native_os) { | 1575 | pub const have_segfault_handling_support = switch (native_os) { |
| 1576 | .linux, .netbsd, .solaris => true, | 1576 | .linux, .netbsd, .solaris => true, |
| 1577 | .macos => native_arch == .x86_64, | ||
| 1577 | .windows => true, | 1578 | .windows => true, |
| 1578 | .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"), | 1579 | .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"), |
| 1579 | else => false, | 1580 | else => false, |
| ... | @@ -1601,7 +1602,7 @@ pub fn attachSegfaultHandler() void { | ... | @@ -1601,7 +1602,7 @@ pub fn attachSegfaultHandler() void { |
| 1601 | return; | 1602 | return; |
| 1602 | } | 1603 | } |
| 1603 | var act = os.Sigaction{ | 1604 | var act = os.Sigaction{ |
| 1604 | .handler = .{ .sigaction = handleSegfaultLinux }, | 1605 | .handler = .{ .sigaction = handleSegfaultPosix }, |
| 1605 | .mask = os.empty_sigset, | 1606 | .mask = os.empty_sigset, |
| 1606 | .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), | 1607 | .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), |
| 1607 | }; | 1608 | }; |
| ... | @@ -1629,7 +1630,7 @@ fn resetSegfaultHandler() void { | ... | @@ -1629,7 +1630,7 @@ fn resetSegfaultHandler() void { |
| 1629 | os.sigaction(os.SIG.BUS, &act, null); | 1630 | os.sigaction(os.SIG.BUS, &act, null); |
| 1630 | } | 1631 | } |
| 1631 | 1632 | ||
| 1632 | fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { | 1633 | fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { |
| 1633 | // Reset to the default handler so that if a segfault happens in this handler it will crash | 1634 | // Reset to the default handler so that if a segfault happens in this handler it will crash |
| 1634 | // the process. Also when this handler returns, the original instruction will be repeated | 1635 | // the process. Also when this handler returns, the original instruction will be repeated |
| 1635 | // and the resulting segfault will crash the process rather than continually dump stack traces. | 1636 | // 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 | ... | @@ -1637,7 +1638,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any |
| 1637 | 1638 | ||
| 1638 | const addr = switch (native_os) { | 1639 | const addr = switch (native_os) { |
| 1639 | .linux => @ptrToInt(info.fields.sigfault.addr), | 1640 | .linux => @ptrToInt(info.fields.sigfault.addr), |
| 1640 | .freebsd => @ptrToInt(info.addr), | 1641 | .freebsd, .macos => @ptrToInt(info.addr), |
| 1641 | .netbsd => @ptrToInt(info.info.reason.fault.addr), | 1642 | .netbsd => @ptrToInt(info.info.reason.fault.addr), |
| 1642 | .openbsd => @ptrToInt(info.data.fault.addr), | 1643 | .openbsd => @ptrToInt(info.data.fault.addr), |
| 1643 | .solaris => @ptrToInt(info.reason.fault.addr), | 1644 | .solaris => @ptrToInt(info.reason.fault.addr), |
| ... | @@ -1668,12 +1669,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any | ... | @@ -1668,12 +1669,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any |
| 1668 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]), | 1669 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]), |
| 1669 | .freebsd => @intCast(usize, ctx.mcontext.rip), | 1670 | .freebsd => @intCast(usize, ctx.mcontext.rip), |
| 1670 | .openbsd => @intCast(usize, ctx.sc_rip), | 1671 | .openbsd => @intCast(usize, ctx.sc_rip), |
| 1672 | .macos => @intCast(usize, ctx.mcontext.ss.rip), | ||
| 1671 | else => unreachable, | 1673 | else => unreachable, |
| 1672 | }; | 1674 | }; |
| 1673 | const bp = switch (native_os) { | 1675 | const bp = switch (native_os) { |
| 1674 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]), | 1676 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]), |
| 1675 | .openbsd => @intCast(usize, ctx.sc_rbp), | 1677 | .openbsd => @intCast(usize, ctx.sc_rbp), |
| 1676 | .freebsd => @intCast(usize, ctx.mcontext.rbp), | 1678 | .freebsd => @intCast(usize, ctx.mcontext.rbp), |
| 1679 | .macos => @intCast(usize, ctx.mcontext.ss.rbp), | ||
| 1677 | else => unreachable, | 1680 | else => unreachable, |
| 1678 | }; | 1681 | }; |
| 1679 | dumpStackTraceFromBase(bp, ip); | 1682 | dumpStackTraceFromBase(bp, ip); |
src/crash_report.zig+6-4| ... | @@ -169,7 +169,7 @@ pub fn attachSegfaultHandler() void { | ... | @@ -169,7 +169,7 @@ pub fn attachSegfaultHandler() void { |
| 169 | return; | 169 | return; |
| 170 | } | 170 | } |
| 171 | var act = os.Sigaction{ | 171 | var act = os.Sigaction{ |
| 172 | .handler = .{ .sigaction = handleSegfaultLinux }, | 172 | .handler = .{ .sigaction = handleSegfaultPosix }, |
| 173 | .mask = os.empty_sigset, | 173 | .mask = os.empty_sigset, |
| 174 | .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), | 174 | .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), |
| 175 | }; | 175 | }; |
| ... | @@ -179,17 +179,17 @@ pub fn attachSegfaultHandler() void { | ... | @@ -179,17 +179,17 @@ pub fn attachSegfaultHandler() void { |
| 179 | os.sigaction(os.SIG.BUS, &act, null); | 179 | os.sigaction(os.SIG.BUS, &act, null); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { | 182 | fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { |
| 183 | // TODO: use alarm() here to prevent infinite loops | 183 | // TODO: use alarm() here to prevent infinite loops |
| 184 | PanicSwitch.preDispatch(); | 184 | PanicSwitch.preDispatch(); |
| 185 | 185 | ||
| 186 | const addr = switch (builtin.os.tag) { | 186 | const addr = switch (builtin.os.tag) { |
| 187 | .linux => @ptrToInt(info.fields.sigfault.addr), | 187 | .linux => @ptrToInt(info.fields.sigfault.addr), |
| 188 | .freebsd => @ptrToInt(info.addr), | 188 | .freebsd, .macos => @ptrToInt(info.addr), |
| 189 | .netbsd => @ptrToInt(info.info.reason.fault.addr), | 189 | .netbsd => @ptrToInt(info.info.reason.fault.addr), |
| 190 | .openbsd => @ptrToInt(info.data.fault.addr), | 190 | .openbsd => @ptrToInt(info.data.fault.addr), |
| 191 | .solaris => @ptrToInt(info.reason.fault.addr), | 191 | .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"), |
| 193 | }; | 193 | }; |
| 194 | 194 | ||
| 195 | var err_buffer: [128]u8 = undefined; | 195 | var err_buffer: [128]u8 = undefined; |
| ... | @@ -213,12 +213,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any | ... | @@ -213,12 +213,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any |
| 213 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]), | 213 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]), |
| 214 | .freebsd => @intCast(usize, ctx.mcontext.rip), | 214 | .freebsd => @intCast(usize, ctx.mcontext.rip), |
| 215 | .openbsd => @intCast(usize, ctx.sc_rip), | 215 | .openbsd => @intCast(usize, ctx.sc_rip), |
| 216 | .macos => @intCast(usize, ctx.mcontext.ss.rip), | ||
| 216 | else => unreachable, | 217 | else => unreachable, |
| 217 | }; | 218 | }; |
| 218 | const bp = switch (builtin.os.tag) { | 219 | const bp = switch (builtin.os.tag) { |
| 219 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]), | 220 | .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]), |
| 220 | .openbsd => @intCast(usize, ctx.sc_rbp), | 221 | .openbsd => @intCast(usize, ctx.sc_rbp), |
| 221 | .freebsd => @intCast(usize, ctx.mcontext.rbp), | 222 | .freebsd => @intCast(usize, ctx.mcontext.rbp), |
| 223 | .macos => @intCast(usize, ctx.mcontext.ss.rbp), | ||
| 222 | else => unreachable, | 224 | else => unreachable, |
| 223 | }; | 225 | }; |
| 224 | break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } }; | 226 | break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } }; |