| author | |
| committer | |
| log | c2ada49354897f89a2e2030ad1e083a8ee9b7c3b |
| tree | 12160c75ce6d7ff7e43212911be88a795a6997e5 |
| parent | 5709369d059ba107accaadb4b977281e2ba843ed |
| signature |
src/crash_handler.zig is still TODO though, i am planning bigger changes there8 files changed, 29 insertions(+), 77 deletions(-)
lib/std/Build.zig+1-1| ... | ... | @@ -2195,7 +2195,7 @@ fn dependencyInner( |
| 2195 | 2195 | sub_builder.runBuild(bz) catch @panic("unhandled error"); |
| 2196 | 2196 | |
| 2197 | 2197 | if (sub_builder.validateUserInputDidItFail()) { |
| 2198 | std.debug.dumpCurrentStackTrace(@returnAddress()); | |
| 2198 | std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); | |
| 2199 | 2199 | } |
| 2200 | 2200 | } |
| 2201 | 2201 |
lib/std/Build/Step.zig+4-20| ... | ... | @@ -60,7 +60,7 @@ test_results: TestResults, |
| 60 | 60 | |
| 61 | 61 | /// The return address associated with creation of this step that can be useful |
| 62 | 62 | /// to print along with debugging messages. |
| 63 | debug_stack_trace: []usize, | |
| 63 | debug_stack_trace: std.builtin.StackTrace, | |
| 64 | 64 | |
| 65 | 65 | pub const TestResults = struct { |
| 66 | 66 | fail_count: u32 = 0, |
| ... | ... | @@ -220,16 +220,9 @@ pub fn init(options: StepOptions) Step { |
| 220 | 220 | .state = .precheck_unstarted, |
| 221 | 221 | .max_rss = options.max_rss, |
| 222 | 222 | .debug_stack_trace = blk: { |
| 223 | if (!std.debug.sys_can_stack_trace) break :blk &.{}; | |
| 224 | const addresses = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM"); | |
| 225 | @memset(addresses, 0); | |
| 223 | const addr_buf = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM"); | |
| 226 | 224 | const first_ret_addr = options.first_ret_addr orelse @returnAddress(); |
| 227 | var stack_trace = std.builtin.StackTrace{ | |
| 228 | .instruction_addresses = addresses, | |
| 229 | .index = 0, | |
| 230 | }; | |
| 231 | std.debug.captureStackTrace(first_ret_addr, &stack_trace); | |
| 232 | break :blk addresses; | |
| 225 | break :blk std.debug.captureCurrentStackTrace(.{ .first_address = first_ret_addr }, addr_buf); | |
| 233 | 226 | }, |
| 234 | 227 | .result_error_msgs = .{}, |
| 235 | 228 | .result_error_bundle = std.zig.ErrorBundle.empty, |
| ... | ... | @@ -315,18 +308,9 @@ pub fn cast(step: *Step, comptime T: type) ?*T { |
| 315 | 308 | |
| 316 | 309 | /// For debugging purposes, prints identifying information about this Step. |
| 317 | 310 | pub fn dump(step: *Step, w: *std.Io.Writer, tty_config: std.Io.tty.Config) void { |
| 318 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { | |
| 319 | w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{ | |
| 320 | @errorName(err), | |
| 321 | }) catch {}; | |
| 322 | return; | |
| 323 | }; | |
| 324 | 311 | if (step.getStackTrace()) |stack_trace| { |
| 325 | 312 | w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {}; |
| 326 | std.debug.writeStackTrace(stack_trace, w, debug_info, tty_config) catch |err| { | |
| 327 | w.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {}; | |
| 328 | return; | |
| 329 | }; | |
| 313 | std.debug.writeStackTrace(stack_trace, w, tty_config) catch {}; | |
| 330 | 314 | } else { |
| 331 | 315 | const field = "debug_stack_frames_count"; |
| 332 | 316 | comptime assert(@hasField(Build, field)); |
lib/std/builtin.zig+5-8| ... | ... | @@ -38,20 +38,17 @@ pub const StackTrace = struct { |
| 38 | 38 | index: usize, |
| 39 | 39 | instruction_addresses: []usize, |
| 40 | 40 | |
| 41 | pub fn format(self: StackTrace, writer: *std.Io.Writer) std.Io.Writer.Error!void { | |
| 41 | pub fn format(st: *const StackTrace, writer: *std.Io.Writer) std.Io.Writer.Error!void { | |
| 42 | 42 | // TODO: re-evaluate whether to use format() methods at all. |
| 43 | 43 | // Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly |
| 44 | 44 | // where it tries to call detectTTYConfig here. |
| 45 | 45 | if (builtin.os.tag == .freestanding) return; |
| 46 | 46 | |
| 47 | const debug_info = std.debug.getSelfDebugInfo() catch |err| { | |
| 48 | return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); | |
| 49 | }; | |
| 50 | const tty_config = std.Io.tty.detectConfig(std.fs.File.stderr()); | |
| 47 | // TODO: why on earth are we using stderr's ttyconfig? | |
| 48 | // If we want colored output, we should just make a formatter out of `writeStackTrace`. | |
| 49 | const tty_config = std.Io.tty.detectConfig(.stderr()); | |
| 51 | 50 | try writer.writeAll("\n"); |
| 52 | std.debug.writeStackTrace(self, writer, debug_info, tty_config) catch |err| { | |
| 53 | try writer.print("Unable to print stack trace: {s}\n", .{@errorName(err)}); | |
| 54 | }; | |
| 51 | try std.debug.writeStackTrace(st, writer, tty_config); | |
| 55 | 52 | } |
| 56 | 53 | }; |
| 57 | 54 |
lib/std/heap/debug_allocator.zig+13-38| ... | ... | @@ -505,23 +505,14 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 505 | 505 | return if (leaks) .leak else .ok; |
| 506 | 506 | } |
| 507 | 507 | |
| 508 | fn collectStackTrace(first_trace_addr: usize, addresses: *[stack_n]usize) void { | |
| 509 | if (stack_n == 0) return; | |
| 510 | @memset(addresses, 0); | |
| 511 | var stack_trace: StackTrace = .{ | |
| 512 | .instruction_addresses = addresses, | |
| 513 | .index = 0, | |
| 514 | }; | |
| 515 | std.debug.captureStackTrace(first_trace_addr, &stack_trace); | |
| 508 | fn collectStackTrace(first_trace_addr: usize, addr_buf: *[stack_n]usize) void { | |
| 509 | const st = std.debug.captureCurrentStackTrace(.{ .first_address = first_trace_addr }, addr_buf); | |
| 510 | @memset(addr_buf[@min(st.index, addr_buf.len)..], 0); | |
| 516 | 511 | } |
| 517 | 512 | |
| 518 | 513 | fn reportDoubleFree(ret_addr: usize, alloc_stack_trace: StackTrace, free_stack_trace: StackTrace) void { |
| 519 | var addresses: [stack_n]usize = @splat(0); | |
| 520 | var second_free_stack_trace: StackTrace = .{ | |
| 521 | .instruction_addresses = &addresses, | |
| 522 | .index = 0, | |
| 523 | }; | |
| 524 | std.debug.captureStackTrace(ret_addr, &second_free_stack_trace); | |
| 514 | var addr_buf: [stack_n]usize = undefined; | |
| 515 | const second_free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf); | |
| 525 | 516 | log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{ |
| 526 | 517 | alloc_stack_trace, free_stack_trace, second_free_stack_trace, |
| 527 | 518 | }); |
| ... | ... | @@ -562,12 +553,8 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 562 | 553 | } |
| 563 | 554 | |
| 564 | 555 | if (config.safety and old_mem.len != entry.value_ptr.bytes.len) { |
| 565 | var addresses: [stack_n]usize = [1]usize{0} ** stack_n; | |
| 566 | var free_stack_trace: StackTrace = .{ | |
| 567 | .instruction_addresses = &addresses, | |
| 568 | .index = 0, | |
| 569 | }; | |
| 570 | std.debug.captureStackTrace(ret_addr, &free_stack_trace); | |
| 556 | var addr_buf: [stack_n]usize = undefined; | |
| 557 | const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf); | |
| 571 | 558 | log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ |
| 572 | 559 | entry.value_ptr.bytes.len, |
| 573 | 560 | old_mem.len, |
| ... | ... | @@ -672,12 +659,8 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 672 | 659 | } |
| 673 | 660 | |
| 674 | 661 | if (config.safety and old_mem.len != entry.value_ptr.bytes.len) { |
| 675 | var addresses: [stack_n]usize = [1]usize{0} ** stack_n; | |
| 676 | var free_stack_trace = StackTrace{ | |
| 677 | .instruction_addresses = &addresses, | |
| 678 | .index = 0, | |
| 679 | }; | |
| 680 | std.debug.captureStackTrace(ret_addr, &free_stack_trace); | |
| 662 | var addr_buf: [stack_n]usize = undefined; | |
| 663 | const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = ret_addr }, &addr_buf); | |
| 681 | 664 | log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ |
| 682 | 665 | entry.value_ptr.bytes.len, |
| 683 | 666 | old_mem.len, |
| ... | ... | @@ -900,12 +883,8 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 900 | 883 | if (requested_size == 0) @panic("Invalid free"); |
| 901 | 884 | const slot_alignment = bucket.log2PtrAligns(slot_count)[slot_index]; |
| 902 | 885 | if (old_memory.len != requested_size or alignment != slot_alignment) { |
| 903 | var addresses: [stack_n]usize = [1]usize{0} ** stack_n; | |
| 904 | var free_stack_trace: StackTrace = .{ | |
| 905 | .instruction_addresses = &addresses, | |
| 906 | .index = 0, | |
| 907 | }; | |
| 908 | std.debug.captureStackTrace(return_address, &free_stack_trace); | |
| 886 | var addr_buf: [stack_n]usize = undefined; | |
| 887 | const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf); | |
| 909 | 888 | if (old_memory.len != requested_size) { |
| 910 | 889 | log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ |
| 911 | 890 | requested_size, |
| ... | ... | @@ -999,12 +978,8 @@ pub fn DebugAllocator(comptime config: Config) type { |
| 999 | 978 | if (requested_size == 0) @panic("Invalid free"); |
| 1000 | 979 | const slot_alignment = bucket.log2PtrAligns(slot_count)[slot_index]; |
| 1001 | 980 | if (memory.len != requested_size or alignment != slot_alignment) { |
| 1002 | var addresses: [stack_n]usize = [1]usize{0} ** stack_n; | |
| 1003 | var free_stack_trace: StackTrace = .{ | |
| 1004 | .instruction_addresses = &addresses, | |
| 1005 | .index = 0, | |
| 1006 | }; | |
| 1007 | std.debug.captureStackTrace(return_address, &free_stack_trace); | |
| 981 | var addr_buf: [stack_n]usize = undefined; | |
| 982 | const free_stack_trace = std.debug.captureCurrentStackTrace(.{ .first_address = return_address }, &addr_buf); | |
| 1008 | 983 | if (memory.len != requested_size) { |
| 1009 | 984 | log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{ |
| 1010 | 985 | requested_size, |
lib/std/os/windows.zig+2-2| ... | ... | @@ -2849,7 +2849,7 @@ pub fn unexpectedError(err: Win32Error) UnexpectedError { |
| 2849 | 2849 | std.debug.print("error.Unexpected: GetLastError({d}): {f}\n", .{ |
| 2850 | 2850 | err, std.unicode.fmtUtf16Le(buf_wstr[0..len]), |
| 2851 | 2851 | }); |
| 2852 | std.debug.dumpCurrentStackTrace(@returnAddress()); | |
| 2852 | std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); | |
| 2853 | 2853 | } |
| 2854 | 2854 | return error.Unexpected; |
| 2855 | 2855 | } |
| ... | ... | @@ -2863,7 +2863,7 @@ pub fn unexpectedWSAError(err: ws2_32.WinsockError) UnexpectedError { |
| 2863 | 2863 | pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { |
| 2864 | 2864 | if (std.posix.unexpected_error_tracing) { |
| 2865 | 2865 | std.debug.print("error.Unexpected NTSTATUS=0x{x}\n", .{@intFromEnum(status)}); |
| 2866 | std.debug.dumpCurrentStackTrace(@returnAddress()); | |
| 2866 | std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); | |
| 2867 | 2867 | } |
| 2868 | 2868 | return error.Unexpected; |
| 2869 | 2869 | } |
lib/std/posix.zig+1-1| ... | ... | @@ -7591,7 +7591,7 @@ pub const UnexpectedError = error{ |
| 7591 | 7591 | pub fn unexpectedErrno(err: E) UnexpectedError { |
| 7592 | 7592 | if (unexpected_error_tracing) { |
| 7593 | 7593 | std.debug.print("unexpected errno: {d}\n", .{@intFromEnum(err)}); |
| 7594 | std.debug.dumpCurrentStackTrace(null); | |
| 7594 | std.debug.dumpCurrentStackTrace(.{}); | |
| 7595 | 7595 | } |
| 7596 | 7596 | return error.Unexpected; |
| 7597 | 7597 | } |
lib/std/testing/FailingAllocator.zig+2-6| ... | ... | @@ -64,12 +64,8 @@ fn alloc( |
| 64 | 64 | const self: *FailingAllocator = @ptrCast(@alignCast(ctx)); |
| 65 | 65 | if (self.alloc_index == self.fail_index) { |
| 66 | 66 | if (!self.has_induced_failure) { |
| 67 | @memset(&self.stack_addresses, 0); | |
| 68 | var stack_trace = std.builtin.StackTrace{ | |
| 69 | .instruction_addresses = &self.stack_addresses, | |
| 70 | .index = 0, | |
| 71 | }; | |
| 72 | std.debug.captureStackTrace(return_address, &stack_trace); | |
| 67 | const st = std.debug.captureCurrentStackTrace(return_address, &self.stack_addresses); | |
| 68 | @memset(self.stack_addresses[@min(st.index, self.stack_addresses.len)..], 0); | |
| 73 | 69 | self.has_induced_failure = true; |
| 74 | 70 | } |
| 75 | 71 | return null; |
src/link/MachO.zig+1-1| ... | ... | @@ -5070,7 +5070,7 @@ pub fn getKernError(err: std.c.kern_return_t) KernE { |
| 5070 | 5070 | pub fn unexpectedKernError(err: KernE) std.posix.UnexpectedError { |
| 5071 | 5071 | if (std.posix.unexpected_error_tracing) { |
| 5072 | 5072 | std.debug.print("unexpected error: {d}\n", .{@intFromEnum(err)}); |
| 5073 | std.debug.dumpCurrentStackTrace(null); | |
| 5073 | std.debug.dumpCurrentStackTrace(.{}); | |
| 5074 | 5074 | } |
| 5075 | 5075 | return error.Unexpected; |
| 5076 | 5076 | } |