| author | |
| committer | |
| log | 9c908ea814b6b5ae67622c0a9cce4704c6734590 |
| tree | 2809339ba3d469c31898c0659371ac22dc79a2c2 |
| parent | 23d9b59b868e7f256668535adf9803facf75e538 |
4 files changed, 105 insertions(+), 0 deletions(-)
test/standalone.zig+4| ... | @@ -230,6 +230,10 @@ pub const build_cases = [_]BuildCase{ | ... | @@ -230,6 +230,10 @@ pub const build_cases = [_]BuildCase{ |
| 230 | .build_root = "test/standalone/zerolength_check", | 230 | .build_root = "test/standalone/zerolength_check", |
| 231 | .import = @import("standalone/zerolength_check/build.zig"), | 231 | .import = @import("standalone/zerolength_check/build.zig"), |
| 232 | }, | 232 | }, |
| 233 | .{ | ||
| 234 | .build_root = "test/standalone/dwarf_unwinding", | ||
| 235 | .import = @import("standalone/dwarf_unwinding/build.zig"), | ||
| 236 | }, | ||
| 233 | }; | 237 | }; |
| 234 | 238 | ||
| 235 | const std = @import("std"); | 239 | const std = @import("std"); |
test/standalone/dwarf_unwinding/build.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn build(b: *std.Build) void { | ||
| 4 | const test_step = b.step("test", "Test it"); | ||
| 5 | b.default_step = test_step; | ||
| 6 | |||
| 7 | const target = b.standardTargetOptions(.{}); | ||
| 8 | const optimize = b.standardOptimizeOption(.{}); | ||
| 9 | |||
| 10 | if (!std.debug.StackIterator.supports_context) return; | ||
| 11 | |||
| 12 | const c_shared_lib = b.addSharedLibrary(.{ | ||
| 13 | .name = "c_shared_lib", | ||
| 14 | .target = target, | ||
| 15 | .optimize = optimize, | ||
| 16 | }); | ||
| 17 | |||
| 18 | if (target.isWindows()) c_shared_lib.defineCMacro("LIB_API", "__declspec(dllexport)"); | ||
| 19 | |||
| 20 | c_shared_lib.strip = false; | ||
| 21 | c_shared_lib.addCSourceFile("shared_lib.c", &.{"-fomit-frame-pointer"}); | ||
| 22 | c_shared_lib.linkLibC(); | ||
| 23 | |||
| 24 | const exe = b.addExecutable(.{ | ||
| 25 | .name = "main", | ||
| 26 | .root_source_file = .{ .path = "main.zig" }, | ||
| 27 | .target = target, | ||
| 28 | .optimize = optimize, | ||
| 29 | }); | ||
| 30 | |||
| 31 | exe.omit_frame_pointer = true; | ||
| 32 | exe.linkLibrary(c_shared_lib); | ||
| 33 | b.installArtifact(exe); | ||
| 34 | |||
| 35 | const run_cmd = b.addRunArtifact(exe); | ||
| 36 | test_step.dependOn(&run_cmd.step); | ||
| 37 | } | ||
test/standalone/dwarf_unwinding/main.zig created+40| ... | @@ -0,0 +1,40 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const debug = std.debug; | ||
| 3 | const testing = std.testing; | ||
| 4 | |||
| 5 | noinline fn frame4(expected: *[4]usize, unwound: *[4]usize) void { | ||
| 6 | expected[0] = @returnAddress(); | ||
| 7 | |||
| 8 | var context: debug.StackTraceContext = undefined; | ||
| 9 | testing.expect(debug.getContext(&context)) catch @panic("failed to getContext"); | ||
| 10 | |||
| 11 | var debug_info = debug.getSelfDebugInfo() catch @panic("failed to openSelfDebugInfo"); | ||
| 12 | var it = debug.StackIterator.initWithContext(null, debug_info, &context) catch @panic("failed to initWithContext"); | ||
| 13 | defer it.deinit(); | ||
| 14 | |||
| 15 | for (unwound) |*addr| { | ||
| 16 | if (it.next()) |return_address| addr.* = return_address; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | noinline fn frame3(expected: *[4]usize, unwound: *[4]usize) void { | ||
| 21 | expected[1] = @returnAddress(); | ||
| 22 | frame4(expected, unwound); | ||
| 23 | } | ||
| 24 | |||
| 25 | fn frame2(expected: *[4]usize, unwound: *[4]usize) callconv(.C) void { | ||
| 26 | frame3(expected, unwound); | ||
| 27 | } | ||
| 28 | |||
| 29 | extern fn frame0( | ||
| 30 | expected: *[4]usize, | ||
| 31 | unwound: *[4]usize, | ||
| 32 | frame_2: *const fn (expected: *[4]usize, unwound: *[4]usize) callconv(.C) void, | ||
| 33 | ) void; | ||
| 34 | |||
| 35 | pub fn main() !void { | ||
| 36 | var expected: [4]usize = undefined; | ||
| 37 | var unwound: [4]usize = undefined; | ||
| 38 | frame0(&expected, &unwound, &frame2); | ||
| 39 | try testing.expectEqual(expected, unwound); | ||
| 40 | } | ||
test/standalone/dwarf_unwinding/shared_lib.c created+24| ... | @@ -0,0 +1,24 @@ | ||
| 1 | #include <stdint.h> | ||
| 2 | |||
| 3 | #ifndef LIB_API | ||
| 4 | #define LIB_API | ||
| 5 | #endif | ||
| 6 | |||
| 7 | __attribute__((noinline)) void frame1( | ||
| 8 | void** expected, | ||
| 9 | void** unwound, | ||
| 10 | void (*frame2)(void** expected, void** unwound)) { | ||
| 11 | expected[2] = &&frame_2_ret; | ||
| 12 | frame2(expected, unwound); | ||
| 13 | frame_2_ret: | ||
| 14 | } | ||
| 15 | |||
| 16 | LIB_API void frame0( | ||
| 17 | void** expected, | ||
| 18 | void** unwound, | ||
| 19 | void (*frame2)(void** expected, void** unwound)) { | ||
| 20 | expected[3] = &&frame_1_ret; | ||
| 21 | frame1(expected, unwound, frame2); | ||
| 22 | frame_1_ret: | ||
| 23 | } | ||
| 24 | |||