╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ stack_traces.zig ─────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
101 .name = "dump current trace with no unwind strategy", 102 .source = 103 \\pub fn main() void { 104 \\ foo(bar()); 105 \\} 106 \\fn bar() void { 107 \\ qux(123); 108 \\} 109 \\fn foo(_: void) void {} 110 \\fn qux(x: u32) void { 111 \\ std.debug.print("pre\n", .{}); 112 \\ std.debug.dumpCurrentStackTrace(.{}); 113 \\ std.debug.print("post\n", .{}); 114 \\ _ = x; 115 \\} 116 \\const std = @import("std"); 117 \\ 118 , 119 .unwind = .no_safe, 120 .expect_panic = false, 121 .expect = "pre\npost\n", 122 .expect_strip = "pre\npost\n", 123 }); 124 125 cases.addCase(.{ 126 .params = params, 127 .target = target, 128 .name = "dump captured trace", 129 .source = 130 \\pub fn main() void { 131 \\ var stack_trace_buf: [8]usize = undefined; 132 \\ dumpIt(&captureIt(&stack_trace_buf)); 133 \\} 134 \\fn captureIt(buf: []usize) std.debug.StackTrace { 135 \\ return captureItInner(buf); 136 \\} 137 \\fn dumpIt(st: *const std.debug.StackTrace) void { 138 \\ std.debug.dumpStackTrace(st); 139 \\} 140 \\fn captureItInner(buf: []usize) std.debug.StackTrace { 141 \\ return std.debug.captureCurrentStackTrace(.{}, buf); 142 \\} 143 \\const std = @import("std"); 144 \\ 145 , 146 .unwind = .safe, 147 .expect_panic = false, 148 .expect = 149 \\source.zig:12:46: [address] in captureItInner 150 \\ return std.debug.captureCurrentStackTrace(.{}, buf); 151 \\ ^ 152 \\source.zig:6:26: [address] in captureIt 153 \\ return captureItInner(buf); 154 \\ ^ 155 \\source.zig:3:22: [address] in main 156 \\ dumpIt(&captureIt(&stack_trace_buf)); 157 \\ ^ 158 \\ 159 , 160 .expect_strip = 161 \\???:?:?: [address] in source.captureItInner 162 \\???:?:?: [address] in source.captureIt 163 \\???:?:?: [address] in source.main 164 \\ 165 , 166 }); 167 168 cases.addCase(.{ 169 .params = params, 170 .target = target, 171 .name = "dump captured trace with no unwind strategy", 172 .source = 173 \\pub fn main() void { 174 \\ var stack_trace_buf: [8]usize = undefined; 175 \\ dumpIt(&captureIt(&stack_trace_buf)); 176 \\} 177 \\fn captureIt(buf: []usize) std.debug.StackTrace { 178 \\ return captureItInner(buf); 179 \\} 180 \\fn dumpIt(st: *const std.debug.StackTrace) void { 181 \\ std.debug.dumpStackTrace(st); 182 \\} 183 \\fn captureItInner(buf: []usize) std.debug.StackTrace { 184 \\ return std.debug.captureCurrentStackTrace(.{}, buf); 185 \\} 186 \\const std = @import("std"); 187 \\ 188 , 189 .unwind = .no_safe, 190 .expect_panic = false, 191 .expect = "(empty stack trace)\n", 192 .expect_strip = "(empty stack trace)\n", 193 }); 194 195 cases.addCase(.{ 196 .params = params, 197 .target = target, 198 .name = "dump captured trace on thread", 199 .source = 200 \\pub fn main() !void { 201 \\ var stack_trace_buf: [8]usize = undefined; 202 \\ const t = try std.Thread.spawn(.{}, threadMain, .{&stack_trace_buf}); 203 \\ t.join(); 204 \\} 205 \\fn threadMain(stack_trace_buf: []usize) void { 206 \\ dumpIt(&captureIt(stack_trace_buf)); 207 \\} 208 \\fn captureIt(buf: []usize) std.debug.StackTrace { 209 \\ return captureItInner(buf); 210 \\} 211 \\fn dumpIt(st: *const std.debug.StackTrace) void { 212 \\ std.debug.dumpStackTrace(st); 213 \\} 214 \\fn captureItInner(buf: []usize) std.debug.StackTrace { 215 \\ return std.debug.captureCurrentStackTrace(.{}, buf); 216 \\} 217 \\const std = @import("std"); 218 \\ 219 , 220 .unwind = .safe, 221 .expect_panic = false, 222 .expect = 223 \\source.zig:16:46: [address] in captureItInner 224 \\ return std.debug.captureCurrentStackTrace(.{}, buf); 225 \\ ^ 226 \\source.zig:10:26: [address] in captureIt 227 \\ return captureItInner(buf); 228 \\ ^ 229 \\source.zig:7:22: [address] in threadMain 230 \\ dumpIt(&captureIt(stack_trace_buf)); 231 \\ ^ 232 \\ 233 , 234 .expect_strip = 235 \\???:?:?: [address] in source.captureItInner 236 \\???:?:?: [address] in source.captureIt 237 \\???:?:?: [address] in source.threadMain 238 \\ 239 , 240 }); 241 242 cases.addCase(.{ 243 .params = params, 244 .target = target, 245 .name = "simple inline panic", 246 // The main function has two inline calls to ensure 247 // that inlinees in PDBs are properly deduplicated. 248 .source = 249 \\pub fn main() void { 250 \\ foo(false); 251 \\ foo(true); 252 \\} 253 \\inline fn foo(b: bool) void { 254 \\ if (b) @panic("oh no"); 255 \\} 256 \\ 257 , 258 .unwind = .any, 259 .expect_panic = true, 260 .expect = switch (target.os.tag) { 261 // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, 262 // so the first location has only a row. 263 .windows => 264 \\panic: oh no 265 \\source.zig:6: [address] in foo 266 \\ if (b) @panic("oh no"); 267 \\ 268 \\source.zig:3:8: [address] in main 269 \\ foo(true); 270 \\ ^ 271 \\ 272 , 273 // On all other platforms, we resolve the innermost inline callee but we don't yet 274 // resolve the inline callers. 275 else => 276 \\panic: oh no 277 \\source.zig:6:12: [address] in foo 278 \\ if (b) @panic("oh no"); 279 \\ ^ 280 , 281 }, 282 .expect_strip = switch (target.os.tag) { 283 .windows => 284 \\panic: oh no 285 \\???:?:?: [address] in source.foo 286 \\???:?:?: [address] in source.main 287 \\ 288 , 289 else => 290 \\panic: oh no 291 \\???:?:?: [address] in source.foo 292 \\ 293 , 294 }, 295 }); 296 297 // Make sure all inline calls are resolved and in the right order! 298 cases.addCase(.{ 299 .params = params, 300 .target = target, 301 .name = "nested inline panic", 302 .source = 303 \\pub fn main() void { 304 \\ foo(); 305 \\} 306 \\inline fn foo() void { 307 \\ bar(); 308 \\} 309 \\inline fn bar() void { 310 \\ baz(); 311 \\} 312 \\inline fn baz() void { 313 \\ @panic("oh no"); 314 \\} 315 \\ 316 , 317 .unwind = .any, 318 .expect_panic = true, 319 // This switch serves a similar purpose as in "inline panic". 320 .expect = switch (target.os.tag) { 321 .windows => 322 \\panic: oh no 323 \\source.zig:11: [address] in baz 324 \\ @panic("oh no"); 325 \\ 326 \\source.zig:8: [address] in bar 327 \\ baz(); 328 \\ 329 \\source.zig:5: [address] in foo 330 \\ bar(); 331 \\ 332 \\source.zig:2:8: [address] in main 333 \\ foo(); 334 \\ ^ 335 \\ 336 , 337 else => 338 \\panic: oh no 339 \\source.zig:11:5: [address] in baz 340 \\ @panic("oh no"); 341 \\ ^ 342 , 343 }, 344 .expect_strip = switch (target.os.tag) { 345 .windows => 346 \\panic: oh no 347 \\???:?:?: [address] in baz 348 \\???:?:?: [address] in bar 349 \\???:?:?: [address] in foo 350 \\???:?:?: [address] in main 351 \\ 352 , 353 else => 354 \\panic: oh no 355 \\???:?:?: [address] in baz 356 \\ 357 , 358 }, 359 }); 360 } 361