aboutsummaryrefslogtreecommitdiff
path: root/test/src/check-stack-trace.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-03-16 17:33:24 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-03-16 17:33:24 -0700
commit1ed569e0b23c4432cd00604dcae89a17edc852a9 (patch)
tree090e0b3817a0caa4f3e7b99ec1d4d965f2bc7438 /test/src/check-stack-trace.zig
parent778ca2ae6bf025edb6babeec08c957be1fbb37a5 (diff)
parentb4d58e93ea4d0bbfe674f80d301279d302fe8fc8 (diff)
downloadzig-1ed569e0b23c4432cd00604dcae89a17edc852a9.tar.gz
zig-1ed569e0b23c4432cd00604dcae89a17edc852a9.zip
Merge remote-tracking branch 'origin/master' into llvm16
Diffstat (limited to 'test/src/check-stack-trace.zig')
-rw-r--r--test/src/check-stack-trace.zig79
1 files changed, 79 insertions, 0 deletions
diff --git a/test/src/check-stack-trace.zig b/test/src/check-stack-trace.zig
new file mode 100644
index 0000000000..bb1db55076
--- /dev/null
+++ b/test/src/check-stack-trace.zig
@@ -0,0 +1,79 @@
+const builtin = @import("builtin");
+const std = @import("std");
+const mem = std.mem;
+const fs = std.fs;
+
+pub fn main() !void {
+ var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+ defer arena_instance.deinit();
+ const arena = arena_instance.allocator();
+
+ const args = try std.process.argsAlloc(arena);
+
+ const input_path = args[1];
+ const optimize_mode_text = args[2];
+
+ const input_bytes = try std.fs.cwd().readFileAlloc(arena, input_path, 5 * 1024 * 1024);
+ const optimize_mode = std.meta.stringToEnum(std.builtin.OptimizeMode, optimize_mode_text).?;
+
+ var stderr = input_bytes;
+
+ // process result
+ // - keep only basename of source file path
+ // - replace address with symbolic string
+ // - replace function name with symbolic string when optimize_mode != .Debug
+ // - skip empty lines
+ const got: []const u8 = got_result: {
+ var buf = std.ArrayList(u8).init(arena);
+ defer buf.deinit();
+ if (stderr.len != 0 and stderr[stderr.len - 1] == '\n') stderr = stderr[0 .. stderr.len - 1];
+ var it = mem.split(u8, stderr, "\n");
+ process_lines: while (it.next()) |line| {
+ if (line.len == 0) continue;
+
+ // offset search past `[drive]:` on windows
+ var pos: usize = if (builtin.os.tag == .windows) 2 else 0;
+ // locate delims/anchor
+ const delims = [_][]const u8{ ":", ":", ":", " in ", "(", ")" };
+ var marks = [_]usize{0} ** delims.len;
+ for (delims, 0..) |delim, i| {
+ marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse {
+ // unexpected pattern: emit raw line and cont
+ try buf.appendSlice(line);
+ try buf.appendSlice("\n");
+ continue :process_lines;
+ };
+ pos = marks[i] + delim.len;
+ }
+ // locate source basename
+ pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse {
+ // unexpected pattern: emit raw line and cont
+ try buf.appendSlice(line);
+ try buf.appendSlice("\n");
+ continue :process_lines;
+ };
+ // end processing if source basename changes
+ if (!mem.eql(u8, "source.zig", line[pos + 1 .. marks[0]])) break;
+ // emit substituted line
+ try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]);
+ try buf.appendSlice(" [address]");
+ if (optimize_mode == .Debug) {
+ // On certain platforms (windows) or possibly depending on how we choose to link main
+ // the object file extension may be present so we simply strip any extension.
+ if (mem.indexOfScalar(u8, line[marks[4]..marks[5]], '.')) |idot| {
+ try buf.appendSlice(line[marks[3] .. marks[4] + idot]);
+ try buf.appendSlice(line[marks[5]..]);
+ } else {
+ try buf.appendSlice(line[marks[3]..]);
+ }
+ } else {
+ try buf.appendSlice(line[marks[3] .. marks[3] + delims[3].len]);
+ try buf.appendSlice("[function]");
+ }
+ try buf.appendSlice("\n");
+ }
+ break :got_result try buf.toOwnedSlice();
+ };
+
+ try std.io.getStdOut().writeAll(got);
+}