Enable segfault handling on FreeBSD.

This commit is contained in:
Alex Cameron 2020-12-19 10:21:55 +00:00 committed by Veikka Tuominen
parent d9fe7ea815
commit 60020fd545
2 changed files with 60 additions and 2 deletions

View File

@ -1696,6 +1696,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
pub const have_segfault_handling_support = switch (builtin.os.tag) {
.linux, .netbsd => true,
.windows => true,
.freebsd => @hasDecl(os, "ucontext_t"),
else => false,
};
pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
@ -1757,6 +1758,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
const addr = switch (builtin.os.tag) {
.linux => @ptrToInt(info.fields.sigfault.addr),
.freebsd => @ptrToInt(info.addr),
.netbsd => @ptrToInt(info.info.reason.fault.addr),
else => unreachable,
};
@ -1781,8 +1783,16 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
},
.x86_64 => {
const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]);
const bp = @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]);
const ip = switch (builtin.os.tag) {
.linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]),
.freebsd => @intCast(usize, ctx.mcontext.rip),
else => unreachable,
};
const bp = switch (builtin.os.tag) {
.linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]),
.freebsd => @intCast(usize, ctx.mcontext.rbp),
else => unreachable,
};
dumpStackTraceFromBase(bp, ip);
},
.arm => {

View File

@ -4,6 +4,7 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("../../std.zig");
const builtin = std.builtin;
const maxInt = std.math.maxInt;
// See https://svnweb.freebsd.org/base/head/sys/sys/_types.h?view=co
@ -815,6 +816,53 @@ pub const sigset_t = extern struct {
pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** _SIG_WORDS };
pub usingnamespace switch (builtin.arch) {
.x86_64 => struct {
pub const ucontext_t = extern struct {
sigmask: sigset_t,
mcontext: mcontext_t,
link: ?*ucontext_t,
stack: stack_t,
flags: c_int,
__spare__: [4]c_int,
};
/// XXX x86_64 specific
pub const mcontext_t = extern struct {
onstack: u64,
rdi: u64,
rsi: u64,
rdx: u64,
rcx: u64,
r8: u64,
r9: u64,
rax: u64,
rbx: u64,
rbp: u64,
r10: u64,
r11: u64,
r12: u64,
r13: u64,
r14: u64,
r15: u64,
trapno: u32,
fs: u16,
gs: u16,
addr: u64,
flags: u32,
es: u16,
ds: u16,
err: u64,
rip: u64,
cs: u64,
rflags: u64,
rsp: u64,
ss: u64,
};
},
else => struct {},
};
pub const EPERM = 1; // Operation not permitted
pub const ENOENT = 2; // No such file or directory
pub const ESRCH = 3; // No such process