Commit e0ccbff87d
Changed files (6)
test
link
macho
test/link/macho/unwind_info/all.h
@@ -0,0 +1,41 @@
+#ifndef ALL
+#define ALL
+
+#include <cstddef>
+#include <string>
+#include <stdexcept>
+
+struct SimpleString {
+ SimpleString(size_t max_size);
+ ~SimpleString();
+
+ void print(const char* tag) const;
+ bool append_line(const char* x);
+
+private:
+ size_t max_size;
+ char* buffer;
+ size_t length;
+};
+
+struct SimpleStringOwner {
+ SimpleStringOwner(const char* x);
+ ~SimpleStringOwner();
+
+private:
+ SimpleString string;
+};
+
+class Error: public std::exception {
+public:
+ explicit Error(const char* msg) : msg{ msg } {}
+ virtual ~Error() noexcept {}
+ virtual const char* what() const noexcept {
+ return msg.c_str();
+ }
+
+protected:
+ std::string msg;
+};
+
+#endif
test/link/macho/unwind_info/build.zig
@@ -0,0 +1,60 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+const LibExeObjectStep = std.build.LibExeObjStep;
+
+pub fn build(b: *Builder) void {
+ const mode = b.standardReleaseOptions();
+ const target: std.zig.CrossTarget = .{ .os_tag = .macos };
+
+ const test_step = b.step("test", "Test the program");
+
+ testUnwindInfo(b, test_step, mode, target, false);
+ testUnwindInfo(b, test_step, mode, target, true);
+}
+
+fn testUnwindInfo(
+ b: *Builder,
+ test_step: *std.build.Step,
+ mode: std.builtin.Mode,
+ target: std.zig.CrossTarget,
+ dead_strip: bool,
+) void {
+ const exe = createScenario(b, mode, target);
+ exe.link_gc_sections = dead_strip;
+
+ const check = exe.checkObject(.macho);
+ check.checkStart("segname __TEXT");
+ check.checkNext("sectname __gcc_except_tab");
+ check.checkNext("sectname __unwind_info");
+ check.checkNext("sectname __eh_frame");
+
+ check.checkInSymtab();
+ check.checkNext("{*} (__TEXT,__text) external ___gxx_personality_v0");
+
+ const run_cmd = check.runAndCompare();
+ run_cmd.expectStdOutEqual(
+ \\Constructed: a
+ \\Constructed: b
+ \\About to destroy: b
+ \\About to destroy: a
+ \\Error: Not enough memory!
+ \\
+ );
+
+ test_step.dependOn(&run_cmd.step);
+}
+
+fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
+ const exe = b.addExecutable("test", null);
+ b.default_step.dependOn(&exe.step);
+ exe.addIncludePath(".");
+ exe.addCSourceFiles(&[_][]const u8{
+ "main.cpp",
+ "simple_string.cpp",
+ "simple_string_owner.cpp",
+ }, &[0][]const u8{});
+ exe.setBuildMode(mode);
+ exe.setTarget(target);
+ exe.linkLibCpp();
+ return exe;
+}
test/link/macho/unwind_info/main.cpp
@@ -0,0 +1,24 @@
+#include "all.h"
+#include <cstdio>
+
+void fn_c() {
+ SimpleStringOwner c{ "cccccccccc" };
+}
+
+void fn_b() {
+ SimpleStringOwner b{ "b" };
+ fn_c();
+}
+
+int main() {
+ try {
+ SimpleStringOwner a{ "a" };
+ fn_b();
+ SimpleStringOwner d{ "d" };
+ } catch (const Error& e) {
+ printf("Error: %s\n", e.what());
+ } catch(const std::exception& e) {
+ printf("Exception: %s\n", e.what());
+ }
+ return 0;
+}
test/link/macho/unwind_info/simple_string.cpp
@@ -0,0 +1,30 @@
+#include "all.h"
+#include <cstdio>
+#include <cstring>
+
+SimpleString::SimpleString(size_t max_size)
+: max_size{ max_size }, length{} {
+ if (max_size == 0) {
+ throw Error{ "Max size must be at least 1." };
+ }
+ buffer = new char[max_size];
+ buffer[0] = 0;
+}
+
+SimpleString::~SimpleString() {
+ delete[] buffer;
+}
+
+void SimpleString::print(const char* tag) const {
+ printf("%s: %s", tag, buffer);
+}
+
+bool SimpleString::append_line(const char* x) {
+ const auto x_len = strlen(x);
+ if (x_len + length + 2 > max_size) return false;
+ std::strncpy(buffer + length, x, max_size - length);
+ length += x_len;
+ buffer[length++] = '\n';
+ buffer[length] = 0;
+ return true;
+}
test/link/macho/unwind_info/simple_string_owner.cpp
@@ -0,0 +1,12 @@
+#include "all.h"
+
+SimpleStringOwner::SimpleStringOwner(const char* x) : string{ 10 } {
+ if (!string.append_line(x)) {
+ throw Error{ "Not enough memory!" };
+ }
+ string.print("Constructed");
+}
+
+SimpleStringOwner::~SimpleStringOwner() {
+ string.print("About to destroy");
+}
test/link.zig
@@ -190,6 +190,11 @@ fn addMachOCases(cases: *tests.StandaloneContext) void {
.requires_symlinks = true,
});
+ cases.addBuildFile("test/link/macho/unwind_info/build.zig", .{
+ .build_modes = true,
+ .requires_symlinks = true,
+ });
+
cases.addBuildFile("test/link/macho/uuid/build.zig", .{
.build_modes = false,
.requires_symlinks = true,