| ... | ... | @@ -610,7 +610,7 @@ fn waitForOtherThreadToFinishPanicking() void { |
| 610 | 610 | /// therefore must be kept in sync with the compiler implementation. |
| 611 | 611 | pub const StackTrace = struct { |
| 612 | 612 | index: usize, |
| 613 | | instruction_addresses: []usize, |
| 613 | return_addresses: []usize, |
| 614 | 614 | }; |
| 615 | 615 | |
| 616 | 616 | pub const StackUnwindOptions = struct { |
| ... | ... | @@ -634,7 +634,7 @@ pub const StackUnwindOptions = struct { |
| 634 | 634 | pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: []usize) StackTrace { |
| 635 | 635 | const empty_trace: StackTrace = .{ |
| 636 | 636 | .index = 0, |
| 637 | | .instruction_addresses = &.{}, |
| 637 | .return_addresses = &.{}, |
| 638 | 638 | }; |
| 639 | 639 | if (!std.options.allow_stack_tracing) return empty_trace; |
| 640 | 640 | var it: StackIterator = .init(options.context); |
| ... | ... | @@ -669,7 +669,7 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: |
| 669 | 669 | }; |
| 670 | 670 | return .{ |
| 671 | 671 | .index = index, |
| 672 | | .instruction_addresses = addr_buf[0..index], |
| 672 | .return_addresses = addr_buf[0..index], |
| 673 | 673 | }; |
| 674 | 674 | } |
| 675 | 675 | /// Write the current stack trace to `writer`, annotated with source locations. |
| ... | ... | @@ -791,16 +791,23 @@ pub const FormatStackTrace = struct { |
| 791 | 791 | }; |
| 792 | 792 | |
| 793 | 793 | /// Write a previously captured error return trace to `writer`, annotated with source locations. |
| 794 | | pub fn writeErrorReturnTrace(st: *const std.builtin.ErrorReturnTrace, t: Io.Terminal) Writer.Error!void { |
| 795 | | try writeTrace(st, t, false); |
| 794 | pub fn writeErrorReturnTrace(et: *const std.builtin.ErrorReturnTrace, t: Io.Terminal) Writer.Error!void { |
| 795 | // Fetch `et.index` straight away. Aside from avoiding redundant loads, this prevents issues if |
| 796 | // errors are encountered while writing the stack trace. |
| 797 | try writeTrace(et.instruction_addresses, et.index, t, false); |
| 796 | 798 | } |
| 797 | 799 | |
| 798 | 800 | /// Write a previously captured stack trace to `writer`, annotated with source locations. |
| 799 | | pub fn writeStackTrace(et: *const StackTrace, t: Io.Terminal) Writer.Error!void { |
| 800 | | try writeTrace(et, t, true); |
| 801 | pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void { |
| 802 | try writeTrace(st.return_addresses, st.index, t, true); |
| 801 | 803 | } |
| 802 | 804 | |
| 803 | | fn writeTrace(trace: anytype, t: Io.Terminal, resolve_inline_callers: bool) Writer.Error!void { |
| 805 | fn writeTrace( |
| 806 | addresses: []const usize, |
| 807 | n_frames: usize, |
| 808 | t: Io.Terminal, |
| 809 | resolve_inline_callers: bool, |
| 810 | ) Writer.Error!void { |
| 804 | 811 | const writer = t.writer; |
| 805 | 812 | if (!std.options.allow_stack_tracing) { |
| 806 | 813 | t.setColor(.dim) catch {}; |
| ... | ... | @@ -809,9 +816,6 @@ fn writeTrace(trace: anytype, t: Io.Terminal, resolve_inline_callers: bool) Writ |
| 809 | 816 | return; |
| 810 | 817 | } |
| 811 | 818 | |
| 812 | | // Fetch `trace.index` straight away. Aside from avoiding redundant loads, this prevents issues if |
| 813 | | // `trace` is `@errorReturnTrace()` and errors are encountered while writing the stack trace. |
| 814 | | const n_frames = trace.index; |
| 815 | 819 | if (n_frames == 0) return writer.writeAll("(empty stack trace)\n"); |
| 816 | 820 | const di = getSelfDebugInfo() catch |err| switch (err) { |
| 817 | 821 | error.UnsupportedTarget => { |
| ... | ... | @@ -822,8 +826,8 @@ fn writeTrace(trace: anytype, t: Io.Terminal, resolve_inline_callers: bool) Writ |
| 822 | 826 | }, |
| 823 | 827 | }; |
| 824 | 828 | const io = std.Options.debug_io; |
| 825 | | const captured_frames = @min(n_frames, trace.instruction_addresses.len); |
| 826 | | for (trace.instruction_addresses[0..captured_frames]) |ret_addr| { |
| 829 | const captured_frames = @min(n_frames, addresses.len); |
| 830 | for (addresses[0..captured_frames]) |ret_addr| { |
| 827 | 831 | // `ret_addr` is the return address, which is *after* the function call. |
| 828 | 832 | // Subtract 1 to get an address *in* the function call for a better source location. |
| 829 | 833 | try printSourceAtAddress(io, di, t, .{ |
| ... | ... | @@ -1729,7 +1733,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize |
| 1729 | 1733 | const frames = mem.sliceTo(frames_array_mutable[0..], 0); |
| 1730 | 1734 | const stack_trace: StackTrace = .{ |
| 1731 | 1735 | .index = frames.len, |
| 1732 | | .instruction_addresses = frames, |
| 1736 | .return_addresses = frames, |
| 1733 | 1737 | }; |
| 1734 | 1738 | writeStackTrace(&stack_trace, stderr) catch return; |
| 1735 | 1739 | } |