Commit 2f75d20d87

kcbanner <kcbanner@gmail.com>
2023-05-25 19:11:21
debug: use an explicit context type instead of anytype for dumpStackTraceFromBase, update crash_report to use this for exceptions
1 parent d74c8ac
Changed files (2)
lib/std/debug.zig
@@ -133,11 +133,20 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
     }
 }
 
+pub const StackTraceContext = blk: {
+    if (native_os == .windows) {
+        break :blk @typeInfo(@TypeOf(os.windows.CONTEXT.getRegs)).Fn.return_type.?;
+    } else if (@hasDecl(os.system, "ucontext_t")) {
+        break :blk *const os.ucontext_t;
+    } else {
+        break :blk void;
+    }
+};
+
 /// Tries to print the stack trace starting from the supplied base pointer to stderr,
 /// unbuffered, and ignores any error returned.
-/// `context` is either *const os.ucontext_t on posix, or the result of CONTEXT.getRegs() on Windows.
 /// TODO multithreaded awareness
-pub fn dumpStackTraceFromBase(context: anytype) void {
+pub fn dumpStackTraceFromBase(context: StackTraceContext) void {
     nosuspend {
         if (comptime builtin.target.isWasm()) {
             if (native_os == .wasi) {
src/crash_report.zig
@@ -203,53 +203,11 @@ fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
     };
 
     const stack_ctx: StackContext = switch (builtin.cpu.arch) {
-        .x86 => ctx: {
-            const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
-            const ip = @as(usize, @intCast(ctx.mcontext.gregs[os.REG.EIP]));
-            const bp = @as(usize, @intCast(ctx.mcontext.gregs[os.REG.EBP]));
-            break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
-        },
-        .x86_64 => ctx: {
-            const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
-            const ip = switch (builtin.os.tag) {
-                .linux, .netbsd, .solaris => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.RIP])),
-                .freebsd => @as(usize, @intCast(ctx.mcontext.rip)),
-                .openbsd => @as(usize, @intCast(ctx.sc_rip)),
-                .macos => @as(usize, @intCast(ctx.mcontext.ss.rip)),
-                else => unreachable,
-            };
-            const bp = switch (builtin.os.tag) {
-                .linux, .netbsd, .solaris => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.RBP])),
-                .openbsd => @as(usize, @intCast(ctx.sc_rbp)),
-                .freebsd => @as(usize, @intCast(ctx.mcontext.rbp)),
-                .macos => @as(usize, @intCast(ctx.mcontext.ss.rbp)),
-                else => unreachable,
-            };
-            break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
-        },
-        .arm => ctx: {
-            const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
-            const ip = @as(usize, @intCast(ctx.mcontext.arm_pc));
-            const bp = @as(usize, @intCast(ctx.mcontext.arm_fp));
-            break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
-        },
-        .aarch64 => ctx: {
-            const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
-            const ip = switch (native_os) {
-                .macos => @as(usize, @intCast(ctx.mcontext.ss.pc)),
-                .netbsd => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.PC])),
-                .freebsd => @as(usize, @intCast(ctx.mcontext.gpregs.elr)),
-                else => @as(usize, @intCast(ctx.mcontext.pc)),
-            };
-            // x29 is the ABI-designated frame pointer
-            const bp = switch (native_os) {
-                .macos => @as(usize, @intCast(ctx.mcontext.ss.fp)),
-                .netbsd => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.FP])),
-                .freebsd => @as(usize, @intCast(ctx.mcontext.gpregs.x[os.REG.FP])),
-                else => @as(usize, @intCast(ctx.mcontext.regs[29])),
-            };
-            break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
-        },
+        .x86,
+        .x86_64,
+        .arm,
+        .aarch64,
+        => StackContext{ .exception = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)) },
         else => .not_supported,
     };
 
@@ -277,7 +235,7 @@ fn handleSegfaultWindowsExtra(info: *os.windows.EXCEPTION_POINTERS, comptime msg
 
     const stack_ctx = if (@hasDecl(os.windows, "CONTEXT")) ctx: {
         const regs = info.ContextRecord.getRegs();
-        break :ctx StackContext{ .exception = .{ .bp = regs.bp, .ip = regs.ip } };
+        break :ctx StackContext{ .exception = regs };
     } else ctx: {
         const addr = @intFromPtr(info.ExceptionRecord.ExceptionAddress);
         break :ctx StackContext{ .current = .{ .ret_addr = addr } };
@@ -314,10 +272,7 @@ const StackContext = union(enum) {
     current: struct {
         ret_addr: ?usize,
     },
-    exception: struct {
-        bp: usize,
-        ip: usize,
-    },
+    exception: debug.StackTraceContext,
     not_supported: void,
 
     pub fn dumpStackTrace(ctx: @This()) void {
@@ -325,8 +280,8 @@ const StackContext = union(enum) {
             .current => |ct| {
                 debug.dumpCurrentStackTrace(ct.ret_addr);
             },
-            .exception => |ex| {
-                debug.dumpStackTraceFromBase(ex.bp, ex.ip);
+            .exception => |context| {
+                debug.dumpStackTraceFromBase(context);
             },
             .not_supported => {
                 const stderr = io.getStdErr().writer();