| ... | ... | @@ -90,9 +90,60 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 90 | 90 | }; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | /// Returns a slice with the same pointer as addresses, with a potentially smaller len. |
| 94 | /// On Windows, when first_address is not null, we ask for at least 32 stack frames, |
| 95 | /// and then try to find the first address. If addresses.len is more than 32, we |
| 96 | /// capture that many stack frames exactly, and then look for the first address, |
| 97 | /// chopping off the irrelevant frames and shifting so that the returned addresses pointer |
| 98 | /// equals the passed in addresses pointer. |
| 99 | pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void { |
| 100 | switch (builtin.os) { |
| 101 | builtin.Os.windows => { |
| 102 | const addrs = stack_trace.instruction_addresses; |
| 103 | const u32_addrs_len = @intCast(u32, addrs.len); |
| 104 | const first_addr = first_address orelse { |
| 105 | stack_trace.index = windows.RtlCaptureStackBackTrace( |
| 106 | 0, |
| 107 | u32_addrs_len, |
| 108 | @ptrCast(**c_void, addrs.ptr), |
| 109 | null, |
| 110 | ); |
| 111 | return; |
| 112 | }; |
| 113 | var addr_buf_stack: [32]usize = undefined; |
| 114 | const addr_buf = if (addr_buf_stack.len > addrs.len) addr_buf_stack[0..] else addrs; |
| 115 | const n = windows.RtlCaptureStackBackTrace(0, u32_addrs_len, @ptrCast(**c_void, addr_buf.ptr), null); |
| 116 | const first_index = for (addr_buf[0..n]) |addr, i| { |
| 117 | if (addr == first_addr) { |
| 118 | break i; |
| 119 | } |
| 120 | } else { |
| 121 | stack_trace.index = 0; |
| 122 | return; |
| 123 | }; |
| 124 | const slice = addr_buf[first_index..n]; |
| 125 | // We use a for loop here because slice and addrs may alias. |
| 126 | for (slice) |addr, i| { |
| 127 | addrs[i] = addr; |
| 128 | } |
| 129 | stack_trace.index = slice.len; |
| 130 | }, |
| 131 | else => { |
| 132 | var it = StackIterator.init(first_address); |
| 133 | for (stack_trace.instruction_addresses) |*addr, i| { |
| 134 | addr.* = it.next() orelse { |
| 135 | stack_trace.index = i; |
| 136 | return; |
| 137 | }; |
| 138 | } |
| 139 | stack_trace.index = stack_trace.instruction_addresses.len; |
| 140 | }, |
| 141 | } |
| 142 | } |
| 143 | |
| 93 | 144 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. |
| 94 | 145 | /// TODO multithreaded awareness |
| 95 | | pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { |
| 146 | pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { |
| 96 | 147 | const stderr = getStderrStream() catch return; |
| 97 | 148 | const debug_info = getSelfDebugInfo() catch |err| { |
| 98 | 149 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| ... | ... | @@ -141,7 +192,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c |
| 141 | 192 | const stderr = getStderrStream() catch os.abort(); |
| 142 | 193 | stderr.print(format ++ "\n", args) catch os.abort(); |
| 143 | 194 | if (trace) |t| { |
| 144 | | dumpStackTrace(t); |
| 195 | dumpStackTrace(t.*); |
| 145 | 196 | } |
| 146 | 197 | dumpCurrentStackTrace(first_trace_addr); |
| 147 | 198 | |
| ... | ... | @@ -155,16 +206,15 @@ const WHITE = "\x1b[37;1m"; |
| 155 | 206 | const DIM = "\x1b[2m"; |
| 156 | 207 | const RESET = "\x1b[0m"; |
| 157 | 208 | |
| 158 | | pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, tty_color: bool) !void { |
| 159 | | var frame_index: usize = undefined; |
| 160 | | var frames_left: usize = undefined; |
| 161 | | if (stack_trace.index < stack_trace.instruction_addresses.len) { |
| 162 | | frame_index = 0; |
| 163 | | frames_left = stack_trace.index; |
| 164 | | } else { |
| 165 | | frame_index = (stack_trace.index + 1) % stack_trace.instruction_addresses.len; |
| 166 | | frames_left = stack_trace.instruction_addresses.len; |
| 167 | | } |
| 209 | pub fn writeStackTrace( |
| 210 | stack_trace: builtin.StackTrace, |
| 211 | out_stream: var, |
| 212 | allocator: *mem.Allocator, |
| 213 | debug_info: *DebugInfo, |
| 214 | tty_color: bool, |
| 215 | ) !void { |
| 216 | var frame_index: usize = 0; |
| 217 | var frames_left: usize = stack_trace.index; |
| 168 | 218 | |
| 169 | 219 | while (frames_left != 0) : ({ |
| 170 | 220 | frames_left -= 1; |