| 1 | //! A variant of `std.builtin.StackTrace` that stores its data within itself |
| 2 | //! instead of being a pointer. This allows storing captured stack traces |
| 3 | //! for later printing. |
| 4 | |
| 5 | data: [31]usize, |
| 6 | index: usize, |
| 7 | |
| 8 | pub const empty: StoredTrace = .{ |
| 9 | .data = .{0} ** 31, |
| 10 | .index = 0, |
| 11 | }; |
| 12 | |
| 13 | pub fn trace(stored: *StoredTrace) std.builtin.StackTrace { |
| 14 | return .{ |
| 15 | .index = stored.index, |
| 16 | .instruction_addresses = &stored.data, |
| 17 | }; |
| 18 | } |
| 19 | |
| 20 | pub fn capture(begin: ?usize) StoredTrace { |
| 21 | var stored: StoredTrace = undefined; |
| 22 | var frame = stored.trace(); |
| 23 | std.debug.captureStackTrace(begin orelse @returnAddress(), &frame); |
| 24 | stored.index = frame.index; |
| 25 | return stored; |
| 26 | } |
| 27 | |
| 28 | pub fn from(stack_trace: ?*std.builtin.StackTrace) StoredTrace { |
| 29 | if (stack_trace) |stack| { |
| 30 | var data: [31]usize = undefined; |
| 31 | @memset(&data, 0); |
| 32 | const items = @min(stack.instruction_addresses.len, 31); |
| 33 | @memcpy(data[0..items], stack.instruction_addresses[0..items]); |
| 34 | return .{ |
| 35 | .data = data, |
| 36 | .index = @min(items, stack.index), |
| 37 | }; |
| 38 | } else { |
| 39 | return empty; |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | pub const BlankImpl = struct { |
| 44 | pub const empty: BlankImpl = .{}; |
| 45 | |
| 46 | pub fn trace(_: *BlankImpl) std.builtin.StackTrace { |
| 47 | @compileError("trace is not available with StoredTrace.BlankImpl"); |
| 48 | } |
| 49 | |
| 50 | pub fn capture(_: ?usize) @This() { |
| 51 | return .{}; |
| 52 | } |
| 53 | |
| 54 | pub fn from(_: ?*std.builtin.StackTrace) @This() { |
| 55 | return .{}; |
| 56 | } |
| 57 | }; |
| 58 | |
| 59 | pub const DebugStoredTrace = if (builtin.mode == .Debug) |
| 60 | StoredTrace |
| 61 | else |
| 62 | BlankImpl; |
| 63 | |
| 64 | pub const StoredTrace = @This(); |
| 65 | |
| 66 | const std = @import("std"); |
| 67 | const builtin = @import("builtin"); |