| author | |
| committer | |
| log | e0ccbff87d329b607093f8f88f959e34571dac70 |
| tree | dc51402fcf4841458f773e476bdbdcbc50adff11 |
| parent | 835a60a34fe2bc3d35e4524caee455a4743a5022 |
6 files changed, 172 insertions(+), 0 deletions(-)
test/link.zig+5| ... | @@ -190,6 +190,11 @@ fn addMachOCases(cases: *tests.StandaloneContext) void { | ... | @@ -190,6 +190,11 @@ fn addMachOCases(cases: *tests.StandaloneContext) void { |
| 190 | .requires_symlinks = true, | 190 | .requires_symlinks = true, |
| 191 | }); | 191 | }); |
| 192 | 192 | ||
| 193 | cases.addBuildFile("test/link/macho/unwind_info/build.zig", .{ | ||
| 194 | .build_modes = true, | ||
| 195 | .requires_symlinks = true, | ||
| 196 | }); | ||
| 197 | |||
| 193 | cases.addBuildFile("test/link/macho/uuid/build.zig", .{ | 198 | cases.addBuildFile("test/link/macho/uuid/build.zig", .{ |
| 194 | .build_modes = false, | 199 | .build_modes = false, |
| 195 | .requires_symlinks = true, | 200 | .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 | |||
| 8 | struct 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 | |||
| 15 | private: | ||
| 16 | size_t max_size; | ||
| 17 | char* buffer; | ||
| 18 | size_t length; | ||
| 19 | }; | ||
| 20 | |||
| 21 | struct SimpleStringOwner { | ||
| 22 | SimpleStringOwner(const char* x); | ||
| 23 | ~SimpleStringOwner(); | ||
| 24 | |||
| 25 | private: | ||
| 26 | SimpleString string; | ||
| 27 | }; | ||
| 28 | |||
| 29 | class Error: public std::exception { | ||
| 30 | public: | ||
| 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 | |||
| 37 | protected: | ||
| 38 | std::string msg; | ||
| 39 | }; | ||
| 40 | |||
| 41 | #endif | ||
test/link/macho/unwind_info/build.zig created+60| ... | @@ -0,0 +1,60 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Builder = std.build.Builder; | ||
| 3 | const LibExeObjectStep = std.build.LibExeObjStep; | ||
| 4 | |||
| 5 | pub 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 | |||
| 15 | fn 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 | |||
| 47 | fn 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 | |||
| 4 | void fn_c() { | ||
| 5 | SimpleStringOwner c{ "cccccccccc" }; | ||
| 6 | } | ||
| 7 | |||
| 8 | void fn_b() { | ||
| 9 | SimpleStringOwner b{ "b" }; | ||
| 10 | fn_c(); | ||
| 11 | } | ||
| 12 | |||
| 13 | int 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 | |||
| 5 | SimpleString::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 | |||
| 14 | SimpleString::~SimpleString() { | ||
| 15 | delete[] buffer; | ||
| 16 | } | ||
| 17 | |||
| 18 | void SimpleString::print(const char* tag) const { | ||
| 19 | printf("%s: %s", tag, buffer); | ||
| 20 | } | ||
| 21 | |||
| 22 | bool 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 | |||
| 3 | SimpleStringOwner::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 | |||
| 10 | SimpleStringOwner::~SimpleStringOwner() { | ||
| 11 | string.print("About to destroy"); | ||
| 12 | } | ||