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