Commit f33d3a5166

Alex Rønne Petersen <alex@alexrp.com>
2025-10-09 09:49:27
std.debug: greatly expand target support for segfault handling/unwinding
I made a couple of decisions for this based on the fact that we don't expose the signal_ucontext_t type outside of the file: * Adding all the floating point and vector state to every ucontext_t and mcontext_t variant was way, way too much work, especially when we don't even use the stuff. So I deleted all that and kept only the bare minimum needed to reach into general-purpose registers. * There is no particularly compelling reason to stick to the naming and struct nesting used in the system headers. So we can actually unify the access patterns for almost all of these variants by taking some liberties here; as a result, fromPosixSignalContext() is now much nicer to read and extend.
1 parent 3f5e782
Changed files (3)
lib
lib/std/debug/SelfInfo/Elf.zig
@@ -94,6 +94,15 @@ pub const can_unwind: bool = s: {
     // Notably, we are yet to support unwinding on ARM. There, unwinding is not done through
     // `.eh_frame`, but instead with the `.ARM.exidx` section, which has a different format.
     const archs: []const std.Target.Cpu.Arch = switch (builtin.target.os.tag) {
+        // Not supported yet: arm, m68k, sparc64
+        .haiku => &.{
+            .aarch64,
+            .powerpc,
+            .riscv64,
+            .x86,
+            .x86_64,
+        },
+        // Not supported yet: arc, arm/armeb/thumb/thumbeb, csky, m68k, or1k, sparc/sparc64, xtensa
         .linux => &.{
             .aarch64,
             .aarch64_be,
@@ -113,31 +122,54 @@ pub const can_unwind: bool = s: {
             .x86,
             .x86_64,
         },
-        .netbsd => &.{
+        .serenity => &.{
             .aarch64,
-            .aarch64_be,
-            .x86,
             .x86_64,
+            .riscv64,
         },
-        .freebsd => &.{
+
+        .dragonfly => &.{
             .x86_64,
+        },
+        // Not supported yet: arm
+        .freebsd => &.{
             .aarch64,
+            .powerpc64,
+            .powerpc64le,
+            .riscv64,
+            .x86_64,
         },
-        .openbsd => &.{
+        // Not supported yet: arm/armeb, m68k, mips64/mips64el, sparc/sparc64
+        .netbsd => &.{
+            .aarch64,
+            .aarch64_be,
+            .mips,
+            .mipsel,
+            .powerpc,
+            .x86,
             .x86_64,
         },
-        .solaris => &.{
+        // Not supported yet: arm, sparc64
+        .openbsd => &.{
+            .aarch64,
+            .mips64,
+            .mips64el,
+            .powerpc,
+            .powerpc64,
+            .riscv64,
+            .x86,
             .x86_64,
         },
+
         .illumos => &.{
             .x86,
             .x86_64,
         },
-        .serenity => &.{
+        // Not supported yet: sparc64
+        .solaris => &.{
             .x86_64,
-            .aarch64,
-            .riscv64,
         },
+
         else => unreachable,
     };
     for (archs) |a| {
lib/std/debug/cpu_context.zig
@@ -24,229 +24,92 @@ pub const DwarfRegisterError = error{
 
 pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
     if (signal_ucontext_t == void) return null;
+
+    // In general, we include the hardwired zero register in the context if applicable.
     const uc: *const signal_ucontext_t = @ptrCast(@alignCast(ctx_ptr));
+
+    // Deal with some special cases first.
+    if (native_arch.isMIPS32() and native_os == .linux) {
+        // The O32 kABI uses 64-bit fields for some reason.
+        return .{
+            .r = s: {
+                var regs: [32]Mips.Gpr = undefined;
+                for (uc.mcontext.r, 0..) |r, i| regs[i] = @truncate(r);
+                break :s regs;
+            },
+            .pc = @truncate(uc.mcontext.pc),
+        };
+    }
+
+    // Only unified conversions from here.
     return switch (native_arch) {
-        .x86 => switch (native_os) {
-            .linux, .netbsd, .illumos => .{ .gprs = .init(.{
-                .eax = uc.mcontext.gregs[std.posix.REG.EAX],
-                .ecx = uc.mcontext.gregs[std.posix.REG.ECX],
-                .edx = uc.mcontext.gregs[std.posix.REG.EDX],
-                .ebx = uc.mcontext.gregs[std.posix.REG.EBX],
-                .esp = uc.mcontext.gregs[std.posix.REG.ESP],
-                .ebp = uc.mcontext.gregs[std.posix.REG.EBP],
-                .esi = uc.mcontext.gregs[std.posix.REG.ESI],
-                .edi = uc.mcontext.gregs[std.posix.REG.EDI],
-                .eip = uc.mcontext.gregs[std.posix.REG.EIP],
-            }) },
-            else => null,
+        .arm, .armeb, .thumb, .thumbeb => .{
+            .r = uc.mcontext.r ++ [_]u32{uc.mcontext.pc},
         },
-        .x86_64 => switch (native_os) {
-            .linux, .solaris, .illumos => .{ .gprs = .init(.{
-                .rax = uc.mcontext.gregs[std.posix.REG.RAX],
-                .rdx = uc.mcontext.gregs[std.posix.REG.RDX],
-                .rcx = uc.mcontext.gregs[std.posix.REG.RCX],
-                .rbx = uc.mcontext.gregs[std.posix.REG.RBX],
-                .rsi = uc.mcontext.gregs[std.posix.REG.RSI],
-                .rdi = uc.mcontext.gregs[std.posix.REG.RDI],
-                .rbp = uc.mcontext.gregs[std.posix.REG.RBP],
-                .rsp = uc.mcontext.gregs[std.posix.REG.RSP],
-                .r8 = uc.mcontext.gregs[std.posix.REG.R8],
-                .r9 = uc.mcontext.gregs[std.posix.REG.R9],
-                .r10 = uc.mcontext.gregs[std.posix.REG.R10],
-                .r11 = uc.mcontext.gregs[std.posix.REG.R11],
-                .r12 = uc.mcontext.gregs[std.posix.REG.R12],
-                .r13 = uc.mcontext.gregs[std.posix.REG.R13],
-                .r14 = uc.mcontext.gregs[std.posix.REG.R14],
-                .r15 = uc.mcontext.gregs[std.posix.REG.R15],
-                .rip = uc.mcontext.gregs[std.posix.REG.RIP],
-            }) },
-            .freebsd, .serenity => .{ .gprs = .init(.{
-                .rax = uc.mcontext.rax,
-                .rdx = uc.mcontext.rdx,
-                .rcx = uc.mcontext.rcx,
-                .rbx = uc.mcontext.rbx,
-                .rsi = uc.mcontext.rsi,
-                .rdi = uc.mcontext.rdi,
-                .rbp = uc.mcontext.rbp,
-                .rsp = uc.mcontext.rsp,
-                .r8 = uc.mcontext.r8,
-                .r9 = uc.mcontext.r9,
-                .r10 = uc.mcontext.r10,
-                .r11 = uc.mcontext.r11,
-                .r12 = uc.mcontext.r12,
-                .r13 = uc.mcontext.r13,
-                .r14 = uc.mcontext.r14,
-                .r15 = uc.mcontext.r15,
-                .rip = uc.mcontext.rip,
-            }) },
-            .openbsd => .{ .gprs = .init(.{
-                .rax = @bitCast(uc.sc_rax),
-                .rdx = @bitCast(uc.sc_rdx),
-                .rcx = @bitCast(uc.sc_rcx),
-                .rbx = @bitCast(uc.sc_rbx),
-                .rsi = @bitCast(uc.sc_rsi),
-                .rdi = @bitCast(uc.sc_rdi),
-                .rbp = @bitCast(uc.sc_rbp),
-                .rsp = @bitCast(uc.sc_rsp),
-                .r8 = @bitCast(uc.sc_r8),
-                .r9 = @bitCast(uc.sc_r9),
-                .r10 = @bitCast(uc.sc_r10),
-                .r11 = @bitCast(uc.sc_r11),
-                .r12 = @bitCast(uc.sc_r12),
-                .r13 = @bitCast(uc.sc_r13),
-                .r14 = @bitCast(uc.sc_r14),
-                .r15 = @bitCast(uc.sc_r15),
-                .rip = @bitCast(uc.sc_rip),
-            }) },
-            .driverkit, .macos, .ios => .{ .gprs = .init(.{
-                .rax = uc.mcontext.ss.rax,
-                .rdx = uc.mcontext.ss.rdx,
-                .rcx = uc.mcontext.ss.rcx,
-                .rbx = uc.mcontext.ss.rbx,
-                .rsi = uc.mcontext.ss.rsi,
-                .rdi = uc.mcontext.ss.rdi,
-                .rbp = uc.mcontext.ss.rbp,
-                .rsp = uc.mcontext.ss.rsp,
-                .r8 = uc.mcontext.ss.r8,
-                .r9 = uc.mcontext.ss.r9,
-                .r10 = uc.mcontext.ss.r10,
-                .r11 = uc.mcontext.ss.r11,
-                .r12 = uc.mcontext.ss.r12,
-                .r13 = uc.mcontext.ss.r13,
-                .r14 = uc.mcontext.ss.r14,
-                .r15 = uc.mcontext.ss.r15,
-                .rip = uc.mcontext.ss.rip,
-            }) },
-            else => null,
+        .aarch64, .aarch64_be => .{
+            .x = uc.mcontext.x ++ [_]u64{uc.mcontext.lr},
+            .sp = uc.mcontext.sp,
+            .pc = uc.mcontext.pc,
         },
-        .arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) {
-            .linux => .{
-                .r = .{
-                    uc.mcontext.arm_r0,
-                    uc.mcontext.arm_r1,
-                    uc.mcontext.arm_r2,
-                    uc.mcontext.arm_r3,
-                    uc.mcontext.arm_r4,
-                    uc.mcontext.arm_r5,
-                    uc.mcontext.arm_r6,
-                    uc.mcontext.arm_r7,
-                    uc.mcontext.arm_r8,
-                    uc.mcontext.arm_r9,
-                    uc.mcontext.arm_r10,
-                    uc.mcontext.arm_fp, // r11 = fp
-                    uc.mcontext.arm_ip, // r12 = ip
-                    uc.mcontext.arm_sp, // r13 = sp
-                    uc.mcontext.arm_lr, // r14 = lr
-                    uc.mcontext.arm_pc, // r15 = pc
-                },
-            },
-            else => null,
+        .hexagon, .loongarch32, .loongarch64, .mips, .mipsel, .mips64, .mips64el, .or1k => .{
+            .r = uc.mcontext.r,
+            .pc = uc.mcontext.pc,
         },
-        .aarch64, .aarch64_be => switch (builtin.os.tag) {
-            .driverkit, .macos, .ios, .tvos, .watchos, .visionos => .{
-                .x = uc.mcontext.ss.regs ++ @as([2]u64, .{
-                    uc.mcontext.ss.fp, // x29 = fp
-                    uc.mcontext.ss.lr, // x30 = lr
-                }),
-                .sp = uc.mcontext.ss.sp,
-                .pc = uc.mcontext.ss.pc,
-            },
-            .netbsd => .{
-                .x = uc.mcontext.gregs[0..31].*,
-                .sp = uc.mcontext.gregs[31],
-                .pc = uc.mcontext.gregs[32],
-            },
-            .freebsd => .{
-                .x = uc.mcontext.gpregs.x ++ @as([1]u64, .{
-                    uc.mcontext.gpregs.lr, // x30 = lr
-                }),
-                .sp = uc.mcontext.gpregs.sp,
-                // On aarch64, the register ELR_LR1 defines the address to return to after handling
-                // a CPU exception (ELR is "Exception Link Register"). FreeBSD's ucontext_t uses
-                // this as the field name, but it's the same thing as the context's PC.
-                .pc = uc.mcontext.gpregs.elr,
-            },
-            .openbsd => .{
-                .x = uc.sc_x ++ .{uc.sc_lr},
-                .sp = uc.sc_sp,
-                // Not a bug; see freebsd above for explanation.
-                .pc = uc.sc_elr,
-            },
-            .linux => .{
-                .x = uc.mcontext.regs,
-                .sp = uc.mcontext.sp,
-                .pc = uc.mcontext.pc,
-            },
-            .serenity => .{
-                .x = uc.mcontext.x,
-                .sp = uc.mcontext.sp,
-                .pc = uc.mcontext.pc,
-            },
-            else => null,
-        },
-        .hexagon => switch (builtin.os.tag) {
-            .linux => .{
-                .r = uc.mcontext.gregs,
-                .pc = uc.mcontext.pc,
-            },
-            else => null,
+        .powerpc, .powerpcle, .powerpc64, .powerpc64le => .{
+            .r = uc.mcontext.r,
+            .pc = uc.mcontext.pc,
+            .lr = uc.mcontext.lr,
         },
-        .loongarch64 => switch (builtin.os.tag) {
-            .linux => .{
-                .r = uc.mcontext.regs, // includes r0 (hardwired zero)
-                .pc = uc.mcontext.pc,
-            },
-            else => null,
+        .riscv32, .riscv32be, .riscv64, .riscv64be => .{
+            // You can thank FreeBSD and OpenBSD for this silliness; they decided to be cute and
+            // group the registers by ABI mnemonic rather than register number.
+            .x = [_]Riscv.Gpr{0} ++
+                uc.mcontext.ra_sp_gp_tp ++
+                uc.mcontext.t0_2 ++
+                uc.mcontext.s0_1 ++
+                uc.mcontext.a ++
+                uc.mcontext.s2_11 ++
+                uc.mcontext.t3_6,
+            .pc = uc.mcontext.pc,
         },
-        .mips, .mipsel => switch (builtin.os.tag) {
-            // The O32 kABI uses 64-bit fields for some reason...
-            .linux => .{
-                .r = s: {
-                    var regs: [32]Mips.Gpr = undefined;
-                    for (uc.mcontext.regs, 0..) |r, i| regs[i] = @truncate(r); // includes r0 (hardwired zero)
-                    break :s regs;
-                },
-                .pc = @truncate(uc.mcontext.pc),
+        .s390x => .{
+            .r = uc.mcontext.r,
+            .psw = .{
+                .mask = uc.mcontext.psw.mask,
+                .addr = uc.mcontext.psw.addr,
             },
-            else => null,
         },
-        .mips64, .mips64el => switch (builtin.os.tag) {
-            .linux => .{
-                .r = uc.mcontext.regs, // includes r0 (hardwired zero)
-                .pc = uc.mcontext.pc,
-            },
-            else => null,
-        },
-        .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (builtin.os.tag) {
-            .linux => .{
-                .r = uc.mcontext.gp_regs[0..32].*,
-                .pc = uc.mcontext.gp_regs[32],
-                .lr = uc.mcontext.gp_regs[36],
-            },
-            else => null,
-        },
-        .riscv32, .riscv64 => switch (builtin.os.tag) {
-            .linux => .{
-                .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero
-                .pc = uc.mcontext.gregs[0],
-            },
-            .serenity => if (native_arch == .riscv32) null else .{
-                .r = [1]u64{0} ++ uc.mcontext.x,
-                .pc = uc.mcontext.pc,
-            },
-            else => null,
-        },
-        .s390x => switch (builtin.os.tag) {
-            .linux => .{
-                .r = uc.mcontext.gregs,
-                .psw = .{
-                    .mask = uc.mcontext.psw.mask,
-                    .addr = uc.mcontext.psw.addr,
-                },
-            },
-            else => null,
-        },
-        else => null,
+        .x86 => .{ .gprs = .init(.{
+            .eax = uc.mcontext.eax,
+            .ecx = uc.mcontext.ecx,
+            .edx = uc.mcontext.edx,
+            .ebx = uc.mcontext.ebx,
+            .esp = uc.mcontext.esp,
+            .ebp = uc.mcontext.ebp,
+            .esi = uc.mcontext.esi,
+            .edi = uc.mcontext.edi,
+            .eip = uc.mcontext.eip,
+        }) },
+        .x86_64 => .{ .gprs = .init(.{
+            .rax = uc.mcontext.rax,
+            .rdx = uc.mcontext.rdx,
+            .rcx = uc.mcontext.rcx,
+            .rbx = uc.mcontext.rbx,
+            .rsi = uc.mcontext.rsi,
+            .rdi = uc.mcontext.rdi,
+            .rbp = uc.mcontext.rbp,
+            .rsp = uc.mcontext.rsp,
+            .r8 = uc.mcontext.r8,
+            .r9 = uc.mcontext.r9,
+            .r10 = uc.mcontext.r10,
+            .r11 = uc.mcontext.r11,
+            .r12 = uc.mcontext.r12,
+            .r13 = uc.mcontext.r13,
+            .r14 = uc.mcontext.r14,
+            .r15 = uc.mcontext.r15,
+            .rip = uc.mcontext.rip,
+        }) },
+        else => comptime unreachable,
     };
 }
 
@@ -615,7 +478,7 @@ const LoongArch = extern struct {
     r: [32]Gpr,
     pc: Gpr,
 
-    pub const Gpr = if (builtin.target.cpu.arch == .loongarch64) u64 else u32;
+    pub const Gpr = if (native_arch == .loongarch64) u64 else u32;
 
     pub inline fn current() LoongArch {
         var ctx: LoongArch = undefined;
@@ -717,7 +580,7 @@ const Mips = extern struct {
     r: [32]Gpr,
     pc: Gpr,
 
-    pub const Gpr = if (builtin.target.cpu.arch.isMIPS64()) u64 else u32;
+    pub const Gpr = if (native_arch.isMIPS64()) u64 else u32;
 
     pub inline fn current() Mips {
         var ctx: Mips = undefined;
@@ -840,7 +703,7 @@ const Powerpc = extern struct {
     pc: Gpr,
     lr: Gpr,
 
-    pub const Gpr = if (builtin.target.cpu.arch.isPowerPC64()) u64 else u32;
+    pub const Gpr = if (native_arch.isPowerPC64()) u64 else u32;
 
     pub inline fn current() Powerpc {
         var ctx: Powerpc = undefined;
@@ -992,10 +855,10 @@ const Powerpc = extern struct {
 /// This is an `extern struct` so that inline assembly in `current` can use field offsets.
 const Riscv = extern struct {
     /// The numbered general-purpose registers r0 - r31. r0 must be zero.
-    r: [32]Gpr,
+    x: [32]Gpr,
     pc: Gpr,
 
-    pub const Gpr = if (builtin.target.cpu.arch.isRiscv64()) u64 else u32;
+    pub const Gpr = if (native_arch.isRiscv64()) u64 else u32;
 
     pub inline fn current() Riscv {
         var ctx: Riscv = undefined;
@@ -1081,7 +944,7 @@ const Riscv = extern struct {
 
     pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 {
         switch (register_num) {
-            0...31 => return @ptrCast(&ctx.r[register_num]),
+            0...31 => return @ptrCast(&ctx.x[register_num]),
             65 => return @ptrCast(&ctx.pc),
 
             32...63 => return error.UnsupportedRegister, // f0 - f31
@@ -1138,61 +1001,199 @@ const S390x = extern struct {
     }
 };
 
+/// The native operating system's `ucontext_t` as seen in the third argument to signal handlers.
+///
+/// These are dramatically simplified since we only need general-purpose registers and don't care
+/// about all the complicated extension state (floating point, vector, etc). This means that these
+/// structures are almost all shorter than the real ones, which is safe because we only access them
+/// through a pointer.
+///
+/// Some effort is made to have structures for the same architecture use the same access pattern,
+/// e.g. `uc.mcontext.x` for `aarch64-linux` and `aarch64-freebsd` even though that's not quite how
+/// they're declared and spelled in the C headers for both targets. Similarly, registers are typed
+/// as unsigned everywhere even if that's not how they're declared in the C headers.
 const signal_ucontext_t = switch (native_os) {
-    .linux => std.os.linux.ucontext_t,
-    .emscripten => std.os.emscripten.ucontext_t,
-    .freebsd => std.os.freebsd.ucontext_t,
-    .driverkit, .macos, .ios, .tvos, .watchos, .visionos => extern struct {
-        onstack: c_int,
-        sigmask: std.c.sigset_t,
-        stack: std.c.stack_t,
-        link: ?*signal_ucontext_t,
-        mcsize: u64,
-        mcontext: *mcontext_t,
-        const mcontext_t = switch (native_arch) {
-            .aarch64 => extern struct {
-                es: extern struct {
-                    far: u64, // Virtual Fault Address
-                    esr: u32, // Exception syndrome
-                    exception: u32, // Number of arm exception taken
-                },
-                ss: extern struct {
-                    /// General purpose registers
-                    regs: [29]u64,
-                    /// Frame pointer x29
-                    fp: u64,
-                    /// Link register x30
+    .linux => switch (native_arch) {
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm64/include/uapi/asm/ucontext.h
+        .aarch64,
+        .aarch64_be,
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/loongarch/include/uapi/asm/ucontext.h
+        .loongarch64,
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/powerpc/include/uapi/asm/ucontext.h
+        .powerpc64,
+        .powerpc64le,
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/riscv/include/uapi/asm/ucontext.h
+        .riscv32,
+        .riscv64,
+        => extern struct {
+            _flags: usize,
+            _link: ?*signal_ucontext_t,
+            _stack: std.os.linux.stack_t,
+            _sigmask: std.os.linux.sigset_t,
+            _unused: [120]u8,
+            mcontext: switch (native_arch) {
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm64/include/uapi/asm/sigcontext.h
+                .aarch64, .aarch64_be => extern struct {
+                    _fault_address: u64 align(16),
+                    x: [30]u64,
                     lr: u64,
-                    /// Stack pointer x31
                     sp: u64,
-                    /// Program counter
                     pc: u64,
-                    /// Current program status register
-                    cpsr: u32,
-                    __pad: u32,
                 },
-                ns: extern struct {
-                    q: [32]u128,
-                    fpsr: u32,
-                    fpcr: u32,
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/loongarch/include/uapi/asm/sigcontext.h
+                .loongarch64 => extern struct {
+                    pc: u64 align(16),
+                    r: [32]u64,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/powerpc/include/uapi/asm/sigcontext.h
+                .powerpc64, .powerpc64le => extern struct {
+                    _unused: [4]u64,
+                    _signal: i32,
+                    _pad: i32,
+                    _handler: u64,
+                    _oldmask: u64,
+                    _regs: ?*anyopaque,
+                    r: [32]u64,
+                    pc: u64,
+                    _msr: u64,
+                    _orig_r3: u64,
+                    _ctr: u64,
+                    lr: u64,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/riscv/include/uapi/asm/sigcontext.h
+                .riscv32, .riscv64 => extern struct {
+                    pc: usize align(16),
+                    ra_sp_gp_tp: [4]usize,
+                    t0_2: [3]usize,
+                    s0_1: [2]usize,
+                    a: [8]usize,
+                    s2_11: [10]usize,
+                    t3_6: [4]usize,
                 },
+                else => unreachable,
             },
-            .x86_64 => extern struct {
-                es: extern struct {
-                    trapno: u16,
-                    cpu: u16,
-                    err: u32,
-                    faultvaddr: u64,
+        },
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/include/uapi/asm-generic/ucontext.h
+        .arc,
+        .csky,
+        .hexagon,
+        .m68k,
+        .mips,
+        .mipsel,
+        .mips64,
+        .mips64el,
+        .or1k,
+        .s390x,
+        .x86,
+        .x86_64,
+        .xtensa,
+        => extern struct {
+            _flags: usize,
+            _link: ?*signal_ucontext_t,
+            _stack: std.os.linux.stack_t,
+            mcontext: switch (native_arch) {
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arc/include/uapi/asm/sigcontext.h
+                .arc => extern struct {
+                    _pad1: u32,
+                    _bta: u32,
+                    _lp: extern struct {
+                        _start: u32,
+                        _end: u32,
+                        _count: u32,
+                    },
+                    _status32: u32,
+                    pc: u32,
+                    r31: u32,
+                    r27_26: [2]u32,
+                    r12_0: [13]u32,
+                    r28: u32,
+                    _pad2: u32,
+                    r25_13: [13]u32,
+                    _efa: u32,
+                    _stop_pc: u32,
+                    r30: u32,
                 },
-                ss: extern struct {
-                    rax: u64,
-                    rbx: u64,
-                    rcx: u64,
-                    rdx: u64,
-                    rdi: u64,
-                    rsi: u64,
-                    rbp: u64,
-                    rsp: u64,
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/csky/include/uapi/asm/sigcontext.h
+                .csky => extern struct {
+                    r31: u32,
+                    r15: u32,
+                    pc: u32,
+                    _sr: u32,
+                    r14: u32,
+                    _orig_a0: u32,
+                    r0_13: [14]u32,
+                    r16_30: [15]u32,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/hexagon/include/uapi/asm/sigcontext.h
+                .hexagon => extern struct {
+                    r: [32]u32 align(8),
+                    _salc: [2]extern struct {
+                        _sa: u32,
+                        _lc: u32,
+                    },
+                    _m: [2]u32,
+                    _usr: u32,
+                    _p: u32,
+                    _gp: u32,
+                    _ugp: u32,
+                    pc: u32,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/m68k/include/asm/ucontext.h
+                .m68k => extern struct {
+                    _version: i32,
+                    d: [8]u32,
+                    a: [8]u32,
+                    pc: u32,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/mips/include/uapi/asm/sigcontext.h
+                .mips, .mipsel => extern struct {
+                    _regmask: u32,
+                    _status: u32,
+                    // ??? A spectacularly failed attempt to be future-proof?
+                    pc: u64,
+                    r: [32]u64,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/mips/include/uapi/asm/sigcontext.h
+                .mips64, .mips64el => extern struct {
+                    r: [32]u64,
+                    _fpregs: [32]u64,
+                    _hi: [4]u64,
+                    _lo: [4]u64,
+                    pc: u64,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/openrisc/include/uapi/asm/sigcontext.h
+                .or1k => extern struct {
+                    r: [32]u32,
+                    pc: u32,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/s390/include/uapi/asm/sigcontext.h
+                .s390x => extern struct {
+                    psw: extern struct {
+                        mask: u64,
+                        addr: u64,
+                    },
+                    r: [16]u64,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/x86/include/uapi/asm/sigcontext.h
+                .x86 => extern struct {
+                    _gs: u32,
+                    _fs: u32,
+                    _es: u32,
+                    _ds: u32,
+                    edi: u32,
+                    esi: u32,
+                    ebp: u32,
+                    esp: u32,
+                    ebx: u32,
+                    edx: u32,
+                    ecx: u32,
+                    eax: u32,
+                    _trapno: u32,
+                    _err: u32,
+                    eip: u32,
+                },
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/x86/include/uapi/asm/sigcontext.h
+                .x86_64 => extern struct {
                     r8: u64,
                     r9: u64,
                     r10: u64,
@@ -1201,197 +1202,540 @@ const signal_ucontext_t = switch (native_os) {
                     r13: u64,
                     r14: u64,
                     r15: u64,
+                    rdi: u64,
+                    rsi: u64,
+                    rbp: u64,
+                    rbx: u64,
+                    rdx: u64,
+                    rax: u64,
+                    rcx: u64,
+                    rsp: u64,
                     rip: u64,
-                    rflags: u64,
-                    cs: u64,
-                    fs: u64,
-                    gs: u64,
                 },
-                fs: extern struct {
-                    reserved: [2]c_int,
-                    fcw: u16,
-                    fsw: u16,
-                    ftw: u8,
-                    rsrv1: u8,
-                    fop: u16,
-                    ip: u32,
-                    cs: u16,
-                    rsrv2: u16,
-                    dp: u32,
-                    ds: u16,
-                    rsrv3: u16,
-                    mxcsr: u32,
-                    mxcsrmask: u32,
-                    stmm: [8]stmm_reg,
-                    xmm: [16]xmm_reg,
-                    rsrv4: [96]u8,
-                    reserved1: c_int,
-
-                    const stmm_reg = [16]u8;
-                    const xmm_reg = [16]u8;
+                // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/xtensa/include/uapi/asm/sigcontext.h
+                .xtensa => extern struct {
+                    pc: u32,
+                    _ps: u32,
+                    _l: extern struct {
+                        _beg: u32,
+                        _end: u32,
+                        _count: u32,
+                    },
+                    _sar: u32,
+                    _acc: extern struct {
+                        _lo: u32,
+                        _hi: u32,
+                    },
+                    a: [16]u32,
                 },
+                else => unreachable,
             },
-            else => void,
-        };
+        },
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm/include/asm/ucontext.h
+        .arm, .armeb, .thumb, .thumbeb => extern struct {
+            _flags: u32,
+            _link: ?*signal_ucontext_t,
+            _stack: std.os.linux.stack_t,
+            _unused: [31]i32,
+            // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm/include/uapi/asm/sigcontext.h
+            mcontext: extern struct {
+                _trap_no: u32,
+                _error_code: u32,
+                _oldmask: u32,
+                r: [15]u32,
+                pc: u32,
+            },
+        },
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/powerpc/include/uapi/asm/ucontext.h
+        .powerpc, .powerpcle => extern struct {
+            _flags: u32,
+            _link: ?*signal_ucontext_t,
+            _stack: std.os.linux.stack_t,
+            _pad1: [7]i32,
+            _regs: ?*anyopaque,
+            _sigmask: std.os.linux.sigset_t,
+            _unused: [120]u8,
+            _pad2: [3]i32,
+            mcontext: extern struct {
+                r: [32]u32 align(16),
+                pc: u32,
+                _msr: u32,
+                _orig_r3: u32,
+                _ctr: u32,
+                lr: u32,
+            },
+        },
+        // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/sparc/include/uapi/asm/uctx.h
+        .sparc => @compileError("sparc-linux ucontext_t missing"),
+        .sparc64 => @compileError("sparc64-linux ucontext_t missing"),
+        else => unreachable,
     },
-    .solaris, .illumos => extern struct {
-        flags: u64,
-        link: ?*signal_ucontext_t,
-        sigmask: std.c.sigset_t,
-        stack: std.c.stack_t,
-        mcontext: mcontext_t,
-        brand_data: [3]?*anyopaque,
-        filler: [2]i64,
-        const mcontext_t = extern struct {
-            gregs: [28]u64,
-            fpregs: std.c.fpregset_t,
-        };
+    // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/sys/_ucontext.h
+    .freebsd => extern struct {
+        _sigmask: std.c.sigset_t,
+        mcontext: switch (native_arch) {
+            // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/arm64/include/ucontext.h
+            .aarch64 => extern struct {
+                x: [30]u64 align(16),
+                lr: u64,
+                sp: u64,
+                pc: u64,
+            },
+            // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/arm/include/ucontext.h
+            .arm => extern struct {
+                r: [15]u32,
+                pc: u32,
+            },
+            // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/powerpc/include/ucontext.h
+            .powerpc64, .powerpc64le => extern struct {
+                _vers: i32 align(16),
+                _flags: i32,
+                _onstack: i32,
+                _len: i32,
+                _avec: [32 * 2]u64,
+                _av: [2]u32,
+                r: [32]u64,
+                lr: u64,
+                _cr: u64,
+                _xer: u64,
+                _ctr: u64,
+                pc: u64,
+            },
+            // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/riscv/include/ucontext.h
+            .riscv64 => extern struct {
+                ra_sp_gp_tp: [4]u64,
+                t0_2: [3]u64,
+                t3_6: [4]u64,
+                s0_1: [2]u64,
+                s2_11: [10]u64,
+                a: [8]u64,
+                pc: u64,
+            },
+            // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/x86/include/ucontext.h
+            .x86_64 => extern struct {
+                _onstack: i64,
+                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: i32,
+                _fs: i16,
+                _gs: i16,
+                _addr: i64,
+                _flags: i32,
+                _es: i16,
+                _ds: i16,
+                _err: i64,
+                rip: u64,
+                _cs: i64,
+                _rflags: i64,
+                rsp: u64,
+            },
+            else => unreachable,
+        },
     },
-    .openbsd => switch (builtin.cpu.arch) {
-        .x86_64 => extern struct {
-            sc_rdi: c_long,
-            sc_rsi: c_long,
-            sc_rdx: c_long,
-            sc_rcx: c_long,
-            sc_r8: c_long,
-            sc_r9: c_long,
-            sc_r10: c_long,
-            sc_r11: c_long,
-            sc_r12: c_long,
-            sc_r13: c_long,
-            sc_r14: c_long,
-            sc_r15: c_long,
-            sc_rbp: c_long,
-            sc_rbx: c_long,
-            sc_rax: c_long,
-            sc_gs: c_long,
-            sc_fs: c_long,
-            sc_es: c_long,
-            sc_ds: c_long,
-            sc_trapno: c_long,
-            sc_err: c_long,
-            sc_rip: c_long,
-            sc_cs: c_long,
-            sc_rflags: c_long,
-            sc_rsp: c_long,
-            sc_ss: c_long,
-
-            sc_fpstate: *anyopaque, // struct fxsave64 *
-            __sc_unused: c_int,
-            sc_mask: c_int,
-            sc_cookie: c_long,
+    // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/sys/_types/_ucontext.h
+    .driverkit, .macos, .ios, .tvos, .watchos, .visionos => extern struct {
+        _onstack: i32,
+        _sigmask: std.c.sigset_t,
+        _stack: std.c.stack_t,
+        _link: ?*signal_ucontext_t,
+        _mcsize: u64,
+        mcontext: *switch (native_arch) {
+            // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/arm/_mcontext.h
+            // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/mach/arm/_structs.h
+            .aarch64 => extern struct {
+                _far: u64 align(16),
+                _esr: u64,
+                x: [30]u64,
+                lr: u64,
+                sp: u64,
+                pc: u64,
+            },
+            // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/i386/_mcontext.h
+            // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/mach/i386/_structs.h
+            .x86_64 => extern struct {
+                _trapno: u16,
+                _cpu: u16,
+                _err: u32,
+                _faultvaddr: u64,
+                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,
+            },
+            else => unreachable,
         },
+    },
+    // This needs to be audited by someone with access to the Solaris headers.
+    .solaris => extern struct {
+        _flags: u64,
+        _link: ?*signal_ucontext_t,
+        _sigmask: std.c.sigset_t,
+        _stack: std.c.stack_t,
+        mcontext: switch (native_arch) {
+            .sparc64 => @compileError("sparc64-solaris mcontext_t missing"),
+            .x86_64 => extern struct {
+                r15: u64,
+                r14: u64,
+                r13: u64,
+                r12: u64,
+                r11: u64,
+                r10: u64,
+                r9: u64,
+                r8: u64,
+                rdi: u64,
+                rsi: u64,
+                rbp: u64,
+                rbx: u64,
+                rdx: u64,
+                rcx: u64,
+                rax: u64,
+                _trapno: i64,
+                _err: i64,
+                rip: u64,
+            },
+            else => unreachable,
+        },
+    },
+    // https://github.com/illumos/illumos-gate/blob/d4ce137bba3bd16823db6374d9e9a643264ce245/usr/src/uts/intel/sys/ucontext.h
+    .illumos => extern struct {
+        _flags: usize,
+        _link: ?*signal_ucontext_t,
+        _sigmask: std.c.sigset_t,
+        _stack: std.c.stack_t,
+        mcontext: switch (native_arch) {
+            // https://github.com/illumos/illumos-gate/blob/d4ce137bba3bd16823db6374d9e9a643264ce245/usr/src/uts/intel/sys/mcontext.h
+            .x86 => extern struct {
+                _gs: u32,
+                _fs: u32,
+                _es: u32,
+                _ds: u32,
+                edi: u32,
+                esi: u32,
+                ebp: u32,
+                esp: u32,
+                ebx: u32,
+                edx: u32,
+                ecx: u32,
+                eax: u32,
+                _trapno: i32,
+                _err: i32,
+                eip: u32,
+            },
+            .x86_64 => extern struct {
+                r15: u64,
+                r14: u64,
+                r13: u64,
+                r12: u64,
+                r11: u64,
+                r10: u64,
+                r9: u64,
+                r8: u64,
+                rdi: u64,
+                rsi: u64,
+                rbp: u64,
+                rbx: u64,
+                rdx: u64,
+                rcx: u64,
+                rax: u64,
+                _trapno: i64,
+                _err: i64,
+                rip: u64,
+            },
+            else => unreachable,
+        },
+    },
+    .openbsd => switch (native_arch) {
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/arm64/include/signal.h
         .aarch64 => extern struct {
-            __sc_unused: c_int,
-            sc_mask: c_int,
-            sc_sp: c_ulong,
-            sc_lr: c_ulong,
-            sc_elr: c_ulong,
-            sc_spsr: c_ulong,
-            sc_x: [30]c_ulong,
-            sc_cookie: c_long,
+            _unused: i32,
+            _mask: i32,
+            mcontext: extern struct {
+                sp: u64,
+                lr: u64,
+                pc: u64,
+                _spsr: u64,
+                x: [30]u64,
+            },
+        },
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/arm/include/signal.h
+        .arm => extern struct {
+            _cookie: i32,
+            _mask: i32,
+            mcontext: extern struct {
+                _spsr: u32 align(8),
+                r: [15]u32,
+                _svc_lr: u32,
+                pc: u32,
+            },
         },
-        else => void,
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/mips64/include/signal.h
+        .mips64, .mips64el => extern struct {
+            _cookie: i64,
+            _mask: i64,
+            mcontext: extern struct {
+                pc: u64,
+                r: [32]u64,
+            },
+        },
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/powerpc/include/signal.h
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/powerpc64/include/signal.h
+        .powerpc, .powerpc64 => extern struct {
+            _cookie: isize,
+            _mask: i32,
+            mcontext: extern struct {
+                r: [32]usize,
+                lr: usize,
+                _cr: usize,
+                _xer: usize,
+                _ctr: usize,
+                pc: usize,
+            },
+        },
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/riscv64/include/signal.h
+        .riscv64 => extern struct {
+            _unused: i32,
+            _mask: i32,
+            mcontext: extern struct {
+                ra_sp_gp_tp: [4]u64,
+                t0_2: [3]u64,
+                t3_6: [4]u64,
+                s0_1: [2]u64,
+                s2_11: [10]u64,
+                a: [8]u64,
+                pc: u64,
+            },
+        },
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sparc64/include/signal.h
+        .sparc64 => @compileError("sparc64-openbsd mcontext_t missing"),
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/i386/include/signal.h
+        .x86 => extern struct {
+            mcontext: extern struct {
+                _gs: i32,
+                _fs: i32,
+                _es: i32,
+                _ds: i32,
+                edi: u32,
+                esi: u32,
+                ebp: u32,
+                ebx: u32,
+                edx: u32,
+                ecx: u32,
+                eax: u32,
+                eip: u32,
+                _cs: i32,
+                _eflags: i32,
+                esp: u32,
+            },
+        },
+        // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/amd64/include/signal.h
+        .x86_64 => extern struct {
+            mcontext: extern struct {
+                rdi: u64,
+                rsi: u64,
+                rdx: u64,
+                rcx: u64,
+                r8: u64,
+                r9: u64,
+                r10: u64,
+                r11: u64,
+                r12: u64,
+                r13: u64,
+                r14: u64,
+                r15: u64,
+                rbp: u64,
+                rbx: u64,
+                rax: u64,
+                _gs: i64,
+                _fs: i64,
+                _es: i64,
+                _ds: i64,
+                _trapno: i64,
+                _err: i64,
+                rip: u64,
+                _cs: i64,
+                _rflags: i64,
+                rsp: u64,
+            },
+        },
+        else => unreachable,
     },
+    // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/sys/ucontext.h
     .netbsd => extern struct {
-        flags: u32,
-        link: ?*signal_ucontext_t,
-        sigmask: std.c.sigset_t,
-        stack: std.c.stack_t,
-        mcontext: mcontext_t,
-        __pad: [
-            switch (builtin.cpu.arch) {
-                .x86 => 4,
-                .mips, .mipsel, .mips64, .mips64el => 14,
-                .arm, .armeb, .thumb, .thumbeb => 1,
-                .sparc, .sparc64 => if (@sizeOf(usize) == 4) 43 else 8,
-                else => 0,
-            }
-        ]u32,
-        const mcontext_t = switch (builtin.cpu.arch) {
+        _flags: u32,
+        _link: ?*signal_ucontext_t,
+        _sigmask: std.c.sigset_t,
+        _stack: std.c.stack_t,
+        mcontext: switch (native_arch) {
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/arm/include/mcontext.h
             .aarch64, .aarch64_be => extern struct {
-                gregs: [35]u64,
-                fregs: [528]u8 align(16),
-                spare: [8]u64,
+                x: [30]u64 align(16),
+                lr: u64,
+                sp: u64,
+                pc: u64,
+            },
+            .arm, .armeb => extern struct {
+                r: [15]u32 align(8),
+                pc: u32,
             },
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/m68k/include/mcontext.h
+            .m68k => extern struct {
+                d: [8]u32,
+                a: [8]u32,
+                pc: u32,
+            },
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/mips/include/mcontext.h
+            .mips, .mipsel => extern struct {
+                r: [32]u32 align(8),
+                _lo: i32,
+                _hi: i32,
+                _cause: i32,
+                pc: u32,
+            },
+            .mips64, .mips64el => @compileError("https://github.com/ziglang/zig/issues/23765#issuecomment-2880386178"),
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/powerpc/include/mcontext.h
+            .powerpc => extern struct {
+                r: [32]u32 align(16),
+                _cr: i32,
+                lr: u32,
+                pc: u32,
+            },
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sparc/include/mcontext.h
+            .sparc => @compileError("sparc-netbsd mcontext_t missing"),
+            .sparc64 => @compileError("sparc64-netbsd mcontext_t missing"),
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/i386/include/mcontext.h
             .x86 => extern struct {
-                gregs: [19]u32,
-                fpregs: [161]u32,
-                mc_tlsbase: u32,
+                _gs: i32,
+                _fs: i32,
+                _es: i32,
+                _ds: i32,
+                edi: u32,
+                esi: u32,
+                ebp: u32,
+                esp: u32,
+                ebx: u32,
+                edx: u32,
+                ecx: u32,
+                eax: u32,
+                _trapno: i32,
+                _err: i32,
+                eip: u32,
             },
+            // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/amd64/include/mcontext.h
             .x86_64 => extern struct {
-                gregs: [26]u64,
-                mc_tlsbase: u64,
-                fpregs: [512]u8 align(8),
+                rdi: u64,
+                rsi: u64,
+                rdx: u64,
+                rcx: u64,
+                r8: u64,
+                r9: u64,
+                r10: u64,
+                r11: u64,
+                r12: u64,
+                r13: u64,
+                r14: u64,
+                r15: u64,
+                rbp: u64,
+                rbx: u64,
+                rax: u64,
+                _gs: i64,
+                _fs: i64,
+                _es: i64,
+                _ds: i64,
+                _trapno: i64,
+                _err: i64,
+                rip: u64,
+                _cs: i64,
+                _rflags: i64,
+                rsp: u64,
             },
-            else => void,
-        };
+            else => unreachable,
+        },
     },
+    // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/3de1e9d36269616d22237f19d60a737a41271ab5/sys/sys/_ucontext.h
     .dragonfly => extern struct {
-        sigmask: std.c.sigset_t,
-        mcontext: mcontext_t,
-        link: ?*signal_ucontext_t,
-        stack: std.c.stack_t,
-        cofunc: ?*fn (?*signal_ucontext_t, ?*anyopaque) void,
-        arg: ?*void,
-        _spare: [4]c_int,
-        const mcontext_t = extern struct {
-            const register_t = isize;
-            onstack: register_t, // XXX - sigcontext compat.
-            rdi: register_t,
-            rsi: register_t,
-            rdx: register_t,
-            rcx: register_t,
-            r8: register_t,
-            r9: register_t,
-            rax: register_t,
-            rbx: register_t,
-            rbp: register_t,
-            r10: register_t,
-            r11: register_t,
-            r12: register_t,
-            r13: register_t,
-            r14: register_t,
-            r15: register_t,
-            xflags: register_t,
-            trapno: register_t,
-            addr: register_t,
-            flags: register_t,
-            err: register_t,
-            rip: register_t,
-            cs: register_t,
-            rflags: register_t,
-            rsp: register_t, // machine state
-            ss: register_t,
-
-            len: c_uint, // sizeof(mcontext_t)
-            fpformat: c_uint,
-            ownedfp: c_uint,
-            reserved: c_uint,
-            unused: [8]c_uint,
-
-            // NOTE! 64-byte aligned as of here. Also must match savefpu structure.
-            fpregs: [256]c_int align(64),
-        };
+        _sigmask: std.c.sigset_t,
+        mcontext: switch (native_arch) {
+            // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/3de1e9d36269616d22237f19d60a737a41271ab5/sys/cpu/x86_64/include/ucontext.h
+            .x86_64 => extern struct {
+                _onstack: i64 align(64),
+                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,
+                _xflags: i64,
+                _trapno: i64,
+                _addr: i64,
+                _flags: i64,
+                _err: i64,
+                rip: u64,
+                _cs: i64,
+                _rflags: i64,
+                rsp: u64,
+            },
+            else => unreachable,
+        },
     },
+    // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/API/POSIX/ucontext.h
     .serenity => extern struct {
-        link: ?*signal_ucontext_t,
-        sigmask: std.c.sigset_t,
-        stack: std.c.stack_t,
-        mcontext: mcontext_t,
-        const mcontext_t = switch (builtin.cpu.arch) {
-            // https://github.com/SerenityOS/serenity/blob/200e91cd7f1ec5453799a2720d4dc114a59cc289/Kernel/Arch/aarch64/mcontext.h#L15-L19
+        _link: ?*signal_ucontext_t,
+        _sigmask: std.c.sigset_t,
+        _stack: std.c.stack_t,
+        mcontext: switch (native_arch) {
+            // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/Arch/aarch64/mcontext.h
             .aarch64 => extern struct {
-                x: [31]u64,
+                x: [30]u64,
+                lr: u64,
                 sp: u64,
                 pc: u64,
             },
-            // https://github.com/SerenityOS/serenity/blob/66f8d0f031ef25c409dbb4fecaa454800fecae0f/Kernel/Arch/riscv64/mcontext.h#L15-L18
+            // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/Arch/riscv64/mcontext.h
             .riscv64 => extern struct {
-                x: [31]u64,
+                ra_sp_gp_tp: [4]u64,
+                t0_2: [3]u64,
+                s0_1: [2]u64,
+                a: [8]u64,
+                s2_11: [10]u64,
+                t3_6: [4]u64,
                 pc: u64,
             },
-            // https://github.com/SerenityOS/serenity/blob/7b9ea3efdec9f86a1042893e8107d0b23aad8727/Kernel/Arch/x86_64/mcontext.h#L15-L40
+            // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/Arch/x86_64/mcontext.h
             .x86_64 => extern struct {
                 rax: u64,
                 rcx: u64,
@@ -1410,262 +1754,103 @@ const signal_ucontext_t = switch (native_os) {
                 r13: u64,
                 r14: u64,
                 r15: u64,
-                rflags: u64,
-                cs: u32,
-                ss: u32,
-                ds: u32,
-                es: u32,
-                fs: u32,
-                gs: u32,
             },
-            else => void,
-        };
+            else => unreachable,
+        },
     },
+    // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/signal.h#L356
     .haiku => extern struct {
-        link: ?*signal_ucontext_t,
-        sigmask: std.c.sigset_t,
-        stack: std.c.stack_t,
-        mcontext: mcontext_t,
-        const mcontext_t = switch (builtin.cpu.arch) {
-            .arm, .thumb => extern struct {
-                r0: u32,
-                r1: u32,
-                r2: u32,
-                r3: u32,
-                r4: u32,
-                r5: u32,
-                r6: u32,
-                r7: u32,
-                r8: u32,
-                r9: u32,
-                r10: u32,
-                r11: u32,
-                r12: u32,
-                r13: u32,
-                r14: u32,
-                r15: u32,
-                cpsr: u32,
+        _link: ?*signal_ucontext_t,
+        _sigmask: std.c.sigset_t,
+        _stack: std.c.stack_t,
+        mcontext: switch (native_arch) {
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/arm/signal.h
+            .arm => extern struct {
+                r: [15]u32 align(8),
+                pc: u32,
             },
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/arm64/signal.h
             .aarch64 => extern struct {
-                x: [10]u64,
+                x: [30]u64 align(16),
                 lr: u64,
                 sp: u64,
-                elr: u64,
-                spsr: u64,
-                fp_q: [32]u128,
-                fpsr: u32,
-                fpcr: u32,
+                pc: u64,
             },
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/m68k/signal.h
             .m68k => extern struct {
-                pc: u32,
-                d0: u32,
-                d1: u32,
-                d2: u32,
-                d3: u32,
-                d4: u32,
-                d5: u32,
-                d6: u32,
-                d7: u32,
-                a0: u32,
-                a1: u32,
-                a2: u32,
-                a3: u32,
-                a4: u32,
-                a5: u32,
-                a6: u32,
-                a7: u32,
-                ccr: u8,
-                f0: f64,
-                f1: f64,
-                f2: f64,
-                f3: f64,
-                f4: f64,
-                f5: f64,
-                f6: f64,
-                f7: f64,
-                f8: f64,
-                f9: f64,
-                f10: f64,
-                f11: f64,
-                f12: f64,
-                f13: f64,
-            },
-            .mipsel => extern struct {
-                r0: u32,
+                pc: u32 align(8),
+                d: [8]u32,
+                a: [8]u32,
             },
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/ppc/signal.h
             .powerpc => extern struct {
-                pc: u32,
-                r0: u32,
-                r1: u32,
-                r2: u32,
-                r3: u32,
-                r4: u32,
-                r5: u32,
-                r6: u32,
-                r7: u32,
-                r8: u32,
-                r9: u32,
-                r10: u32,
-                r11: u32,
-                r12: u32,
-                f0: f64,
-                f1: f64,
-                f2: f64,
-                f3: f64,
-                f4: f64,
-                f5: f64,
-                f6: f64,
-                f7: f64,
-                f8: f64,
-                f9: f64,
-                f10: f64,
-                f11: f64,
-                f12: f64,
-                f13: f64,
-                reserved: u32,
-                fpscr: u32,
-                ctr: u32,
-                xer: u32,
-                cr: u32,
-                msr: u32,
+                pc: u32 align(8),
+                r: [13]u32, // Um, are you okay, Haiku?
+                _f: [14]f64,
+                _reserved: u32,
+                _fpscr: u32,
+                _ctr: u32,
+                _xer: u32,
+                _cr: u32,
+                _msr: u32,
                 lr: u32,
             },
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/riscv64/signal.h
             .riscv64 => extern struct {
-                x: [31]u64,
+                ra_sp_gp_tp: [4]u64,
+                t0_2: [3]u64,
+                s0_1: [2]u64,
+                a: [8]u64,
+                s2_11: [10]u64,
+                t3_6: [4]u64,
                 pc: u64,
-                f: [32]f64,
-                fcsr: u64,
-            },
-            .sparc64 => extern struct {
-                g1: u64,
-                g2: u64,
-                g3: u64,
-                g4: u64,
-                g5: u64,
-                g6: u64,
-                g7: u64,
-                o0: u64,
-                o1: u64,
-                o2: u64,
-                o3: u64,
-                o4: u64,
-                o5: u64,
-                sp: u64,
-                o7: u64,
-                l0: u64,
-                l1: u64,
-                l2: u64,
-                l3: u64,
-                l4: u64,
-                l5: u64,
-                l6: u64,
-                l7: u64,
-                i0: u64,
-                i1: u64,
-                i2: u64,
-                i3: u64,
-                i4: u64,
-                i5: u64,
-                fp: u64,
-                i7: u64,
             },
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/sparc64/signal.h
+            .sparc64 => @compileError("sparc64-haiku mcontext_t missing"),
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/x86/signal.h
             .x86 => extern struct {
-                pub const old_extended_regs = extern struct {
-                    control: u16,
-                    reserved1: u16,
-                    status: u16,
-                    reserved2: u16,
-                    tag: u16,
-                    reserved3: u16,
-                    eip: u32,
-                    cs: u16,
-                    opcode: u16,
-                    datap: u32,
-                    ds: u16,
-                    reserved4: u16,
-                    fp_mmx: [8][10]u8,
-                };
-
-                pub const fp_register = extern struct { value: [10]u8, reserved: [6]u8 };
-
-                pub const xmm_register = extern struct { value: [16]u8 };
-
-                pub const new_extended_regs = extern struct {
-                    control: u16,
-                    status: u16,
-                    tag: u16,
-                    opcode: u16,
-                    eip: u32,
-                    cs: u16,
-                    reserved1: u16,
-                    datap: u32,
-                    ds: u16,
-                    reserved2: u16,
-                    mxcsr: u32,
-                    reserved3: u32,
-                    fp_mmx: [8]fp_register,
-                    xmmx: [8]xmm_register,
-                    reserved4: [224]u8,
-                };
-
-                pub const extended_regs = extern struct {
-                    state: extern union {
-                        old_format: old_extended_regs,
-                        new_format: new_extended_regs,
-                    },
-                    format: u32,
-                };
-
                 eip: u32,
-                eflags: u32,
+                _eflags: u32,
                 eax: u32,
                 ecx: u32,
                 edx: u32,
                 esp: u32,
                 ebp: u32,
-                reserved: u32,
-                xregs: extended_regs,
+                _reserved: u32,
+                _xregs: extern struct {
+                    _fp_control: u16,
+                    _fp_status: u16,
+                    _fp_tag: u16,
+                    _fp_opcode: u16,
+                    _fp_eip: u32,
+                    _fp_cs: u16,
+                    _reserved1: u16,
+                    _fp_datap: u32,
+                    _fp_ds: u16,
+                    _reserved2: u16,
+                    _mxcsr: u32,
+                    _mxcsr_mask: u32,
+                    _mmx: [8][16]u8,
+                    _xmmx: [8][16]u8,
+                    _reserved3: [176]u8,
+                    _fault_address: u32,
+                    _error_code: u32,
+                    _cs: u16,
+                    _ds: u16,
+                    _es: u16,
+                    _fs: u16,
+                    _gs: u16,
+                    _ss: u16,
+                    _trap_number: u8,
+                    _reserved4: [27]u8,
+                    _format: u32,
+                },
                 edi: u32,
                 esi: u32,
                 ebx: u32,
             },
+            // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/x86_64/signal.h
             .x86_64 => extern struct {
-                pub const fp_register = extern struct {
-                    value: [10]u8,
-                    reserved: [6]u8,
-                };
-
-                pub const xmm_register = extern struct {
-                    value: [16]u8,
-                };
-
-                pub const fpu_state = extern struct {
-                    control: u16,
-                    status: u16,
-                    tag: u16,
-                    opcode: u16,
-                    rip: u64,
-                    rdp: u64,
-                    mxcsr: u32,
-                    mscsr_mask: u32,
-
-                    fp_mmx: [8]fp_register,
-                    xmm: [16]xmm_register,
-                    reserved: [96]u8,
-                };
-
-                pub const xstate_hdr = extern struct {
-                    bv: u64,
-                    xcomp_bv: u64,
-                    reserved: [48]u8,
-                };
-
-                pub const savefpu = extern struct {
-                    fxsave: fpu_state,
-                    xstate: xstate_hdr,
-                    ymm: [16]xmm_register,
-                };
-
                 rax: u64,
                 rbx: u64,
                 rcx: u64,
@@ -1683,11 +1868,9 @@ const signal_ucontext_t = switch (native_os) {
                 r15: u64,
                 rsp: u64,
                 rip: u64,
-                rflags: u64,
-                fpu: savefpu,
             },
-            else => void,
-        };
+            else => unreachable,
+        },
     },
     else => void,
 };
lib/std/debug.zig
@@ -1315,15 +1315,26 @@ fn getDebugInfoAllocator() 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) {
+    .haiku,
     .linux,
-    .macos,
+    .serenity,
+
+    .dragonfly,
+    .freebsd,
     .netbsd,
-    .solaris,
+    .openbsd,
+
+    .driverkit,
+    .ios,
+    .macos,
+    .tvos,
+    .visionos,
+    .watchos,
+
     .illumos,
+    .solaris,
+
     .windows,
-    .freebsd,
-    .openbsd,
-    .serenity,
     => true,
 
     else => false,
@@ -1406,11 +1417,26 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
             }
         }
         const addr: usize = switch (native_os) {
-            .linux => @intFromPtr(info.fields.sigfault.addr),
-            .freebsd, .macos, .serenity => @intFromPtr(info.addr),
-            .netbsd => @intFromPtr(info.info.reason.fault.addr),
-            .openbsd => @intFromPtr(info.data.fault.addr),
-            .solaris, .illumos => @intFromPtr(info.reason.fault.addr),
+            .serenity,
+            .dragonfly,
+            .freebsd,
+            .driverkit,
+            .ios,
+            .macos,
+            .tvos,
+            .visionos,
+            .watchos,
+            => @intFromPtr(info.addr),
+            .linux,
+            => @intFromPtr(info.fields.sigfault.addr),
+            .netbsd,
+            => @intFromPtr(info.info.reason.fault.addr),
+            .haiku,
+            .openbsd,
+            => @intFromPtr(info.data.fault.addr),
+            .illumos,
+            .solaris,
+            => @intFromPtr(info.reason.fault.addr),
             else => comptime unreachable,
         };
         const name = switch (sig) {