| ... | @@ -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 awareness | 148 | /// TODO multithreaded awareness |
| 149 | pub fn dumpStackTraceFromBase(context: StackTraceContext) void { | 149 | pub 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 | } |
| 415 | | 415 | |
| | 416 | inline 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 | |
| 416 | pub const StackIterator = struct { | 424 | pub 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") and | 434 | 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 | } |
| 609 | | 617 | |
| 610 | // TODO: Capture a context and use initWithContext | 618 | 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(); |
| 613 | | 623 | |
| 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(); |
| 2165 | | 2175 | |
| 2166 | dumpStackTraceFromBase(regs); | 2176 | dumpStackTraceFromBase(&regs); |
| 2167 | } | 2177 | } |
| 2168 | | 2178 | |
| 2169 | pub fn dumpStackPointerAddr(prefix: []const u8) void { | 2179 | pub fn dumpStackPointerAddr(prefix: []const u8) void { |