authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-05 20:40:11+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-30 13:44:51+01:00
logc2ada49354897f89a2e2030ad1e083a8ee9b7c3b
tree12160c75ce6d7ff7e43212911be88a795a6997e5
parent5709369d059ba107accaadb4b977281e2ba843ed
signaturelock-open Commit is signed but in an unrecognized format.

replace usages of old std.debug APIs

src/crash_handler.zig is still TODO though, i am planning bigger changes there

8 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");
21962196
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 }
22012201
lib/std/Build/Step.zig+4-20
...@@ -60,7 +60,7 @@ test_results: TestResults,...@@ -60,7 +60,7 @@ test_results: TestResults,
6060
61/// The return address associated with creation of this step that can be useful61/// 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.
63debug_stack_trace: []usize,63debug_stack_trace: std.builtin.StackTrace,
6464
65pub const TestResults = struct {65pub 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 {
315308
316/// For debugging purposes, prints identifying information about this Step.309/// For debugging purposes, prints identifying information about this Step.
317pub fn dump(step: *Step, w: *std.Io.Writer, tty_config: std.Io.tty.Config) void {310pub 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,
4040
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 WebAssembly43 // 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;
4646
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};
5754
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 }
507507
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 }
517512
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 }
563554
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 }
673660
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 {
2863pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError {2863pub 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{
7591pub fn unexpectedErrno(err: E) UnexpectedError {7591pub 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 {
5070pub fn unexpectedKernError(err: KernE) std.posix.UnexpectedError {5070pub 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}