Commit c4237e8909

Cezary Kupaj <zenshixd@proton.me>
2025-05-14 05:38:38
Fix SIGSEGV handler for AArch64 Darwin targets
* ucontext_t ptr is 8-byte aligned instead of 16-byte aligned which @alignCast() expects * Retrieve pc address from ucontext_t since unwind_state is null * Work around __mcontext_data being written incorrectly by the kernel
1 parent 0cb9ffc
Changed files (1)
lib
lib/std/debug.zig
@@ -437,7 +437,13 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
 
         var it = StackIterator.initWithContext(null, debug_info, context) catch return;
         defer it.deinit();
-        printSourceAtAddress(debug_info, stderr, it.unwind_state.?.dwarf_context.pc, tty_config) catch return;
+
+        // DWARF unwinding on aarch64-macos is not complete so we need to get pc address from mcontext
+        const pc_addr = if (builtin.target.os.tag.isDarwin() and native_arch == .aarch64)
+            context.mcontext.ss.pc
+        else
+            it.unwind_state.?.dwarf_context.pc;
+        printSourceAtAddress(debug_info, stderr, pc_addr, tty_config) catch return;
 
         while (it.next()) |return_address| {
             printLastUnwindError(&it, debug_info, stderr, tty_config);
@@ -1480,8 +1486,26 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
         .aarch64,
         .aarch64_be,
         => {
-            const ctx: *posix.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
-            dumpStackTraceFromBase(ctx);
+            // Some kernels don't align `ctx_ptr` properly. Handle this defensively.
+            const ctx: *align(1) posix.ucontext_t = @ptrCast(ctx_ptr);
+            var new_ctx: posix.ucontext_t = ctx.*;
+            if (builtin.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) {
+                // The kernel incorrectly writes the contents of `__mcontext_data` right after `mcontext`,
+                // rather than after the 8 bytes of padding that are supposed to sit between the two. Copy the
+                // contents to the right place so that the `mcontext` pointer will be correct after the
+                // `relocateContext` call below.
+                new_ctx.__mcontext_data = @as(*align(1) extern struct {
+                    onstack: c_int,
+                    sigmask: std.c.sigset_t,
+                    stack: std.c.stack_t,
+                    link: ?*std.c.ucontext_t,
+                    mcsize: u64,
+                    mcontext: *std.c.mcontext_t,
+                    __mcontext_data: std.c.mcontext_t align(@sizeOf(usize)), // Disable padding after `mcontext`.
+                }, @ptrCast(ctx)).__mcontext_data;
+            }
+            relocateContext(&new_ctx);
+            dumpStackTraceFromBase(&new_ctx);
         },
         else => {},
     }