authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-13 22:09:42-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-02 21:45:44-07:00
log148b963a606c2a7b71dced22d1d5b42cce4d9c04
treeb13ecc2a299ece729ad92b4e4a35185494a2896d
parentb713ce0249e68edd5db6fea79df4fffadbdc7ef9

Merge pull request #10584 from ziglang/macho-rustc-fixes

zld: a couple of fixes which result in better rustc support

9 files changed, 146 insertions(+), 31 deletions(-)

src/Compilation.zig+8-3
...@@ -636,6 +636,11 @@ pub const ClangPreprocessorMode = enum {...@@ -636,6 +636,11 @@ pub const ClangPreprocessorMode = enum {
636636
637pub const SystemLib = link.SystemLib;637pub const SystemLib = link.SystemLib;
638638
639pub const LinkObject = struct {
640 path: []const u8,
641 must_link: bool = false,
642};
643
639pub const InitOptions = struct {644pub const InitOptions = struct {
640 zig_lib_directory: Directory,645 zig_lib_directory: Directory,
641 local_cache_directory: Directory,646 local_cache_directory: Directory,
...@@ -679,7 +684,7 @@ pub const InitOptions = struct {...@@ -679,7 +684,7 @@ pub const InitOptions = struct {
679 lib_dirs: []const []const u8 = &[0][]const u8{},684 lib_dirs: []const []const u8 = &[0][]const u8{},
680 rpath_list: []const []const u8 = &[0][]const u8{},685 rpath_list: []const []const u8 = &[0][]const u8{},
681 c_source_files: []const CSourceFile = &[0]CSourceFile{},686 c_source_files: []const CSourceFile = &[0]CSourceFile{},
682 link_objects: []const []const u8 = &[0][]const u8{},687 link_objects: []LinkObject = &[0]LinkObject{},
683 framework_dirs: []const []const u8 = &[0][]const u8{},688 framework_dirs: []const []const u8 = &[0][]const u8{},
684 frameworks: []const []const u8 = &[0][]const u8{},689 frameworks: []const []const u8 = &[0][]const u8{},
685 system_lib_names: []const []const u8 = &.{},690 system_lib_names: []const []const u8 = &.{},
...@@ -1027,7 +1032,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1027,7 +1032,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1027 if (options.system_lib_names.len != 0)1032 if (options.system_lib_names.len != 0)
1028 break :x true;1033 break :x true;
1029 for (options.link_objects) |obj| {1034 for (options.link_objects) |obj| {
1030 switch (classifyFileExt(obj)) {1035 switch (classifyFileExt(obj.path)) {
1031 .shared_library => break :x true,1036 .shared_library => break :x true,
1032 else => continue,1037 else => continue,
1033 }1038 }
...@@ -1389,7 +1394,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1389,7 +1394,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1389 if (options.c_source_files.len >= 1) {1394 if (options.c_source_files.len >= 1) {
1390 hash.addBytes(options.c_source_files[0].src_path);1395 hash.addBytes(options.c_source_files[0].src_path);
1391 } else if (options.link_objects.len >= 1) {1396 } else if (options.link_objects.len >= 1) {
1392 hash.addBytes(options.link_objects[0]);1397 hash.addBytes(options.link_objects[0].path);
1393 }1398 }
13941399
1395 const digest = hash.final();1400 const digest = hash.final();
src/link.zig+7-4
...@@ -137,7 +137,7 @@ pub const Options = struct {...@@ -137,7 +137,7 @@ pub const Options = struct {
137 soname: ?[]const u8,137 soname: ?[]const u8,
138 llvm_cpu_features: ?[*:0]const u8,138 llvm_cpu_features: ?[*:0]const u8,
139139
140 objects: []const []const u8,140 objects: []Compilation.LinkObject,
141 framework_dirs: []const []const u8,141 framework_dirs: []const []const u8,
142 frameworks: []const []const u8,142 frameworks: []const []const u8,
143 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),143 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
...@@ -683,7 +683,10 @@ pub const File = struct {...@@ -683,7 +683,10 @@ pub const File = struct {
683 // We are about to obtain this lock, so here we give other processes a chance first.683 // We are about to obtain this lock, so here we give other processes a chance first.
684 base.releaseLock();684 base.releaseLock();
685685
686 try man.addListOfFiles(base.options.objects);686 for (base.options.objects) |obj| {
687 _ = try man.addFile(obj.path, null);
688 man.hash.add(obj.must_link);
689 }
687 for (comp.c_object_table.keys()) |key| {690 for (comp.c_object_table.keys()) |key| {
688 _ = try man.addFile(key.status.success.object_path, null);691 _ = try man.addFile(key.status.success.object_path, null);
689 }692 }
...@@ -720,8 +723,8 @@ pub const File = struct {...@@ -720,8 +723,8 @@ pub const File = struct {
720 var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files);723 var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files);
721 defer object_files.deinit();724 defer object_files.deinit();
722725
723 for (base.options.objects) |obj_path| {726 for (base.options.objects) |obj| {
724 object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path));727 object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj.path));
725 }728 }
726 for (comp.c_object_table.keys()) |key| {729 for (comp.c_object_table.keys()) |key| {
727 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path));730 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path));
src/link/Coff.zig+9-3
...@@ -920,7 +920,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -920,7 +920,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
920 man = comp.cache_parent.obtain();920 man = comp.cache_parent.obtain();
921 self.base.releaseLock();921 self.base.releaseLock();
922922
923 try man.addListOfFiles(self.base.options.objects);923 for (self.base.options.objects) |obj| {
924 _ = try man.addFile(obj.path, null);
925 man.hash.add(obj.must_link);
926 }
924 for (comp.c_object_table.keys()) |key| {927 for (comp.c_object_table.keys()) |key| {
925 _ = try man.addFile(key.status.success.object_path, null);928 _ = try man.addFile(key.status.success.object_path, null);
926 }929 }
...@@ -984,7 +987,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -984,7 +987,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
984 // build-obj. See also the corresponding TODO in linkAsArchive.987 // build-obj. See also the corresponding TODO in linkAsArchive.
985 const the_object_path = blk: {988 const the_object_path = blk: {
986 if (self.base.options.objects.len != 0)989 if (self.base.options.objects.len != 0)
987 break :blk self.base.options.objects[0];990 break :blk self.base.options.objects[0].path;
988991
989 if (comp.c_object_table.count() != 0)992 if (comp.c_object_table.count() != 0)
990 break :blk comp.c_object_table.keys()[0].status.success.object_path;993 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -1093,7 +1096,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -1093,7 +1096,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
1093 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));1096 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
1094 }1097 }
10951098
1096 try argv.appendSlice(self.base.options.objects);1099 try argv.ensureUnusedCapacity(self.base.options.objects.len);
1100 for (self.base.options.objects) |obj| {
1101 argv.appendAssumeCapacity(obj.path);
1102 }
10971103
1098 for (comp.c_object_table.keys()) |key| {1104 for (comp.c_object_table.keys()) |key| {
1099 try argv.append(key.status.success.object_path);1105 try argv.append(key.status.success.object_path);
src/link/Elf.zig+9-3
...@@ -1307,7 +1307,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1307,7 +1307,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
13071307
1308 try man.addOptionalFile(self.base.options.linker_script);1308 try man.addOptionalFile(self.base.options.linker_script);
1309 try man.addOptionalFile(self.base.options.version_script);1309 try man.addOptionalFile(self.base.options.version_script);
1310 try man.addListOfFiles(self.base.options.objects);1310 for (self.base.options.objects) |obj| {
1311 _ = try man.addFile(obj.path, null);
1312 man.hash.add(obj.must_link);
1313 }
1311 for (comp.c_object_table.keys()) |key| {1314 for (comp.c_object_table.keys()) |key| {
1312 _ = try man.addFile(key.status.success.object_path, null);1315 _ = try man.addFile(key.status.success.object_path, null);
1313 }1316 }
...@@ -1392,7 +1395,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1392,7 +1395,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1392 // build-obj. See also the corresponding TODO in linkAsArchive.1395 // build-obj. See also the corresponding TODO in linkAsArchive.
1393 const the_object_path = blk: {1396 const the_object_path = blk: {
1394 if (self.base.options.objects.len != 0)1397 if (self.base.options.objects.len != 0)
1395 break :blk self.base.options.objects[0];1398 break :blk self.base.options.objects[0].path;
13961399
1397 if (comp.c_object_table.count() != 0)1400 if (comp.c_object_table.count() != 0)
1398 break :blk comp.c_object_table.keys()[0].status.success.object_path;1401 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -1607,7 +1610,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1607,7 +1610,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1607 }1610 }
16081611
1609 // Positional arguments to the linker such as object files.1612 // Positional arguments to the linker such as object files.
1610 try argv.appendSlice(self.base.options.objects);1613 try argv.ensureUnusedCapacity(self.base.options.objects.len);
1614 for (self.base.options.objects) |obj| {
1615 argv.appendAssumeCapacity(obj.path);
1616 }
16111617
1612 for (comp.c_object_table.keys()) |key| {1618 for (comp.c_object_table.keys()) |key| {
1613 try argv.append(key.status.success.object_path);1619 try argv.append(key.status.success.object_path);
src/link/MachO.zig+87-8
...@@ -140,6 +140,9 @@ objc_selrefs_section_index: ?u16 = null,...@@ -140,6 +140,9 @@ objc_selrefs_section_index: ?u16 = null,
140objc_classrefs_section_index: ?u16 = null,140objc_classrefs_section_index: ?u16 = null,
141objc_data_section_index: ?u16 = null,141objc_data_section_index: ?u16 = null,
142142
143rustc_section_index: ?u16 = null,
144rustc_section_size: u64 = 0,
145
143bss_file_offset: u32 = 0,146bss_file_offset: u32 = 0,
144tlv_bss_file_offset: u32 = 0,147tlv_bss_file_offset: u32 = 0,
145148
...@@ -466,7 +469,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -466,7 +469,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
466 // We are about to obtain this lock, so here we give other processes a chance first.469 // We are about to obtain this lock, so here we give other processes a chance first.
467 self.base.releaseLock();470 self.base.releaseLock();
468471
469 try man.addListOfFiles(self.base.options.objects);472 for (self.base.options.objects) |obj| {
473 _ = try man.addFile(obj.path, null);
474 man.hash.add(obj.must_link);
475 }
470 for (comp.c_object_table.keys()) |key| {476 for (comp.c_object_table.keys()) |key| {
471 _ = try man.addFile(key.status.success.object_path, null);477 _ = try man.addFile(key.status.success.object_path, null);
472 }478 }
...@@ -539,8 +545,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -539,8 +545,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
539 // here. TODO: think carefully about how we can avoid this redundant operation when doing545 // here. TODO: think carefully about how we can avoid this redundant operation when doing
540 // build-obj. See also the corresponding TODO in linkAsArchive.546 // build-obj. See also the corresponding TODO in linkAsArchive.
541 const the_object_path = blk: {547 const the_object_path = blk: {
542 if (self.base.options.objects.len != 0)548 if (self.base.options.objects.len != 0) {
543 break :blk self.base.options.objects[0];549 break :blk self.base.options.objects[0].path;
550 }
544551
545 if (comp.c_object_table.count() != 0)552 if (comp.c_object_table.count() != 0)
546 break :blk comp.c_object_table.keys()[0].status.success.object_path;553 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -649,8 +656,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -649,8 +656,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
649656
650 // Positional arguments to the linker such as object files and static archives.657 // Positional arguments to the linker such as object files and static archives.
651 var positionals = std.ArrayList([]const u8).init(arena);658 var positionals = std.ArrayList([]const u8).init(arena);
659 try positionals.ensureUnusedCapacity(self.base.options.objects.len);
652660
653 try positionals.appendSlice(self.base.options.objects);661 var must_link_archives = std.StringArrayHashMap(void).init(arena);
662 try must_link_archives.ensureUnusedCapacity(self.base.options.objects.len);
663
664 for (self.base.options.objects) |obj| {
665 if (must_link_archives.contains(obj.path)) continue;
666 if (obj.must_link) {
667 _ = must_link_archives.getOrPutAssumeCapacity(obj.path);
668 } else {
669 _ = positionals.appendAssumeCapacity(obj.path);
670 }
671 }
654672
655 for (comp.c_object_table.keys()) |key| {673 for (comp.c_object_table.keys()) |key| {
656 try positionals.append(key.status.success.object_path);674 try positionals.append(key.status.success.object_path);
...@@ -857,12 +875,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -857,12 +875,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
857 try argv.append("dynamic_lookup");875 try argv.append("dynamic_lookup");
858 }876 }
859877
878 for (must_link_archives.keys()) |lib| {
879 try argv.append(try std.fmt.allocPrint(arena, "-force_load {s}", .{lib}));
880 }
881
860 Compilation.dump_argv(argv.items);882 Compilation.dump_argv(argv.items);
861 }883 }
862884
863 var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator);885 var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator);
864 defer dependent_libs.deinit();886 defer dependent_libs.deinit();
865 try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs);887 try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs);
888 try self.parseAndForceLoadStaticArchives(must_link_archives.keys());
866 try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs);889 try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs);
867 try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs);890 try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs);
868 }891 }
...@@ -953,6 +976,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -953,6 +976,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
953 try self.writeAtoms();976 try self.writeAtoms();
954 }977 }
955978
979 if (self.rustc_section_index) |id| {
980 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment;
981 const sect = &seg.sections.items[id];
982 sect.size = self.rustc_section_size;
983 }
984
956 try self.setEntryPoint();985 try self.setEntryPoint();
957 try self.updateSectionOrdinals();986 try self.updateSectionOrdinals();
958 try self.writeLinkeditSegment();987 try self.writeLinkeditSegment();
...@@ -1142,7 +1171,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool {...@@ -1142,7 +1171,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool {
1142 return true;1171 return true;
1143}1172}
11441173
1145fn parseArchive(self: *MachO, path: []const u8) !bool {1174fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {
1146 const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {1175 const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
1147 error.FileNotFound => return false,1176 error.FileNotFound => return false,
1148 else => |e| return e,1177 else => |e| return e,
...@@ -1165,7 +1194,23 @@ fn parseArchive(self: *MachO, path: []const u8) !bool {...@@ -1165,7 +1194,23 @@ fn parseArchive(self: *MachO, path: []const u8) !bool {
1165 else => |e| return e,1194 else => |e| return e,
1166 };1195 };
11671196
1168 try self.archives.append(self.base.allocator, archive);1197 if (force_load) {
1198 defer archive.deinit(self.base.allocator);
1199 // Get all offsets from the ToC
1200 var offsets = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
1201 defer offsets.deinit();
1202 for (archive.toc.values()) |offs| {
1203 for (offs.items) |off| {
1204 _ = try offsets.getOrPut(off);
1205 }
1206 }
1207 for (offsets.keys()) |off| {
1208 const object = try self.objects.addOne(self.base.allocator);
1209 object.* = try archive.parseObject(self.base.allocator, self.base.options.target, off);
1210 }
1211 } else {
1212 try self.archives.append(self.base.allocator, archive);
1213 }
11691214
1170 return true;1215 return true;
1171}1216}
...@@ -1250,7 +1295,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const...@@ -1250,7 +1295,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
1250 log.debug("parsing input file path '{s}'", .{full_path});1295 log.debug("parsing input file path '{s}'", .{full_path});
12511296
1252 if (try self.parseObject(full_path)) continue;1297 if (try self.parseObject(full_path)) continue;
1253 if (try self.parseArchive(full_path)) continue;1298 if (try self.parseArchive(full_path, false)) continue;
1254 if (try self.parseDylib(full_path, .{1299 if (try self.parseDylib(full_path, .{
1255 .syslibroot = syslibroot,1300 .syslibroot = syslibroot,
1256 .dependent_libs = dependent_libs,1301 .dependent_libs = dependent_libs,
...@@ -1260,6 +1305,21 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const...@@ -1260,6 +1305,21 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
1260 }1305 }
1261}1306}
12621307
1308fn parseAndForceLoadStaticArchives(self: *MachO, files: []const []const u8) !void {
1309 for (files) |file_name| {
1310 const full_path = full_path: {
1311 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
1312 const path = try fs.realpath(file_name, &buffer);
1313 break :full_path try self.base.allocator.dupe(u8, path);
1314 };
1315 defer self.base.allocator.free(full_path);
1316 log.debug("parsing and force loading static archive '{s}'", .{full_path});
1317
1318 if (try self.parseArchive(full_path, true)) continue;
1319 log.warn("unknown filetype: expected static archive: '{s}'", .{file_name});
1320 }
1321}
1322
1263fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void {1323fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void {
1264 for (libs) |lib| {1324 for (libs) |lib| {
1265 log.debug("parsing lib path '{s}'", .{lib});1325 log.debug("parsing lib path '{s}'", .{lib});
...@@ -1267,7 +1327,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, de...@@ -1267,7 +1327,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, de
1267 .syslibroot = syslibroot,1327 .syslibroot = syslibroot,
1268 .dependent_libs = dependent_libs,1328 .dependent_libs = dependent_libs,
1269 })) continue;1329 })) continue;
1270 if (try self.parseArchive(lib)) continue;1330 if (try self.parseArchive(lib, false)) continue;
12711331
1272 log.warn("unknown filetype for a library: '{s}'", .{lib});1332 log.warn("unknown filetype for a library: '{s}'", .{lib});
1273 }1333 }
...@@ -1833,6 +1893,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1833,6 +1893,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1833 .seg = self.data_segment_cmd_index.?,1893 .seg = self.data_segment_cmd_index.?,
1834 .sect = self.objc_data_section_index.?,1894 .sect = self.objc_data_section_index.?,
1835 };1895 };
1896 } else if (mem.eql(u8, sectname, ".rustc")) {
1897 if (self.rustc_section_index == null) {
1898 self.rustc_section_index = try self.initSection(
1899 self.data_segment_cmd_index.?,
1900 ".rustc",
1901 sect.size,
1902 sect.@"align",
1903 .{},
1904 );
1905 // We need to preserve the section size for rustc to properly
1906 // decompress the metadata.
1907 self.rustc_section_size = sect.size;
1908 }
1909
1910 break :blk .{
1911 .seg = self.data_segment_cmd_index.?,
1912 .sect = self.rustc_section_index.?,
1913 };
1836 } else {1914 } else {
1837 if (self.data_section_index == null) {1915 if (self.data_section_index == null) {
1838 self.data_section_index = try self.initSection(1916 self.data_section_index = try self.initSection(
...@@ -5003,6 +5081,7 @@ fn sortSections(self: *MachO) !void {...@@ -5003,6 +5081,7 @@ fn sortSections(self: *MachO) !void {
50035081
5004 // __DATA segment5082 // __DATA segment
5005 const indices = &[_]*?u16{5083 const indices = &[_]*?u16{
5084 &self.rustc_section_index,
5006 &self.la_symbol_ptr_section_index,5085 &self.la_symbol_ptr_section_index,
5007 &self.objc_const_section_index,5086 &self.objc_const_section_index,
5008 &self.objc_selrefs_section_index,5087 &self.objc_selrefs_section_index,
src/link/MachO/Atom.zig+2-1
...@@ -419,6 +419,7 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC...@@ -419,6 +419,7 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC
419 .X86_64_RELOC_BRANCH => {419 .X86_64_RELOC_BRANCH => {
420 // TODO rewrite relocation420 // TODO rewrite relocation
421 try addStub(target, context);421 try addStub(target, context);
422 addend = mem.readIntLittle(i32, self.code.items[offset..][0..4]);
422 },423 },
423 .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD => {424 .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD => {
424 // TODO rewrite relocation425 // TODO rewrite relocation
...@@ -1003,7 +1004,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -1003,7 +1004,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
1003 .X86_64_RELOC_BRANCH => {1004 .X86_64_RELOC_BRANCH => {
1004 const displacement = try math.cast(1005 const displacement = try math.cast(
1005 i32,1006 i32,
1006 @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4,1007 @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4 + rel.addend,
1007 );1008 );
1008 mem.writeIntLittle(u32, self.code.items[rel.offset..][0..4], @bitCast(u32, displacement));1009 mem.writeIntLittle(u32, self.code.items[rel.offset..][0..4], @bitCast(u32, displacement));
1009 },1010 },
src/link/MachO/Object.zig+1-1
...@@ -409,7 +409,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !...@@ -409,7 +409,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !
409 } else blk: {409 } else blk: {
410 var iundefsym: usize = sorted_all_nlists.items.len;410 var iundefsym: usize = sorted_all_nlists.items.len;
411 while (iundefsym > 0) : (iundefsym -= 1) {411 while (iundefsym > 0) : (iundefsym -= 1) {
412 const nlist = sorted_all_nlists.items[iundefsym];412 const nlist = sorted_all_nlists.items[iundefsym - 1];
413 if (nlist.nlist.sect()) break;413 if (nlist.nlist.sect()) break;
414 }414 }
415 break :blk iundefsym;415 break :blk iundefsym;
src/link/Wasm.zig+9-3
...@@ -1012,7 +1012,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1012,7 +1012,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1012 // We are about to obtain this lock, so here we give other processes a chance first.1012 // We are about to obtain this lock, so here we give other processes a chance first.
1013 self.base.releaseLock();1013 self.base.releaseLock();
10141014
1015 try man.addListOfFiles(self.base.options.objects);1015 for (self.base.options.objects) |obj| {
1016 _ = try man.addFile(obj.path, null);
1017 man.hash.add(obj.must_link);
1018 }
1016 for (comp.c_object_table.keys()) |key| {1019 for (comp.c_object_table.keys()) |key| {
1017 _ = try man.addFile(key.status.success.object_path, null);1020 _ = try man.addFile(key.status.success.object_path, null);
1018 }1021 }
...@@ -1065,7 +1068,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1065,7 +1068,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1065 // build-obj. See also the corresponding TODO in linkAsArchive.1068 // build-obj. See also the corresponding TODO in linkAsArchive.
1066 const the_object_path = blk: {1069 const the_object_path = blk: {
1067 if (self.base.options.objects.len != 0)1070 if (self.base.options.objects.len != 0)
1068 break :blk self.base.options.objects[0];1071 break :blk self.base.options.objects[0].path;
10691072
1070 if (comp.c_object_table.count() != 0)1073 if (comp.c_object_table.count() != 0)
1071 break :blk comp.c_object_table.keys()[0].status.success.object_path;1074 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -1225,7 +1228,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1225,7 +1228,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1225 }1228 }
12261229
1227 // Positional arguments to the linker such as object files.1230 // Positional arguments to the linker such as object files.
1228 try argv.appendSlice(self.base.options.objects);1231 try argv.ensureUnusedCapacity(self.base.options.objects.len);
1232 for (self.base.options.objects) |obj| {
1233 argv.appendAssumeCapacity(obj.path);
1234 }
12291235
1230 for (comp.c_object_table.keys()) |key| {1236 for (comp.c_object_table.keys()) |key| {
1231 try argv.append(key.status.success.object_path);1237 try argv.append(key.status.success.object_path);
src/main.zig+14-5
...@@ -703,7 +703,7 @@ fn buildOutputType(...@@ -703,7 +703,7 @@ fn buildOutputType(
703 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa);703 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa);
704 defer c_source_files.deinit();704 defer c_source_files.deinit();
705705
706 var link_objects = std.ArrayList([]const u8).init(gpa);706 var link_objects = std.ArrayList(Compilation.LinkObject).init(gpa);
707 defer link_objects.deinit();707 defer link_objects.deinit();
708708
709 var framework_dirs = std.ArrayList([]const u8).init(gpa);709 var framework_dirs = std.ArrayList([]const u8).init(gpa);
...@@ -1236,7 +1236,7 @@ fn buildOutputType(...@@ -1236,7 +1236,7 @@ fn buildOutputType(
1236 }1236 }
1237 } else switch (Compilation.classifyFileExt(arg)) {1237 } else switch (Compilation.classifyFileExt(arg)) {
1238 .object, .static_library, .shared_library => {1238 .object, .static_library, .shared_library => {
1239 try link_objects.append(arg);1239 try link_objects.append(.{ .path = arg });
1240 },1240 },
1241 .assembly, .c, .cpp, .h, .ll, .bc, .m, .mm => {1241 .assembly, .c, .cpp, .h, .ll, .bc, .m, .mm => {
1242 try c_source_files.append(.{1242 try c_source_files.append(.{
...@@ -1307,7 +1307,7 @@ fn buildOutputType(...@@ -1307,7 +1307,7 @@ fn buildOutputType(
1307 switch (file_ext) {1307 switch (file_ext) {
1308 .assembly, .c, .cpp, .ll, .bc, .h, .m, .mm => try c_source_files.append(.{ .src_path = it.only_arg }),1308 .assembly, .c, .cpp, .ll, .bc, .h, .m, .mm => try c_source_files.append(.{ .src_path = it.only_arg }),
1309 .unknown, .shared_library, .object, .static_library => {1309 .unknown, .shared_library, .object, .static_library => {
1310 try link_objects.append(it.only_arg);1310 try link_objects.append(.{ .path = it.only_arg });
1311 },1311 },
1312 .zig => {1312 .zig => {
1313 if (root_src_file) |other| {1313 if (root_src_file) |other| {
...@@ -1751,6 +1751,15 @@ fn buildOutputType(...@@ -1751,6 +1751,15 @@ fn buildOutputType(
1751 fatal("expected linker arg after '{s}'", .{arg});1751 fatal("expected linker arg after '{s}'", .{arg});
1752 }1752 }
1753 install_name = linker_args.items[i];1753 install_name = linker_args.items[i];
1754 } else if (mem.eql(u8, arg, "-force_load")) {
1755 i += 1;
1756 if (i >= linker_args.items.len) {
1757 fatal("expected linker arg after '{s}'", .{arg});
1758 }
1759 try link_objects.append(.{
1760 .path = linker_args.items[i],
1761 .must_link = true,
1762 });
1754 } else {1763 } else {
1755 warn("unsupported linker arg: {s}", .{arg});1764 warn("unsupported linker arg: {s}", .{arg});
1756 }1765 }
...@@ -1845,7 +1854,7 @@ fn buildOutputType(...@@ -1845,7 +1854,7 @@ fn buildOutputType(
1845 const basename = fs.path.basename(c_source_files.items[0].src_path);1854 const basename = fs.path.basename(c_source_files.items[0].src_path);
1846 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];1855 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
1847 } else if (link_objects.items.len >= 1) {1856 } else if (link_objects.items.len >= 1) {
1848 const basename = fs.path.basename(link_objects.items[0]);1857 const basename = fs.path.basename(link_objects.items[0].path);
1849 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];1858 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
1850 } else if (emit_bin == .yes) {1859 } else if (emit_bin == .yes) {
1851 const basename = fs.path.basename(emit_bin.yes);1860 const basename = fs.path.basename(emit_bin.yes);
...@@ -2048,7 +2057,7 @@ fn buildOutputType(...@@ -2048,7 +2057,7 @@ fn buildOutputType(
2048 test_path.items, @errorName(e),2057 test_path.items, @errorName(e),
2049 }),2058 }),
2050 };2059 };
2051 try link_objects.append(try arena.dupe(u8, test_path.items));2060 try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) });
2052 break;2061 break;
2053 } else {2062 } else {
2054 var search_paths = std.ArrayList(u8).init(arena);2063 var search_paths = std.ArrayList(u8).init(arena);