Commit 3bb4d65b2f

Jakub Konka <kubkon@jakubkonka.com>
2022-06-21 23:01:06
link-tests: move macho tests to subfolder
Handle `-e` option in MachO linker allowing the user to set a custom entrypoint address.
1 parent 937464f
Changed files (22)
lib/std/build/CheckMachOStep.zig
@@ -156,6 +156,14 @@ fn dumpLoadCommand(lc: macho.LoadCommand, index: u16, writer: anytype) !void {
             });
         },
 
+        .MAIN => {
+            try writer.writeByte('\n');
+            try writer.print(
+                \\entryoff {x}
+                \\stacksize {x}
+            , .{ lc.main.entryoff, lc.main.stacksize });
+        },
+
         .RPATH => {
             try writer.writeByte('\n');
             try writer.print(
src/link/MachO.zig
@@ -934,6 +934,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
                     try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{pagezero_size}));
                 }
 
+                if (self.base.options.entry) |entry| {
+                    try argv.append("-e");
+                    try argv.append(entry);
+                }
+
                 try argv.appendSlice(positionals.items);
 
                 try argv.append("-o");
@@ -3371,13 +3376,12 @@ fn addCodeSignatureLC(self: *MachO) !void {
 fn setEntryPoint(self: *MachO) !void {
     if (self.base.options.output_mode != .Exe) return;
 
-    // TODO we should respect the -entry flag passed in by the user to set a custom
-    // entrypoint. For now, assume default of `_main`.
     const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment;
-    const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "_main"), StringIndexAdapter{
+    const entry_name = self.base.options.entry orelse "_main";
+    const n_strx = self.strtab_dir.getKeyAdapted(entry_name, StringIndexAdapter{
         .bytes = &self.strtab,
     }) orelse {
-        log.err("'_main' export not found", .{});
+        log.err("entrypoint '{s}' not found", .{entry_name});
         return error.MissingMainEntrypoint;
     };
     const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
test/link/dylib/a.c → test/link/macho/dylib/a.c
File renamed without changes
test/link/dylib/build.zig → test/link/macho/dylib/build.zig
File renamed without changes
test/link/dylib/main.c → test/link/macho/dylib/main.c
File renamed without changes
test/link/macho/entry/build.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+
+pub fn build(b: *Builder) void {
+    const mode = b.standardReleaseOptions();
+
+    const test_step = b.step("test", "Test");
+    test_step.dependOn(b.getInstallStep());
+
+    const exe = b.addExecutable("main", null);
+    exe.setBuildMode(mode);
+    exe.addCSourceFile("main.c", &.{});
+    exe.linkLibC();
+    exe.entry_symbol_name = "_non_main";
+
+    const check_exe = exe.checkMachO();
+    check_exe.check("cmd MAIN");
+    check_exe.checkNext("entryoff {x}");
+
+    test_step.dependOn(&check_exe.step);
+
+    const run = exe.run();
+    run.expectStdOutEqual("42");
+    test_step.dependOn(&run.step);
+}
test/link/macho/entry/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int non_main() {
+  printf("%d", 42);
+  return 0;
+}
test/link/frameworks/build.zig → test/link/macho/frameworks/build.zig
File renamed without changes
test/link/frameworks/main.c → test/link/macho/frameworks/main.c
File renamed without changes
test/link/objc/build.zig → test/link/macho/objc/build.zig
File renamed without changes
test/link/objc/Foo.h → test/link/macho/objc/Foo.h
File renamed without changes
test/link/objc/Foo.m → test/link/macho/objc/Foo.m
File renamed without changes
test/link/objc/test.m → test/link/macho/objc/test.m
File renamed without changes
test/link/objcpp/build.zig → test/link/macho/objcpp/build.zig
File renamed without changes
test/link/objcpp/Foo.h → test/link/macho/objcpp/Foo.h
File renamed without changes
test/link/objcpp/Foo.mm → test/link/macho/objcpp/Foo.mm
File renamed without changes
test/link/objcpp/test.mm → test/link/macho/objcpp/test.mm
File renamed without changes
test/link/pagezero/build.zig → test/link/macho/pagezero/build.zig
File renamed without changes
test/link/pagezero/main.c → test/link/macho/pagezero/main.c
File renamed without changes
test/link/macho/stack_size/build.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+
+pub fn build(b: *Builder) void {
+    const mode = b.standardReleaseOptions();
+
+    const test_step = b.step("test", "Test");
+    test_step.dependOn(b.getInstallStep());
+
+    const exe = b.addExecutable("main", null);
+    exe.setBuildMode(mode);
+    exe.addCSourceFile("main.c", &.{});
+    exe.linkLibC();
+    exe.stack_size = 0x100000000;
+
+    const check_exe = exe.checkMachO();
+    check_exe.check("cmd MAIN");
+    check_exe.checkNext("stacksize 100000000");
+
+    test_step.dependOn(&check_exe.step);
+
+    const run = exe.run();
+    test_step.dependOn(&run.step);
+}
test/link/macho/stack_size/main.c
@@ -0,0 +1,3 @@
+int main(int argc, char* argv[]) {
+  return 0;
+}
test/link.zig
@@ -28,29 +28,37 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
     });
 
     if (builtin.os.tag == .macos) {
-        cases.addBuildFile("test/link/pagezero/build.zig", .{
+        cases.addBuildFile("test/link/entry/build.zig", .{
+            .build_modes = true,
+        });
+
+        cases.addBuildFile("test/link/macho/pagezero/build.zig", .{
             .build_modes = false,
         });
 
-        cases.addBuildFile("test/link/dylib/build.zig", .{
+        cases.addBuildFile("test/link/macho/dylib/build.zig", .{
             .build_modes = true,
         });
 
-        cases.addBuildFile("test/link/frameworks/build.zig", .{
+        cases.addBuildFile("test/link/macho/frameworks/build.zig", .{
             .build_modes = true,
             .requires_macos_sdk = true,
         });
 
         // Try to build and run an Objective-C executable.
-        cases.addBuildFile("test/link/objc/build.zig", .{
+        cases.addBuildFile("test/link/macho/objc/build.zig", .{
             .build_modes = true,
             .requires_macos_sdk = true,
         });
 
         // Try to build and run an Objective-C++ executable.
-        cases.addBuildFile("test/link/objcpp/build.zig", .{
+        cases.addBuildFile("test/link/macho/objcpp/build.zig", .{
             .build_modes = true,
             .requires_macos_sdk = true,
         });
+
+        cases.addBuildFile("test/link/macho/stack_size/build.zig", .{
+            .build_modes = true,
+        });
     }
 }