fn handleSegfaultPosix(sig: posix.SIG, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.c) noreturn {
if (use_trap_panic) @trap();
const addr: ?usize, const name: []const u8 = info: {
if (native_os == .linux and native_arch == .x86_64) {
// x86_64 doesn't have a full 64-bit virtual address space.
// Addresses outside of that address space are non-canonical
// and the CPU won't provide the faulting address to us.
// This happens when accessing memory addresses such as 0xaaaaaaaaaaaaaaaa
// but can also happen when no addressable memory is involved;
// for example when reading/writing model-specific registers
// by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).
const SI_KERNEL = 0x80;
if (sig == .SEGV and info.code == SI_KERNEL) {
break :info .{ null, "General protection exception" };
}
}
const addr: usize = switch (native_os) {
.serenity,
.dragonfly,
.freebsd,
.driverkit,
.ios,
.maccatalyst,
.macos,
.tvos,
.visionos,
.watchos,
.haiku,
=> @intFromPtr(info.addr),
.linux,
=> @intFromPtr(info.fields.sigfault.addr),
.netbsd,
=> @intFromPtr(info.info.reason.fault.addr),
.openbsd,
=> @intFromPtr(info.data.fault.addr),
.illumos,
=> @intFromPtr(info.reason.fault.addr),
else => comptime unreachable,
};
const name = switch (sig) {
.SEGV => "Segmentation fault",
.ILL => "Illegal instruction",
.BUS => "Bus error",
.FPE => "Arithmetic exception",
else => unreachable,
};
break :info .{ addr, name };
};
const opt_cpu_context: ?cpu_context.Native = cpu_context.fromPosixSignalContext(ctx_ptr);
handleSegfault(addr, name, if (opt_cpu_context) |*ctx| ctx else null);
}