authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-20 20:57:40+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-20 20:57:40+01:00
loge0ccbff87d329b607093f8f88f959e34571dac70
treedc51402fcf4841458f773e476bdbdcbc50adff11
parent835a60a34fe2bc3d35e4524caee455a4743a5022

link-tests: test unwind info emitter via c++ exceptions


6 files changed, 172 insertions(+), 0 deletions(-)

test/link.zig+5
......@@ -190,6 +190,11 @@ fn addMachOCases(cases: *tests.StandaloneContext) void {
190190 .requires_symlinks = true,
191191 });
192192
193 cases.addBuildFile("test/link/macho/unwind_info/build.zig", .{
194 .build_modes = true,
195 .requires_symlinks = true,
196 });
197
193198 cases.addBuildFile("test/link/macho/uuid/build.zig", .{
194199 .build_modes = false,
195200 .requires_symlinks = true,
test/link/macho/unwind_info/all.h created+41
......@@ -0,0 +1,41 @@
1#ifndef ALL
2#define ALL
3
4#include <cstddef>
5#include <string>
6#include <stdexcept>
7
8struct SimpleString {
9 SimpleString(size_t max_size);
10 ~SimpleString();
11
12 void print(const char* tag) const;
13 bool append_line(const char* x);
14
15private:
16 size_t max_size;
17 char* buffer;
18 size_t length;
19};
20
21struct SimpleStringOwner {
22 SimpleStringOwner(const char* x);
23 ~SimpleStringOwner();
24
25private:
26 SimpleString string;
27};
28
29class Error: public std::exception {
30public:
31 explicit Error(const char* msg) : msg{ msg } {}
32 virtual ~Error() noexcept {}
33 virtual const char* what() const noexcept {
34 return msg.c_str();
35 }
36
37protected:
38 std::string msg;
39};
40
41#endif
test/link/macho/unwind_info/build.zig created+60
......@@ -0,0 +1,60 @@
1const std = @import("std");
2const Builder = std.build.Builder;
3const LibExeObjectStep = std.build.LibExeObjStep;
4
5pub fn build(b: *Builder) void {
6 const mode = b.standardReleaseOptions();
7 const target: std.zig.CrossTarget = .{ .os_tag = .macos };
8
9 const test_step = b.step("test", "Test the program");
10
11 testUnwindInfo(b, test_step, mode, target, false);
12 testUnwindInfo(b, test_step, mode, target, true);
13}
14
15fn testUnwindInfo(
16 b: *Builder,
17 test_step: *std.build.Step,
18 mode: std.builtin.Mode,
19 target: std.zig.CrossTarget,
20 dead_strip: bool,
21) void {
22 const exe = createScenario(b, mode, target);
23 exe.link_gc_sections = dead_strip;
24
25 const check = exe.checkObject(.macho);
26 check.checkStart("segname __TEXT");
27 check.checkNext("sectname __gcc_except_tab");
28 check.checkNext("sectname __unwind_info");
29 check.checkNext("sectname __eh_frame");
30
31 check.checkInSymtab();
32 check.checkNext("{*} (__TEXT,__text) external ___gxx_personality_v0");
33
34 const run_cmd = check.runAndCompare();
35 run_cmd.expectStdOutEqual(
36 \\Constructed: a
37 \\Constructed: b
38 \\About to destroy: b
39 \\About to destroy: a
40 \\Error: Not enough memory!
41 \\
42 );
43
44 test_step.dependOn(&run_cmd.step);
45}
46
47fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
48 const exe = b.addExecutable("test", null);
49 b.default_step.dependOn(&exe.step);
50 exe.addIncludePath(".");
51 exe.addCSourceFiles(&[_][]const u8{
52 "main.cpp",
53 "simple_string.cpp",
54 "simple_string_owner.cpp",
55 }, &[0][]const u8{});
56 exe.setBuildMode(mode);
57 exe.setTarget(target);
58 exe.linkLibCpp();
59 return exe;
60}
test/link/macho/unwind_info/main.cpp created+24
......@@ -0,0 +1,24 @@
1#include "all.h"
2#include <cstdio>
3
4void fn_c() {
5 SimpleStringOwner c{ "cccccccccc" };
6}
7
8void fn_b() {
9 SimpleStringOwner b{ "b" };
10 fn_c();
11}
12
13int main() {
14 try {
15 SimpleStringOwner a{ "a" };
16 fn_b();
17 SimpleStringOwner d{ "d" };
18 } catch (const Error& e) {
19 printf("Error: %s\n", e.what());
20 } catch(const std::exception& e) {
21 printf("Exception: %s\n", e.what());
22 }
23 return 0;
24}
test/link/macho/unwind_info/simple_string.cpp created+30
......@@ -0,0 +1,30 @@
1#include "all.h"
2#include <cstdio>
3#include <cstring>
4
5SimpleString::SimpleString(size_t max_size)
6: max_size{ max_size }, length{} {
7 if (max_size == 0) {
8 throw Error{ "Max size must be at least 1." };
9 }
10 buffer = new char[max_size];
11 buffer[0] = 0;
12}
13
14SimpleString::~SimpleString() {
15 delete[] buffer;
16}
17
18void SimpleString::print(const char* tag) const {
19 printf("%s: %s", tag, buffer);
20}
21
22bool SimpleString::append_line(const char* x) {
23 const auto x_len = strlen(x);
24 if (x_len + length + 2 > max_size) return false;
25 std::strncpy(buffer + length, x, max_size - length);
26 length += x_len;
27 buffer[length++] = '\n';
28 buffer[length] = 0;
29 return true;
30}
test/link/macho/unwind_info/simple_string_owner.cpp created+12
......@@ -0,0 +1,12 @@
1#include "all.h"
2
3SimpleStringOwner::SimpleStringOwner(const char* x) : string{ 10 } {
4 if (!string.append_line(x)) {
5 throw Error{ "Not enough memory!" };
6 }
7 string.print("Constructed");
8}
9
10SimpleStringOwner::~SimpleStringOwner() {
11 string.print("About to destroy");
12}