| author | |
| committer | |
| log | 51d08f4b9b051d66534b77462a3bfb9bace9f1fb |
| tree | fb486d669517bc50049cff0d2e693230a6141686 |
| parent | 5f0073896977fe4a177b4b7817ce2b59160ab29d |
| signature |
5 files changed, 28 insertions(+), 20 deletions(-)
lib/compiler/test_runner.zig+4-4| ... | @@ -140,7 +140,7 @@ fn mainServer() !void { | ... | @@ -140,7 +140,7 @@ fn mainServer() !void { |
| 140 | else => { | 140 | else => { |
| 141 | fail = true; | 141 | fail = true; |
| 142 | if (@errorReturnTrace()) |trace| { | 142 | if (@errorReturnTrace()) |trace| { |
| 143 | std.debug.dumpStackTrace(trace.*); | 143 | std.debug.dumpStackTrace(trace); |
| 144 | } | 144 | } |
| 145 | }, | 145 | }, |
| 146 | }; | 146 | }; |
| ... | @@ -182,7 +182,7 @@ fn mainServer() !void { | ... | @@ -182,7 +182,7 @@ fn mainServer() !void { |
| 182 | error.SkipZigTest => return, | 182 | error.SkipZigTest => return, |
| 183 | else => { | 183 | else => { |
| 184 | if (@errorReturnTrace()) |trace| { | 184 | if (@errorReturnTrace()) |trace| { |
| 185 | std.debug.dumpStackTrace(trace.*); | 185 | std.debug.dumpStackTrace(trace); |
| 186 | } | 186 | } |
| 187 | std.debug.print("failed with error.{t}\n", .{err}); | 187 | std.debug.print("failed with error.{t}\n", .{err}); |
| 188 | std.process.exit(1); | 188 | std.process.exit(1); |
| ... | @@ -261,7 +261,7 @@ fn mainTerminal() void { | ... | @@ -261,7 +261,7 @@ fn mainTerminal() void { |
| 261 | std.debug.print("FAIL ({t})\n", .{err}); | 261 | std.debug.print("FAIL ({t})\n", .{err}); |
| 262 | } | 262 | } |
| 263 | if (@errorReturnTrace()) |trace| { | 263 | if (@errorReturnTrace()) |trace| { |
| 264 | std.debug.dumpStackTrace(trace.*); | 264 | std.debug.dumpStackTrace(trace); |
| 265 | } | 265 | } |
| 266 | test_node.end(); | 266 | test_node.end(); |
| 267 | }, | 267 | }, |
| ... | @@ -398,7 +398,7 @@ pub fn fuzz( | ... | @@ -398,7 +398,7 @@ pub fn fuzz( |
| 398 | error.SkipZigTest => return, | 398 | error.SkipZigTest => return, |
| 399 | else => { | 399 | else => { |
| 400 | std.debug.lockStdErr(); | 400 | std.debug.lockStdErr(); |
| 401 | if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); | 401 | if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace); |
| 402 | std.debug.print("failed with error.{t}\n", .{err}); | 402 | std.debug.print("failed with error.{t}\n", .{err}); |
| 403 | std.process.exit(1); | 403 | std.process.exit(1); |
| 404 | }, | 404 | }, |
lib/std/debug.zig+16-10| ... | @@ -754,6 +754,10 @@ pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void { | ... | @@ -754,6 +754,10 @@ pub fn dumpCurrentStackTrace(options: StackUnwindOptions) void { |
| 754 | 754 | ||
| 755 | /// Write a previously captured stack trace to `writer`, annotated with source locations. | 755 | /// Write a previously captured stack trace to `writer`, annotated with source locations. |
| 756 | pub fn writeStackTrace(st: *const std.builtin.StackTrace, writer: *Writer, tty_config: tty.Config) Writer.Error!void { | 756 | pub fn writeStackTrace(st: *const std.builtin.StackTrace, writer: *Writer, tty_config: tty.Config) Writer.Error!void { |
| 757 | // Fetch `st.index` straight away. Aside from avoiding redundant loads, this prevents issues if | ||
| 758 | // `st` is `@errorReturnTrace()` and errors are encountered while writing the stack trace. | ||
| 759 | const n_frames = st.index; | ||
| 760 | if (n_frames == 0) return writer.writeAll("(empty stack trace)\n"); | ||
| 757 | const di_gpa = getDebugInfoAllocator(); | 761 | const di_gpa = getDebugInfoAllocator(); |
| 758 | const di = getSelfDebugInfo() catch |err| switch (err) { | 762 | const di = getSelfDebugInfo() catch |err| switch (err) { |
| 759 | error.UnsupportedTarget => { | 763 | error.UnsupportedTarget => { |
| ... | @@ -763,14 +767,13 @@ pub fn writeStackTrace(st: *const std.builtin.StackTrace, writer: *Writer, tty_c | ... | @@ -763,14 +767,13 @@ pub fn writeStackTrace(st: *const std.builtin.StackTrace, writer: *Writer, tty_c |
| 763 | return; | 767 | return; |
| 764 | }, | 768 | }, |
| 765 | }; | 769 | }; |
| 766 | if (st.index == 0) return writer.writeAll("(empty stack trace)\n"); | 770 | const captured_frames = @min(n_frames, st.instruction_addresses.len); |
| 767 | const captured_frames = @min(st.index, st.instruction_addresses.len); | ||
| 768 | for (st.instruction_addresses[0..captured_frames]) |return_address| { | 771 | for (st.instruction_addresses[0..captured_frames]) |return_address| { |
| 769 | try printSourceAtAddress(di_gpa, di, writer, return_address -| 1, tty_config); | 772 | try printSourceAtAddress(di_gpa, di, writer, return_address -| 1, tty_config); |
| 770 | } | 773 | } |
| 771 | if (st.index > captured_frames) { | 774 | if (n_frames > captured_frames) { |
| 772 | tty_config.setColor(writer, .bold) catch {}; | 775 | tty_config.setColor(writer, .bold) catch {}; |
| 773 | try writer.print("({d} additional stack frames skipped...)\n", .{st.index - captured_frames}); | 776 | try writer.print("({d} additional stack frames skipped...)\n", .{n_frames - captured_frames}); |
| 774 | tty_config.setColor(writer, .reset) catch {}; | 777 | tty_config.setColor(writer, .reset) catch {}; |
| 775 | } | 778 | } |
| 776 | } | 779 | } |
| ... | @@ -853,7 +856,7 @@ const StackIterator = union(enum) { | ... | @@ -853,7 +856,7 @@ const StackIterator = union(enum) { |
| 853 | const di = getSelfDebugInfo() catch unreachable; | 856 | const di = getSelfDebugInfo() catch unreachable; |
| 854 | const di_gpa = getDebugInfoAllocator(); | 857 | const di_gpa = getDebugInfoAllocator(); |
| 855 | if (di.unwindFrame(di_gpa, unwind_context)) |ra| { | 858 | if (di.unwindFrame(di_gpa, unwind_context)) |ra| { |
| 856 | if (ra == 0) return .end; | 859 | if (ra <= 1) return .end; |
| 857 | return .{ .frame = ra }; | 860 | return .{ .frame = ra }; |
| 858 | } else |err| { | 861 | } else |err| { |
| 859 | const pc = unwind_context.pc; | 862 | const pc = unwind_context.pc; |
| ... | @@ -888,7 +891,9 @@ const StackIterator = union(enum) { | ... | @@ -888,7 +891,9 @@ const StackIterator = union(enum) { |
| 888 | if (bp != 0 and bp <= fp) return .end; | 891 | if (bp != 0 and bp <= fp) return .end; |
| 889 | 892 | ||
| 890 | it.fp = bp; | 893 | it.fp = bp; |
| 891 | return .{ .frame = ra_ptr.* }; | 894 | const ra = ra_ptr.*; |
| 895 | if (ra <= 1) return .end; | ||
| 896 | return .{ .frame = ra }; | ||
| 892 | }, | 897 | }, |
| 893 | } | 898 | } |
| 894 | } | 899 | } |
| ... | @@ -1409,11 +1414,12 @@ test "manage resources correctly" { | ... | @@ -1409,11 +1414,12 @@ test "manage resources correctly" { |
| 1409 | return @returnAddress(); | 1414 | return @returnAddress(); |
| 1410 | } | 1415 | } |
| 1411 | }; | 1416 | }; |
| 1412 | var discarding: std.io.Writer.Discarding = .init(&.{}); | 1417 | const gpa = std.testing.allocator; |
| 1413 | var di: SelfInfo = try .open(testing.allocator); | 1418 | var discarding: std.Io.Writer.Discarding = .init(&.{}); |
| 1414 | defer di.deinit(); | 1419 | var di: SelfInfo = .init; |
| 1420 | defer di.deinit(gpa); | ||
| 1415 | try printSourceAtAddress( | 1421 | try printSourceAtAddress( |
| 1416 | testing.allocator, | 1422 | gpa, |
| 1417 | &di, | 1423 | &di, |
| 1418 | &discarding.writer, | 1424 | &discarding.writer, |
| 1419 | S.showMyTrace(), | 1425 | S.showMyTrace(), |
lib/std/debug/SelfInfo.zig+3-3| ... | @@ -18,8 +18,8 @@ const root = @import("root"); | ... | @@ -18,8 +18,8 @@ const root = @import("root"); |
| 18 | 18 | ||
| 19 | const SelfInfo = @This(); | 19 | const SelfInfo = @This(); |
| 20 | 20 | ||
| 21 | modules: std.AutoArrayHashMapUnmanaged(usize, Module.DebugInfo), | 21 | modules: if (target_supported) std.AutoArrayHashMapUnmanaged(usize, Module.DebugInfo) else void, |
| 22 | lookup_cache: Module.LookupCache, | 22 | lookup_cache: if (target_supported) Module.LookupCache else void, |
| 23 | 23 | ||
| 24 | pub const Error = error{ | 24 | pub const Error = error{ |
| 25 | /// The required debug info is invalid or corrupted. | 25 | /// The required debug info is invalid or corrupted. |
| ... | @@ -40,7 +40,7 @@ pub const target_supported: bool = Module != void; | ... | @@ -40,7 +40,7 @@ pub const target_supported: bool = Module != void; |
| 40 | /// Indicates whether the `SelfInfo` implementation has support for unwinding on this target. | 40 | /// Indicates whether the `SelfInfo` implementation has support for unwinding on this target. |
| 41 | /// | 41 | /// |
| 42 | /// For whether DWARF unwinding is *theoretically* possible, see `Dwarf.abi.supportsUnwinding`. | 42 | /// For whether DWARF unwinding is *theoretically* possible, see `Dwarf.abi.supportsUnwinding`. |
| 43 | pub const supports_unwinding: bool = Module.supports_unwinding; | 43 | pub const supports_unwinding: bool = target_supported and Module.supports_unwinding; |
| 44 | 44 | ||
| 45 | pub const UnwindContext = if (supports_unwinding) Module.UnwindContext; | 45 | pub const UnwindContext = if (supports_unwinding) Module.UnwindContext; |
| 46 | 46 |
lib/std/start.zig+4-2| ... | @@ -635,8 +635,10 @@ pub inline fn callMain() u8 { | ... | @@ -635,8 +635,10 @@ pub inline fn callMain() u8 { |
| 635 | else => {}, | 635 | else => {}, |
| 636 | } | 636 | } |
| 637 | std.log.err("{s}", .{@errorName(err)}); | 637 | std.log.err("{s}", .{@errorName(err)}); |
| 638 | if (@errorReturnTrace()) |trace| { | 638 | if (native_os != .freestanding) { |
| 639 | std.debug.dumpStackTrace(trace); | 639 | if (@errorReturnTrace()) |trace| { |
| 640 | std.debug.dumpStackTrace(trace); | ||
| 641 | } | ||
| 640 | } | 642 | } |
| 641 | return 1; | 643 | return 1; |
| 642 | }; | 644 | }; |
lib/std/testing/FailingAllocator.zig+1-1| ... | @@ -64,7 +64,7 @@ fn alloc( | ... | @@ -64,7 +64,7 @@ fn alloc( |
| 64 | const self: *FailingAllocator = @ptrCast(@alignCast(ctx)); | 64 | const self: *FailingAllocator = @ptrCast(@alignCast(ctx)); |
| 65 | if (self.alloc_index == self.fail_index) { | 65 | if (self.alloc_index == self.fail_index) { |
| 66 | if (!self.has_induced_failure) { | 66 | if (!self.has_induced_failure) { |
| 67 | const st = std.debug.captureCurrentStackTrace(return_address, &self.stack_addresses); | 67 | const st = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &self.stack_addresses); |
| 68 | @memset(self.stack_addresses[@min(st.index, self.stack_addresses.len)..], 0); | 68 | @memset(self.stack_addresses[@min(st.index, self.stack_addresses.len)..], 0); |
| 69 | self.has_induced_failure = true; | 69 | self.has_induced_failure = true; |
| 70 | } | 70 | } |