authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-29 17:46:23+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-29 17:46:23+02:00
log8211cef77c15d37d3ec9b92943476c7755ef7efc
tree2c3df4c5f939f6bc959e11806d3b587067320a38
parent069fcf1c95dafa7c711b4f5c7d1041eaab54a9e5

zld: we can now create basic dylibs targeting macOS!


2 files changed, 128 insertions(+), 60 deletions(-)

src/link/MachO.zig+33-5
...@@ -626,12 +626,12 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -626,12 +626,12 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
626626
627 const is_lib = self.base.options.output_mode == .Lib;627 const is_lib = self.base.options.output_mode == .Lib;
628 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;628 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
629 // const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;629 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
630 const target = self.base.options.target;630 const target = self.base.options.target;
631 const stack_size = self.base.options.stack_size_override orelse 0;631 const stack_size = self.base.options.stack_size_override orelse 0;
632 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;632 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
633633
634 const id_symlink_basename = "lld.id";634 const id_symlink_basename = "zld.id";
635635
636 var man: Cache.Manifest = undefined;636 var man: Cache.Manifest = undefined;
637 defer if (!self.base.options.disable_lld_caching) man.deinit();637 defer if (!self.base.options.disable_lld_caching) man.deinit();
...@@ -731,7 +731,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -731,7 +731,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
731 zld.closeFiles();731 zld.closeFiles();
732 zld.deinit();732 zld.deinit();
733 }733 }
734 zld.arch = target.cpu.arch;734 zld.target = target;
735 zld.stack_size = stack_size;735 zld.stack_size = stack_size;
736736
737 // Positional arguments to the linker such as object files and static archives.737 // Positional arguments to the linker such as object files and static archives.
...@@ -876,12 +876,40 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -876,12 +876,40 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
876 rpaths.appendAssumeCapacity(key.*);876 rpaths.appendAssumeCapacity(key.*);
877 }877 }
878878
879 const output: Zld.Output = output: {
880 if (is_dyn_lib) {
881 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{
882 self.base.options.emit.?.sub_path,
883 });
884 break :output .{
885 .tag = .dylib,
886 .path = full_out_path,
887 .install_name = install_name,
888 };
889 }
890 break :output .{
891 .tag = .exe,
892 .path = full_out_path,
893 };
894 };
895
879 if (self.base.options.verbose_link) {896 if (self.base.options.verbose_link) {
880 var argv = std.ArrayList([]const u8).init(arena);897 var argv = std.ArrayList([]const u8).init(arena);
881898
882 try argv.append("zig");899 try argv.append("zig");
883 try argv.append("ld");900 try argv.append("ld");
884901
902 if (is_exe_or_dyn_lib) {
903 try argv.append("-dynamic");
904 }
905
906 if (is_dyn_lib) {
907 try argv.append("-dylib");
908
909 try argv.append("-install_name");
910 try argv.append(output.install_name.?);
911 }
912
885 if (self.base.options.sysroot) |syslibroot| {913 if (self.base.options.sysroot) |syslibroot| {
886 try argv.append("-syslibroot");914 try argv.append("-syslibroot");
887 try argv.append(syslibroot);915 try argv.append(syslibroot);
...@@ -895,7 +923,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -895,7 +923,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
895 try argv.appendSlice(positionals.items);923 try argv.appendSlice(positionals.items);
896924
897 try argv.append("-o");925 try argv.append("-o");
898 try argv.append(full_out_path);926 try argv.append(output.path);
899927
900 if (native_libsystem_available) {928 if (native_libsystem_available) {
901 try argv.append("-lSystem");929 try argv.append("-lSystem");
...@@ -913,7 +941,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -913,7 +941,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
913 Compilation.dump_argv(argv.items);941 Compilation.dump_argv(argv.items);
914 }942 }
915943
916 try zld.link(positionals.items, full_out_path, .{944 try zld.link(positionals.items, output, .{
917 .syslibroot = self.base.options.sysroot,945 .syslibroot = self.base.options.sysroot,
918 .libs = libs.items,946 .libs = libs.items,
919 .rpaths = rpaths.items,947 .rpaths = rpaths.items,
src/link/MachO/Zld.zig+95-55
...@@ -25,10 +25,10 @@ usingnamespace @import("bind.zig");...@@ -25,10 +25,10 @@ usingnamespace @import("bind.zig");
2525
26allocator: *Allocator,26allocator: *Allocator,
2727
28arch: ?std.Target.Cpu.Arch = null,28target: ?std.Target = null,
29page_size: ?u16 = null,29page_size: ?u16 = null,
30file: ?fs.File = null,30file: ?fs.File = null,
31out_path: ?[]const u8 = null,31output: ?Output = null,
3232
33// TODO these args will become obselete once Zld is coalesced with incremental33// TODO these args will become obselete once Zld is coalesced with incremental
34// linker.34// linker.
...@@ -54,6 +54,7 @@ dylinker_cmd_index: ?u16 = null,...@@ -54,6 +54,7 @@ dylinker_cmd_index: ?u16 = null,
54data_in_code_cmd_index: ?u16 = null,54data_in_code_cmd_index: ?u16 = null,
55function_starts_cmd_index: ?u16 = null,55function_starts_cmd_index: ?u16 = null,
56main_cmd_index: ?u16 = null,56main_cmd_index: ?u16 = null,
57dylib_id_cmd_index: ?u16 = null,
57version_min_cmd_index: ?u16 = null,58version_min_cmd_index: ?u16 = null,
58source_version_cmd_index: ?u16 = null,59source_version_cmd_index: ?u16 = null,
59uuid_cmd_index: ?u16 = null,60uuid_cmd_index: ?u16 = null,
...@@ -118,6 +119,12 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},...@@ -118,6 +119,12 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
118119
119stub_helper_stubs_start_off: ?u64 = null,120stub_helper_stubs_start_off: ?u64 = null,
120121
122pub const Output = struct {
123 tag: enum { exe, dylib },
124 path: []const u8,
125 install_name: ?[]const u8 = null,
126};
127
121const TlvOffset = struct {128const TlvOffset = struct {
122 source_addr: u64,129 source_addr: u64,
123 offset: u64,130 offset: u64,
...@@ -200,36 +207,17 @@ const LinkArgs = struct {...@@ -200,36 +207,17 @@ const LinkArgs = struct {
200 rpaths: []const []const u8,207 rpaths: []const []const u8,
201};208};
202209
203pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: LinkArgs) !void {210pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArgs) !void {
204 if (files.len == 0) return error.NoInputFiles;211 if (files.len == 0) return error.NoInputFiles;
205 if (out_path.len == 0) return error.EmptyOutputPath;212 if (output.path.len == 0) return error.EmptyOutputPath;
206
207 if (self.arch == null) {
208 // Try inferring the arch from the object files.
209 self.arch = blk: {
210 const file = try fs.cwd().openFile(files[0], .{});
211 defer file.close();
212 var reader = file.reader();
213 const header = try reader.readStruct(macho.mach_header_64);
214 const arch: std.Target.Cpu.Arch = switch (header.cputype) {
215 macho.CPU_TYPE_X86_64 => .x86_64,
216 macho.CPU_TYPE_ARM64 => .aarch64,
217 else => |value| {
218 log.err("unsupported cpu architecture 0x{x}", .{value});
219 return error.UnsupportedCpuArchitecture;
220 },
221 };
222 break :blk arch;
223 };
224 }
225213
226 self.page_size = switch (self.arch.?) {214 self.page_size = switch (self.target.?.cpu.arch) {
227 .aarch64 => 0x4000,215 .aarch64 => 0x4000,
228 .x86_64 => 0x1000,216 .x86_64 => 0x1000,
229 else => unreachable,217 else => unreachable,
230 };218 };
231 self.out_path = out_path;219 self.output = output;
232 self.file = try fs.cwd().createFile(out_path, .{220 self.file = try fs.cwd().createFile(self.output.?.path, .{
233 .truncate = true,221 .truncate = true,
234 .read = true,222 .read = true,
235 .mode = if (std.Target.current.os.tag == .windows) 0 else 0o777,223 .mode = if (std.Target.current.os.tag == .windows) 0 else 0o777,
...@@ -263,19 +251,19 @@ fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u...@@ -263,19 +251,19 @@ fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u
263 break :full_path try self.allocator.dupe(u8, path);251 break :full_path try self.allocator.dupe(u8, path);
264 };252 };
265253
266 if (try Object.createAndParseFromPath(self.allocator, self.arch.?, full_path)) |object| {254 if (try Object.createAndParseFromPath(self.allocator, self.target.?.cpu.arch, full_path)) |object| {
267 try self.objects.append(self.allocator, object);255 try self.objects.append(self.allocator, object);
268 continue;256 continue;
269 }257 }
270258
271 if (try Archive.createAndParseFromPath(self.allocator, self.arch.?, full_path)) |archive| {259 if (try Archive.createAndParseFromPath(self.allocator, self.target.?.cpu.arch, full_path)) |archive| {
272 try self.archives.append(self.allocator, archive);260 try self.archives.append(self.allocator, archive);
273 continue;261 continue;
274 }262 }
275263
276 if (try Dylib.createAndParseFromPath(264 if (try Dylib.createAndParseFromPath(
277 self.allocator,265 self.allocator,
278 self.arch.?,266 self.target.?.cpu.arch,
279 full_path,267 full_path,
280 .{ .syslibroot = syslibroot },268 .{ .syslibroot = syslibroot },
281 )) |dylibs| {269 )) |dylibs| {
...@@ -292,7 +280,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi...@@ -292,7 +280,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi
292 for (libs) |lib| {280 for (libs) |lib| {
293 if (try Dylib.createAndParseFromPath(281 if (try Dylib.createAndParseFromPath(
294 self.allocator,282 self.allocator,
295 self.arch.?,283 self.target.?.cpu.arch,
296 lib,284 lib,
297 .{ .syslibroot = syslibroot },285 .{ .syslibroot = syslibroot },
298 )) |dylibs| {286 )) |dylibs| {
...@@ -301,7 +289,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi...@@ -301,7 +289,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi
301 continue;289 continue;
302 }290 }
303291
304 if (try Archive.createAndParseFromPath(self.allocator, self.arch.?, lib)) |archive| {292 if (try Archive.createAndParseFromPath(self.allocator, self.target.?.cpu.arch, lib)) |archive| {
305 try self.archives.append(self.allocator, archive);293 try self.archives.append(self.allocator, archive);
306 continue;294 continue;
307 }295 }
...@@ -989,7 +977,7 @@ fn allocateTextSegment(self: *Zld) !void {...@@ -989,7 +977,7 @@ fn allocateTextSegment(self: *Zld) !void {
989 const stub_helper = &seg.sections.items[self.stub_helper_section_index.?];977 const stub_helper = &seg.sections.items[self.stub_helper_section_index.?];
990 stubs.size += nstubs * stubs.reserved2;978 stubs.size += nstubs * stubs.reserved2;
991979
992 const stub_size: u4 = switch (self.arch.?) {980 const stub_size: u4 = switch (self.target.?.cpu.arch) {
993 .x86_64 => 10,981 .x86_64 => 10,
994 .aarch64 => 3 * @sizeOf(u32),982 .aarch64 => 3 * @sizeOf(u32),
995 else => unreachable,983 else => unreachable,
...@@ -1226,7 +1214,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1226,7 +1214,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1226 const data = &data_segment.sections.items[self.data_section_index.?];1214 const data = &data_segment.sections.items[self.data_section_index.?];
12271215
1228 self.stub_helper_stubs_start_off = blk: {1216 self.stub_helper_stubs_start_off = blk: {
1229 switch (self.arch.?) {1217 switch (self.target.?.cpu.arch) {
1230 .x86_64 => {1218 .x86_64 => {
1231 const code_size = 15;1219 const code_size = 15;
1232 var code: [code_size]u8 = undefined;1220 var code: [code_size]u8 = undefined;
...@@ -1358,7 +1346,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {...@@ -1358,7 +1346,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
1358 const data_segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1346 const data_segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1359 const la_symbol_ptr = data_segment.sections.items[self.la_symbol_ptr_section_index.?];1347 const la_symbol_ptr = data_segment.sections.items[self.la_symbol_ptr_section_index.?];
13601348
1361 const stub_size: u4 = switch (self.arch.?) {1349 const stub_size: u4 = switch (self.target.?.cpu.arch) {
1362 .x86_64 => 10,1350 .x86_64 => 10,
1363 .aarch64 => 3 * @sizeOf(u32),1351 .aarch64 => 3 * @sizeOf(u32),
1364 else => unreachable,1352 else => unreachable,
...@@ -1384,7 +1372,7 @@ fn writeStub(self: *Zld, index: u32) !void {...@@ -1384,7 +1372,7 @@ fn writeStub(self: *Zld, index: u32) !void {
1384 log.debug("writing stub at 0x{x}", .{stub_off});1372 log.debug("writing stub at 0x{x}", .{stub_off});
1385 var code = try self.allocator.alloc(u8, stubs.reserved2);1373 var code = try self.allocator.alloc(u8, stubs.reserved2);
1386 defer self.allocator.free(code);1374 defer self.allocator.free(code);
1387 switch (self.arch.?) {1375 switch (self.target.?.cpu.arch) {
1388 .x86_64 => {1376 .x86_64 => {
1389 assert(la_ptr_addr >= stub_addr + stubs.reserved2);1377 assert(la_ptr_addr >= stub_addr + stubs.reserved2);
1390 const displacement = try math.cast(u32, la_ptr_addr - stub_addr - stubs.reserved2);1378 const displacement = try math.cast(u32, la_ptr_addr - stub_addr - stubs.reserved2);
...@@ -1447,7 +1435,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1447,7 +1435,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
1447 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;1435 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1448 const stub_helper = text_segment.sections.items[self.stub_helper_section_index.?];1436 const stub_helper = text_segment.sections.items[self.stub_helper_section_index.?];
14491437
1450 const stub_size: u4 = switch (self.arch.?) {1438 const stub_size: u4 = switch (self.target.?.cpu.arch) {
1451 .x86_64 => 10,1439 .x86_64 => 10,
1452 .aarch64 => 3 * @sizeOf(u32),1440 .aarch64 => 3 * @sizeOf(u32),
1453 else => unreachable,1441 else => unreachable,
...@@ -1455,7 +1443,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1455,7 +1443,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
1455 const stub_off = self.stub_helper_stubs_start_off.? + index * stub_size;1443 const stub_off = self.stub_helper_stubs_start_off.? + index * stub_size;
1456 var code = try self.allocator.alloc(u8, stub_size);1444 var code = try self.allocator.alloc(u8, stub_size);
1457 defer self.allocator.free(code);1445 defer self.allocator.free(code);
1458 switch (self.arch.?) {1446 switch (self.target.?.cpu.arch) {
1459 .x86_64 => {1447 .x86_64 => {
1460 const displacement = try math.cast(1448 const displacement = try math.cast(
1461 i32,1449 i32,
...@@ -1999,7 +1987,7 @@ fn populateMetadata(self: *Zld) !void {...@@ -1999,7 +1987,7 @@ fn populateMetadata(self: *Zld) !void {
1999 if (self.text_section_index == null) {1987 if (self.text_section_index == null) {
2000 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;1988 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2001 self.text_section_index = @intCast(u16, text_seg.sections.items.len);1989 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
2002 const alignment: u2 = switch (self.arch.?) {1990 const alignment: u2 = switch (self.target.?.cpu.arch) {
2003 .x86_64 => 0,1991 .x86_64 => 0,
2004 .aarch64 => 2,1992 .aarch64 => 2,
2005 else => unreachable, // unhandled architecture type1993 else => unreachable, // unhandled architecture type
...@@ -2013,12 +2001,12 @@ fn populateMetadata(self: *Zld) !void {...@@ -2013,12 +2001,12 @@ fn populateMetadata(self: *Zld) !void {
2013 if (self.stubs_section_index == null) {2001 if (self.stubs_section_index == null) {
2014 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;2002 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2015 self.stubs_section_index = @intCast(u16, text_seg.sections.items.len);2003 self.stubs_section_index = @intCast(u16, text_seg.sections.items.len);
2016 const alignment: u2 = switch (self.arch.?) {2004 const alignment: u2 = switch (self.target.?.cpu.arch) {
2017 .x86_64 => 0,2005 .x86_64 => 0,
2018 .aarch64 => 2,2006 .aarch64 => 2,
2019 else => unreachable, // unhandled architecture type2007 else => unreachable, // unhandled architecture type
2020 };2008 };
2021 const stub_size: u4 = switch (self.arch.?) {2009 const stub_size: u4 = switch (self.target.?.cpu.arch) {
2022 .x86_64 => 6,2010 .x86_64 => 6,
2023 .aarch64 => 3 * @sizeOf(u32),2011 .aarch64 => 3 * @sizeOf(u32),
2024 else => unreachable, // unhandled architecture type2012 else => unreachable, // unhandled architecture type
...@@ -2033,12 +2021,12 @@ fn populateMetadata(self: *Zld) !void {...@@ -2033,12 +2021,12 @@ fn populateMetadata(self: *Zld) !void {
2033 if (self.stub_helper_section_index == null) {2021 if (self.stub_helper_section_index == null) {
2034 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;2022 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2035 self.stub_helper_section_index = @intCast(u16, text_seg.sections.items.len);2023 self.stub_helper_section_index = @intCast(u16, text_seg.sections.items.len);
2036 const alignment: u2 = switch (self.arch.?) {2024 const alignment: u2 = switch (self.target.?.cpu.arch) {
2037 .x86_64 => 0,2025 .x86_64 => 0,
2038 .aarch64 => 2,2026 .aarch64 => 2,
2039 else => unreachable, // unhandled architecture type2027 else => unreachable, // unhandled architecture type
2040 };2028 };
2041 const stub_helper_size: u6 = switch (self.arch.?) {2029 const stub_helper_size: u6 = switch (self.target.?.cpu.arch) {
2042 .x86_64 => 15,2030 .x86_64 => 15,
2043 .aarch64 => 6 * @sizeOf(u32),2031 .aarch64 => 6 * @sizeOf(u32),
2044 else => unreachable,2032 else => unreachable,
...@@ -2187,7 +2175,7 @@ fn populateMetadata(self: *Zld) !void {...@@ -2187,7 +2175,7 @@ fn populateMetadata(self: *Zld) !void {
2187 try self.load_commands.append(self.allocator, .{ .Dylinker = dylinker_cmd });2175 try self.load_commands.append(self.allocator, .{ .Dylinker = dylinker_cmd });
2188 }2176 }
21892177
2190 if (self.main_cmd_index == null) {2178 if (self.main_cmd_index == null and self.output.?.tag == .exe) {
2191 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);2179 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);
2192 try self.load_commands.append(self.allocator, .{2180 try self.load_commands.append(self.allocator, .{
2193 .Main = .{2181 .Main = .{
...@@ -2199,6 +2187,41 @@ fn populateMetadata(self: *Zld) !void {...@@ -2199,6 +2187,41 @@ fn populateMetadata(self: *Zld) !void {
2199 });2187 });
2200 }2188 }
22012189
2190 if (self.dylib_id_cmd_index == null and self.output.?.tag == .dylib) {
2191 self.dylib_id_cmd_index = @intCast(u16, self.load_commands.items.len);
2192 var dylib_cmd = try createLoadDylibCommand(
2193 self.allocator,
2194 self.output.?.install_name.?,
2195 2,
2196 0x10000, // TODO forward user-provided versions
2197 0x10000,
2198 );
2199 errdefer dylib_cmd.deinit(self.allocator);
2200 dylib_cmd.inner.cmd = macho.LC_ID_DYLIB;
2201 try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd });
2202 }
2203
2204 if (self.version_min_cmd_index == null) {
2205 self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len);
2206 const cmd: u32 = switch (self.target.?.os.tag) {
2207 .macos => macho.LC_VERSION_MIN_MACOSX,
2208 .ios => macho.LC_VERSION_MIN_IPHONEOS,
2209 .tvos => macho.LC_VERSION_MIN_TVOS,
2210 .watchos => macho.LC_VERSION_MIN_WATCHOS,
2211 else => unreachable, // wrong OS
2212 };
2213 const ver = self.target.?.os.version_range.semver.min;
2214 const version = ver.major << 16 | ver.minor << 8 | ver.patch;
2215 try self.load_commands.append(self.allocator, .{
2216 .VersionMin = .{
2217 .cmd = cmd,
2218 .cmdsize = @sizeOf(macho.version_min_command),
2219 .version = version,
2220 .sdk = version,
2221 },
2222 });
2223 }
2224
2202 if (self.source_version_cmd_index == null) {2225 if (self.source_version_cmd_index == null) {
2203 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);2226 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
2204 try self.load_commands.append(self.allocator, .{2227 try self.load_commands.append(self.allocator, .{
...@@ -2237,7 +2260,7 @@ fn addDataInCodeLC(self: *Zld) !void {...@@ -2237,7 +2260,7 @@ fn addDataInCodeLC(self: *Zld) !void {
2237}2260}
22382261
2239fn addCodeSignatureLC(self: *Zld) !void {2262fn addCodeSignatureLC(self: *Zld) !void {
2240 if (self.code_signature_cmd_index == null and self.arch.? == .aarch64) {2263 if (self.code_signature_cmd_index == null and self.target.?.cpu.arch == .aarch64) {
2241 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);2264 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
2242 try self.load_commands.append(self.allocator, .{2265 try self.load_commands.append(self.allocator, .{
2243 .LinkeditData = .{2266 .LinkeditData = .{
...@@ -2355,19 +2378,20 @@ fn flush(self: *Zld) !void {...@@ -2355,19 +2378,20 @@ fn flush(self: *Zld) !void {
2355 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2378 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
2356 }2379 }
23572380
2358 if (self.arch.? == .aarch64) {2381 if (self.target.?.cpu.arch == .aarch64) {
2359 try self.writeCodeSignaturePadding();2382 try self.writeCodeSignaturePadding();
2360 }2383 }
23612384
2362 try self.writeLoadCommands();2385 try self.writeLoadCommands();
2363 try self.writeHeader();2386 try self.writeHeader();
23642387
2365 if (self.arch.? == .aarch64) {2388 if (self.target.?.cpu.arch == .aarch64) {
2366 try self.writeCodeSignature();2389 try self.writeCodeSignature();
2367 }2390 }
23682391
2369 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {2392 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
2370 try fs.cwd().copyFile(self.out_path.?, fs.cwd(), self.out_path.?, .{});2393 const out_path = self.output.?.path;
2394 try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
2371 }2395 }
2372}2396}
23732397
...@@ -2392,6 +2416,8 @@ fn writeGotEntries(self: *Zld) !void {...@@ -2392,6 +2416,8 @@ fn writeGotEntries(self: *Zld) !void {
2392}2416}
23932417
2394fn setEntryPoint(self: *Zld) !void {2418fn setEntryPoint(self: *Zld) !void {
2419 if (self.output.?.tag != .exe) return;
2420
2395 // TODO we should respect the -entry flag passed in by the user to set a custom2421 // TODO we should respect the -entry flag passed in by the user to set a custom
2396 // entrypoint. For now, assume default of `_main`.2422 // entrypoint. For now, assume default of `_main`.
2397 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2423 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
...@@ -2636,12 +2662,12 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {...@@ -2636,12 +2662,12 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
2636 }2662 }
2637 assert(self.stubs.items.len <= offsets.items.len);2663 assert(self.stubs.items.len <= offsets.items.len);
26382664
2639 const stub_size: u4 = switch (self.arch.?) {2665 const stub_size: u4 = switch (self.target.?.cpu.arch) {
2640 .x86_64 => 10,2666 .x86_64 => 10,
2641 .aarch64 => 3 * @sizeOf(u32),2667 .aarch64 => 3 * @sizeOf(u32),
2642 else => unreachable,2668 else => unreachable,
2643 };2669 };
2644 const off: u4 = switch (self.arch.?) {2670 const off: u4 = switch (self.target.?.cpu.arch) {
2645 .x86_64 => 1,2671 .x86_64 => 1,
2646 .aarch64 => 2 * @sizeOf(u32),2672 .aarch64 => 2 * @sizeOf(u32),
2647 else => unreachable,2673 else => unreachable,
...@@ -2998,7 +3024,7 @@ fn writeStringTable(self: *Zld) !void {...@@ -2998,7 +3024,7 @@ fn writeStringTable(self: *Zld) !void {
29983024
2999 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);3025 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
30003026
3001 if (symtab.strsize > self.strtab.items.len and self.arch.? == .x86_64) {3027 if (symtab.strsize > self.strtab.items.len and self.target.?.cpu.arch == .x86_64) {
3002 // This is the last section, so we need to pad it out.3028 // This is the last section, so we need to pad it out.
3003 try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1);3029 try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1);
3004 }3030 }
...@@ -3046,7 +3072,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {...@@ -3046,7 +3072,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
3046 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;3072 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;
3047 const fileoff = seg.inner.fileoff + seg.inner.filesize;3073 const fileoff = seg.inner.fileoff + seg.inner.filesize;
3048 const needed_size = CodeSignature.calcCodeSignaturePaddingSize(3074 const needed_size = CodeSignature.calcCodeSignaturePaddingSize(
3049 self.out_path.?,3075 self.output.?.path,
3050 fileoff,3076 fileoff,
3051 self.page_size.?,3077 self.page_size.?,
3052 );3078 );
...@@ -3072,7 +3098,7 @@ fn writeCodeSignature(self: *Zld) !void {...@@ -3072,7 +3098,7 @@ fn writeCodeSignature(self: *Zld) !void {
3072 defer code_sig.deinit();3098 defer code_sig.deinit();
3073 try code_sig.calcAdhocSignature(3099 try code_sig.calcAdhocSignature(
3074 self.file.?,3100 self.file.?,
3075 self.out_path.?,3101 self.output.?.path,
3076 text_seg.inner,3102 text_seg.inner,
3077 code_sig_cmd,3103 code_sig_cmd,
3078 .Exe,3104 .Exe,
...@@ -3114,7 +3140,7 @@ fn writeHeader(self: *Zld) !void {...@@ -3114,7 +3140,7 @@ fn writeHeader(self: *Zld) !void {
3114 cpu_subtype: macho.cpu_subtype_t,3140 cpu_subtype: macho.cpu_subtype_t,
3115 };3141 };
31163142
3117 const cpu_info: CpuInfo = switch (self.arch.?) {3143 const cpu_info: CpuInfo = switch (self.target.?.cpu.arch) {
3118 .aarch64 => .{3144 .aarch64 => .{
3119 .cpu_type = macho.CPU_TYPE_ARM64,3145 .cpu_type = macho.CPU_TYPE_ARM64,
3120 .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,3146 .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,
...@@ -3127,8 +3153,22 @@ fn writeHeader(self: *Zld) !void {...@@ -3127,8 +3153,22 @@ fn writeHeader(self: *Zld) !void {
3127 };3153 };
3128 header.cputype = cpu_info.cpu_type;3154 header.cputype = cpu_info.cpu_type;
3129 header.cpusubtype = cpu_info.cpu_subtype;3155 header.cpusubtype = cpu_info.cpu_subtype;
3130 header.filetype = macho.MH_EXECUTE;3156
3131 header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;3157 switch (self.output.?.tag) {
3158 .exe => {
3159 header.filetype = macho.MH_EXECUTE;
3160 header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;
3161 },
3162 .dylib => {
3163 header.filetype = macho.MH_DYLIB;
3164 header.flags = macho.MH_NOUNDEFS |
3165 macho.MH_DYLDLINK |
3166 macho.MH_PIE |
3167 macho.MH_TWOLEVEL |
3168 macho.MH_NO_REEXPORTED_DYLIBS;
3169 },
3170 }
3171
3132 header.reserved = 0;3172 header.reserved = 0;
31333173
3134 if (self.tlv_section_index) |_|3174 if (self.tlv_section_index) |_|