authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-06-26 00:59:28-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:14-04:00
log5cd8ab2473a4255f081f417eb3ec95e1a3a9e9d8
tree2ee974ba827afe762cd96d327019618c95f3a6b8
parenta9b6f2d92984e1b4d4a9fe2b0ba0b14ec8b812c5

debug: enhance writeCurrentStackTrace to use context-based unwinding when available


1 files changed, 16 insertions(+), 6 deletions(-)

lib/std/debug.zig+16-6
...@@ -137,7 +137,7 @@ pub const StackTraceContext = blk: {...@@ -137,7 +137,7 @@ pub const StackTraceContext = blk: {
137 if (native_os == .windows) {137 if (native_os == .windows) {
138 break :blk @typeInfo(@TypeOf(os.windows.CONTEXT.getRegs)).Fn.return_type.?;138 break :blk @typeInfo(@TypeOf(os.windows.CONTEXT.getRegs)).Fn.return_type.?;
139 } else if (@hasDecl(os.system, "ucontext_t")) {139 } else if (@hasDecl(os.system, "ucontext_t")) {
140 break :blk *const os.ucontext_t;140 break :blk os.ucontext_t;
141 } else {141 } else {
142 break :blk void;142 break :blk void;
143 }143 }
...@@ -146,7 +146,7 @@ pub const StackTraceContext = blk: {...@@ -146,7 +146,7 @@ pub const StackTraceContext = blk: {
146/// 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,
147/// unbuffered, and ignores any error returned.147/// unbuffered, and ignores any error returned.
148/// TODO multithreaded awareness148/// TODO multithreaded awareness
149pub fn dumpStackTraceFromBase(context: StackTraceContext) void {149pub fn dumpStackTraceFromBase(context: *const StackTraceContext) void {
150 nosuspend {150 nosuspend {
151 if (comptime builtin.target.isWasm()) {151 if (comptime builtin.target.isWasm()) {
152 if (native_os == .wasi) {152 if (native_os == .wasi) {
...@@ -413,6 +413,14 @@ pub fn writeStackTrace(...@@ -413,6 +413,14 @@ pub fn writeStackTrace(
413 }413 }
414}414}
415415
416inline fn getContext(context: *StackTraceContext) bool {
417 if (native_os == .windows) {
418 @compileError("Syscall please!");
419 }
420
421 return @hasDecl(os.system, "getcontext") and os.system.getcontext(context) == 0;
422}
423
416pub const StackIterator = struct {424pub const StackIterator = struct {
417 // Skip every frame before this address is found.425 // Skip every frame before this address is found.
418 first_address: ?usize,426 first_address: ?usize,
...@@ -423,7 +431,7 @@ pub const StackIterator = struct {...@@ -423,7 +431,7 @@ pub const StackIterator = struct {
423 // stacks with frames that don't use a frame pointer (ie. -fomit-frame-pointer).431 // stacks with frames that don't use a frame pointer (ie. -fomit-frame-pointer).
424 debug_info: ?*DebugInfo,432 debug_info: ?*DebugInfo,
425 dwarf_context: if (supports_context) DW.UnwindContext else void = undefined,433 dwarf_context: if (supports_context) DW.UnwindContext else void = undefined,
426 const supports_context = @hasDecl(os.system, "ucontext_t") and434 pub const supports_context = @hasDecl(os.system, "ucontext_t") and
427 (builtin.os.tag != .linux or switch (builtin.cpu.arch) {435 (builtin.os.tag != .linux or switch (builtin.cpu.arch) {
428 .mips, .mipsel, .mips64, .mips64el, .riscv64 => false,436 .mips, .mipsel, .mips64, .mips64el, .riscv64 => false,
429 else => true,437 else => true,
...@@ -607,8 +615,10 @@ pub fn writeCurrentStackTrace(...@@ -607,8 +615,10 @@ pub fn writeCurrentStackTrace(
607 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);615 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
608 }616 }
609617
610 // TODO: Capture a context and use initWithContext618 var context: StackTraceContext = undefined;
611 var it = StackIterator.init(start_addr, null);619 var it = (if (getContext(&context)) blk: {
620 break :blk StackIterator.initWithContext(start_addr, debug_info, &context) catch null;
621 } else null) orelse StackIterator.init(start_addr, null);
612 defer it.deinit();622 defer it.deinit();
613623
614 while (it.next()) |return_address| {624 while (it.next()) |return_address| {
...@@ -2163,7 +2173,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[...@@ -2163,7 +2173,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[
2163 else => unreachable,2173 else => unreachable,
2164 } catch os.abort();2174 } catch os.abort();
21652175
2166 dumpStackTraceFromBase(regs);2176 dumpStackTraceFromBase(&regs);
2167}2177}
21682178
2169pub fn dumpStackPointerAddr(prefix: []const u8) void {2179pub fn dumpStackPointerAddr(prefix: []const u8) void {