authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-05-25 13:11:21-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:13-04:00
log2f75d20d87fe68eb2695acd37fc2364c06c4c582
treee002f84e8e47bdc303baab0316cbecef366a614f
parentd74c8acdfbf297587db2c85a85808bcedbb9e219

debug: use an explicit context type instead of anytype for dumpStackTraceFromBase, update crash_report to use this for exceptions


2 files changed, 20 insertions(+), 56 deletions(-)

lib/std/debug.zig+11-2
...@@ -133,11 +133,20 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {...@@ -133,11 +133,20 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
133 }133 }
134}134}
135135
136pub const StackTraceContext = blk: {
137 if (native_os == .windows) {
138 break :blk @typeInfo(@TypeOf(os.windows.CONTEXT.getRegs)).Fn.return_type.?;
139 } else if (@hasDecl(os.system, "ucontext_t")) {
140 break :blk *const os.ucontext_t;
141 } else {
142 break :blk void;
143 }
144};
145
136/// Tries to print the stack trace starting from the supplied base pointer to stderr,146/// Tries to print the stack trace starting from the supplied base pointer to stderr,
137/// unbuffered, and ignores any error returned.147/// unbuffered, and ignores any error returned.
138/// `context` is either *const os.ucontext_t on posix, or the result of CONTEXT.getRegs() on Windows.
139/// TODO multithreaded awareness148/// TODO multithreaded awareness
140pub fn dumpStackTraceFromBase(context: anytype) void {149pub fn dumpStackTraceFromBase(context: StackTraceContext) void {
141 nosuspend {150 nosuspend {
142 if (comptime builtin.target.isWasm()) {151 if (comptime builtin.target.isWasm()) {
143 if (native_os == .wasi) {152 if (native_os == .wasi) {
src/crash_report.zig+9-54
...@@ -203,53 +203,11 @@ fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any...@@ -203,53 +203,11 @@ fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
203 };203 };
204204
205 const stack_ctx: StackContext = switch (builtin.cpu.arch) {205 const stack_ctx: StackContext = switch (builtin.cpu.arch) {
206 .x86 => ctx: {206 .x86,
207 const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));207 .x86_64,
208 const ip = @as(usize, @intCast(ctx.mcontext.gregs[os.REG.EIP]));208 .arm,
209 const bp = @as(usize, @intCast(ctx.mcontext.gregs[os.REG.EBP]));209 .aarch64,
210 break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };210 => StackContext{ .exception = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)) },
211 },
212 .x86_64 => ctx: {
213 const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
214 const ip = switch (builtin.os.tag) {
215 .linux, .netbsd, .solaris => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.RIP])),
216 .freebsd => @as(usize, @intCast(ctx.mcontext.rip)),
217 .openbsd => @as(usize, @intCast(ctx.sc_rip)),
218 .macos => @as(usize, @intCast(ctx.mcontext.ss.rip)),
219 else => unreachable,
220 };
221 const bp = switch (builtin.os.tag) {
222 .linux, .netbsd, .solaris => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.RBP])),
223 .openbsd => @as(usize, @intCast(ctx.sc_rbp)),
224 .freebsd => @as(usize, @intCast(ctx.mcontext.rbp)),
225 .macos => @as(usize, @intCast(ctx.mcontext.ss.rbp)),
226 else => unreachable,
227 };
228 break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
229 },
230 .arm => ctx: {
231 const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
232 const ip = @as(usize, @intCast(ctx.mcontext.arm_pc));
233 const bp = @as(usize, @intCast(ctx.mcontext.arm_fp));
234 break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
235 },
236 .aarch64 => ctx: {
237 const ctx: *const os.ucontext_t = @ptrCast(@alignCast(ctx_ptr));
238 const ip = switch (native_os) {
239 .macos => @as(usize, @intCast(ctx.mcontext.ss.pc)),
240 .netbsd => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.PC])),
241 .freebsd => @as(usize, @intCast(ctx.mcontext.gpregs.elr)),
242 else => @as(usize, @intCast(ctx.mcontext.pc)),
243 };
244 // x29 is the ABI-designated frame pointer
245 const bp = switch (native_os) {
246 .macos => @as(usize, @intCast(ctx.mcontext.ss.fp)),
247 .netbsd => @as(usize, @intCast(ctx.mcontext.gregs[os.REG.FP])),
248 .freebsd => @as(usize, @intCast(ctx.mcontext.gpregs.x[os.REG.FP])),
249 else => @as(usize, @intCast(ctx.mcontext.regs[29])),
250 };
251 break :ctx StackContext{ .exception = .{ .bp = bp, .ip = ip } };
252 },
253 else => .not_supported,211 else => .not_supported,
254 };212 };
255213
...@@ -277,7 +235,7 @@ fn handleSegfaultWindowsExtra(info: *os.windows.EXCEPTION_POINTERS, comptime msg...@@ -277,7 +235,7 @@ fn handleSegfaultWindowsExtra(info: *os.windows.EXCEPTION_POINTERS, comptime msg
277235
278 const stack_ctx = if (@hasDecl(os.windows, "CONTEXT")) ctx: {236 const stack_ctx = if (@hasDecl(os.windows, "CONTEXT")) ctx: {
279 const regs = info.ContextRecord.getRegs();237 const regs = info.ContextRecord.getRegs();
280 break :ctx StackContext{ .exception = .{ .bp = regs.bp, .ip = regs.ip } };238 break :ctx StackContext{ .exception = regs };
281 } else ctx: {239 } else ctx: {
282 const addr = @intFromPtr(info.ExceptionRecord.ExceptionAddress);240 const addr = @intFromPtr(info.ExceptionRecord.ExceptionAddress);
283 break :ctx StackContext{ .current = .{ .ret_addr = addr } };241 break :ctx StackContext{ .current = .{ .ret_addr = addr } };
...@@ -314,10 +272,7 @@ const StackContext = union(enum) {...@@ -314,10 +272,7 @@ const StackContext = union(enum) {
314 current: struct {272 current: struct {
315 ret_addr: ?usize,273 ret_addr: ?usize,
316 },274 },
317 exception: struct {275 exception: debug.StackTraceContext,
318 bp: usize,
319 ip: usize,
320 },
321 not_supported: void,276 not_supported: void,
322277
323 pub fn dumpStackTrace(ctx: @This()) void {278 pub fn dumpStackTrace(ctx: @This()) void {
...@@ -325,8 +280,8 @@ const StackContext = union(enum) {...@@ -325,8 +280,8 @@ const StackContext = union(enum) {
325 .current => |ct| {280 .current => |ct| {
326 debug.dumpCurrentStackTrace(ct.ret_addr);281 debug.dumpCurrentStackTrace(ct.ret_addr);
327 },282 },
328 .exception => |ex| {283 .exception => |context| {
329 debug.dumpStackTraceFromBase(ex.bp, ex.ip);284 debug.dumpStackTraceFromBase(context);
330 },285 },
331 .not_supported => {286 .not_supported => {
332 const stderr = io.getStdErr().writer();287 const stderr = io.getStdErr().writer();