diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 2652ad57a8..a8e8b7bce8 100644 --- a/lib/std/debug.zig +++ b/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) { diff --git a/src/crash_report.zig b/src/crash_report.zig index fc41528321..5cd00c5b13 100644 --- a/src/crash_report.zig +++ b/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();