| 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 | 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 | 198 | cases.addBuildFile("test/link/macho/uuid/build.zig", .{ |
| 194 | 199 | .build_modes = false, |
| 195 | 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 | } |