authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-13 22:09:42-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-13 22:09:42-05:00
log75b6637d6013b735d36da0ab6e5655002a1b59e9
tree76d3d25d4307138e34450da7ca30310f12197941
parent7e76aab98abe94e01cfd8b01ce288360ed67dbc7
parent5cde5f947fa12440463f684d9417ac00c8b9790a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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

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

9 files changed, 150 insertions(+), 32 deletions(-)

src/Compilation.zig+13-4
...@@ -654,6 +654,11 @@ pub const ClangPreprocessorMode = enum {...@@ -654,6 +654,11 @@ pub const ClangPreprocessorMode = enum {
654pub const SystemLib = link.SystemLib;654pub const SystemLib = link.SystemLib;
655pub const CacheMode = link.CacheMode;655pub const CacheMode = link.CacheMode;
656656
657pub const LinkObject = struct {
658 path: []const u8,
659 must_link: bool = false,
660};
661
657pub const InitOptions = struct {662pub const InitOptions = struct {
658 zig_lib_directory: Directory,663 zig_lib_directory: Directory,
659 local_cache_directory: Directory,664 local_cache_directory: Directory,
...@@ -698,7 +703,7 @@ pub const InitOptions = struct {...@@ -698,7 +703,7 @@ pub const InitOptions = struct {
698 lib_dirs: []const []const u8 = &[0][]const u8{},703 lib_dirs: []const []const u8 = &[0][]const u8{},
699 rpath_list: []const []const u8 = &[0][]const u8{},704 rpath_list: []const []const u8 = &[0][]const u8{},
700 c_source_files: []const CSourceFile = &[0]CSourceFile{},705 c_source_files: []const CSourceFile = &[0]CSourceFile{},
701 link_objects: []const []const u8 = &[0][]const u8{},706 link_objects: []LinkObject = &[0]LinkObject{},
702 framework_dirs: []const []const u8 = &[0][]const u8{},707 framework_dirs: []const []const u8 = &[0][]const u8{},
703 frameworks: []const []const u8 = &[0][]const u8{},708 frameworks: []const []const u8 = &[0][]const u8{},
704 system_lib_names: []const []const u8 = &.{},709 system_lib_names: []const []const u8 = &.{},
...@@ -1056,7 +1061,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1056,7 +1061,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1056 if (options.system_lib_names.len != 0)1061 if (options.system_lib_names.len != 0)
1057 break :x true;1062 break :x true;
1058 for (options.link_objects) |obj| {1063 for (options.link_objects) |obj| {
1059 switch (classifyFileExt(obj)) {1064 switch (classifyFileExt(obj.path)) {
1060 .shared_library => break :x true,1065 .shared_library => break :x true,
1061 else => continue,1066 else => continue,
1062 }1067 }
...@@ -1459,7 +1464,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1459,7 +1464,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1459 if (options.c_source_files.len >= 1) {1464 if (options.c_source_files.len >= 1) {
1460 hash.addBytes(options.c_source_files[0].src_path);1465 hash.addBytes(options.c_source_files[0].src_path);
1461 } else if (options.link_objects.len >= 1) {1466 } else if (options.link_objects.len >= 1) {
1462 hash.addBytes(options.link_objects[0]);1467 hash.addBytes(options.link_objects[0].path);
1463 }1468 }
14641469
1465 const digest = hash.final();1470 const digest = hash.final();
...@@ -2265,7 +2270,11 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2265,7 +2270,11 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
22652270
2266 try man.addOptionalFile(comp.bin_file.options.linker_script);2271 try man.addOptionalFile(comp.bin_file.options.linker_script);
2267 try man.addOptionalFile(comp.bin_file.options.version_script);2272 try man.addOptionalFile(comp.bin_file.options.version_script);
2268 try man.addListOfFiles(comp.bin_file.options.objects);2273
2274 for (comp.bin_file.options.objects) |obj| {
2275 _ = try man.addFile(obj.path, null);
2276 man.hash.add(obj.must_link);
2277 }
22692278
2270 for (comp.c_object_table.keys()) |key| {2279 for (comp.c_object_table.keys()) |key| {
2271 _ = try man.addFile(key.src.src_path, null);2280 _ = try man.addFile(key.src.src_path, null);
src/link.zig+7-4
...@@ -155,7 +155,7 @@ pub const Options = struct {...@@ -155,7 +155,7 @@ pub const Options = struct {
155 soname: ?[]const u8,155 soname: ?[]const u8,
156 llvm_cpu_features: ?[*:0]const u8,156 llvm_cpu_features: ?[*:0]const u8,
157157
158 objects: []const []const u8,158 objects: []Compilation.LinkObject,
159 framework_dirs: []const []const u8,159 framework_dirs: []const []const u8,
160 frameworks: []const []const u8,160 frameworks: []const []const u8,
161 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),161 system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
...@@ -755,7 +755,10 @@ pub const File = struct {...@@ -755,7 +755,10 @@ pub const File = struct {
755 // We are about to obtain this lock, so here we give other processes a chance first.755 // We are about to obtain this lock, so here we give other processes a chance first.
756 base.releaseLock();756 base.releaseLock();
757757
758 try man.addListOfFiles(base.options.objects);758 for (base.options.objects) |obj| {
759 _ = try man.addFile(obj.path, null);
760 man.hash.add(obj.must_link);
761 }
759 for (comp.c_object_table.keys()) |key| {762 for (comp.c_object_table.keys()) |key| {
760 _ = try man.addFile(key.status.success.object_path, null);763 _ = try man.addFile(key.status.success.object_path, null);
761 }764 }
...@@ -792,8 +795,8 @@ pub const File = struct {...@@ -792,8 +795,8 @@ pub const File = struct {
792 var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files);795 var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files);
793 defer object_files.deinit();796 defer object_files.deinit();
794797
795 for (base.options.objects) |obj_path| {798 for (base.options.objects) |obj| {
796 object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path));799 object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj.path));
797 }800 }
798 for (comp.c_object_table.keys()) |key| {801 for (comp.c_object_table.keys()) |key| {
799 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path));802 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path));
src/link/Coff.zig+9-3
...@@ -943,7 +943,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -943,7 +943,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
943943
944 comptime assert(Compilation.link_hash_implementation_version == 1);944 comptime assert(Compilation.link_hash_implementation_version == 1);
945945
946 try man.addListOfFiles(self.base.options.objects);946 for (self.base.options.objects) |obj| {
947 _ = try man.addFile(obj.path, null);
948 man.hash.add(obj.must_link);
949 }
947 for (comp.c_object_table.keys()) |key| {950 for (comp.c_object_table.keys()) |key| {
948 _ = try man.addFile(key.status.success.object_path, null);951 _ = try man.addFile(key.status.success.object_path, null);
949 }952 }
...@@ -1005,7 +1008,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -1005,7 +1008,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
1005 // build-obj. See also the corresponding TODO in linkAsArchive.1008 // build-obj. See also the corresponding TODO in linkAsArchive.
1006 const the_object_path = blk: {1009 const the_object_path = blk: {
1007 if (self.base.options.objects.len != 0)1010 if (self.base.options.objects.len != 0)
1008 break :blk self.base.options.objects[0];1011 break :blk self.base.options.objects[0].path;
10091012
1010 if (comp.c_object_table.count() != 0)1013 if (comp.c_object_table.count() != 0)
1011 break :blk comp.c_object_table.keys()[0].status.success.object_path;1014 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -1110,7 +1113,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -1110,7 +1113,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
1110 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));1113 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
1111 }1114 }
11121115
1113 try argv.appendSlice(self.base.options.objects);1116 try argv.ensureUnusedCapacity(self.base.options.objects.len);
1117 for (self.base.options.objects) |obj| {
1118 argv.appendAssumeCapacity(obj.path);
1119 }
11141120
1115 for (comp.c_object_table.keys()) |key| {1121 for (comp.c_object_table.keys()) |key| {
1116 try argv.append(key.status.success.object_path);1122 try argv.append(key.status.success.object_path);
src/link/Elf.zig+9-3
...@@ -1384,7 +1384,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1384,7 +1384,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
13841384
1385 try man.addOptionalFile(self.base.options.linker_script);1385 try man.addOptionalFile(self.base.options.linker_script);
1386 try man.addOptionalFile(self.base.options.version_script);1386 try man.addOptionalFile(self.base.options.version_script);
1387 try man.addListOfFiles(self.base.options.objects);1387 for (self.base.options.objects) |obj| {
1388 _ = try man.addFile(obj.path, null);
1389 man.hash.add(obj.must_link);
1390 }
1388 for (comp.c_object_table.keys()) |key| {1391 for (comp.c_object_table.keys()) |key| {
1389 _ = try man.addFile(key.status.success.object_path, null);1392 _ = try man.addFile(key.status.success.object_path, null);
1390 }1393 }
...@@ -1469,7 +1472,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1469,7 +1472,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1469 // build-obj. See also the corresponding TODO in linkAsArchive.1472 // build-obj. See also the corresponding TODO in linkAsArchive.
1470 const the_object_path = blk: {1473 const the_object_path = blk: {
1471 if (self.base.options.objects.len != 0)1474 if (self.base.options.objects.len != 0)
1472 break :blk self.base.options.objects[0];1475 break :blk self.base.options.objects[0].path;
14731476
1474 if (comp.c_object_table.count() != 0)1477 if (comp.c_object_table.count() != 0)
1475 break :blk comp.c_object_table.keys()[0].status.success.object_path;1478 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -1678,7 +1681,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1678,7 +1681,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1678 }1681 }
16791682
1680 // Positional arguments to the linker such as object files.1683 // Positional arguments to the linker such as object files.
1681 try argv.appendSlice(self.base.options.objects);1684 try argv.ensureUnusedCapacity(self.base.options.objects.len);
1685 for (self.base.options.objects) |obj| {
1686 argv.appendAssumeCapacity(obj.path);
1687 }
16821688
1683 for (comp.c_object_table.keys()) |key| {1689 for (comp.c_object_table.keys()) |key| {
1684 try argv.append(key.status.success.object_path);1690 try argv.append(key.status.success.object_path);
src/link/MachO.zig+86-8
...@@ -141,6 +141,9 @@ objc_selrefs_section_index: ?u16 = null,...@@ -141,6 +141,9 @@ objc_selrefs_section_index: ?u16 = null,
141objc_classrefs_section_index: ?u16 = null,141objc_classrefs_section_index: ?u16 = null,
142objc_data_section_index: ?u16 = null,142objc_data_section_index: ?u16 = null,
143143
144rustc_section_index: ?u16 = null,
145rustc_section_size: u64 = 0,
146
144bss_file_offset: u32 = 0,147bss_file_offset: u32 = 0,
145tlv_bss_file_offset: u32 = 0,148tlv_bss_file_offset: u32 = 0,
146149
...@@ -496,7 +499,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -496,7 +499,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
496499
497 comptime assert(Compilation.link_hash_implementation_version == 1);500 comptime assert(Compilation.link_hash_implementation_version == 1);
498501
499 try man.addListOfFiles(self.base.options.objects);502 for (self.base.options.objects) |obj| {
503 _ = try man.addFile(obj.path, null);
504 man.hash.add(obj.must_link);
505 }
500 for (comp.c_object_table.keys()) |key| {506 for (comp.c_object_table.keys()) |key| {
501 _ = try man.addFile(key.status.success.object_path, null);507 _ = try man.addFile(key.status.success.object_path, null);
502 }508 }
...@@ -568,8 +574,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -568,8 +574,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
568 // here. TODO: think carefully about how we can avoid this redundant operation when doing574 // here. TODO: think carefully about how we can avoid this redundant operation when doing
569 // build-obj. See also the corresponding TODO in linkAsArchive.575 // build-obj. See also the corresponding TODO in linkAsArchive.
570 const the_object_path = blk: {576 const the_object_path = blk: {
571 if (self.base.options.objects.len != 0)577 if (self.base.options.objects.len != 0) {
572 break :blk self.base.options.objects[0];578 break :blk self.base.options.objects[0].path;
579 }
573580
574 if (comp.c_object_table.count() != 0)581 if (comp.c_object_table.count() != 0)
575 break :blk comp.c_object_table.keys()[0].status.success.object_path;582 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -678,8 +685,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -678,8 +685,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
678685
679 // Positional arguments to the linker such as object files and static archives.686 // Positional arguments to the linker such as object files and static archives.
680 var positionals = std.ArrayList([]const u8).init(arena);687 var positionals = std.ArrayList([]const u8).init(arena);
688 try positionals.ensureUnusedCapacity(self.base.options.objects.len);
681689
682 try positionals.appendSlice(self.base.options.objects);690 var must_link_archives = std.StringArrayHashMap(void).init(arena);
691 try must_link_archives.ensureUnusedCapacity(self.base.options.objects.len);
692
693 for (self.base.options.objects) |obj| {
694 if (must_link_archives.contains(obj.path)) continue;
695 if (obj.must_link) {
696 _ = must_link_archives.getOrPutAssumeCapacity(obj.path);
697 } else {
698 _ = positionals.appendAssumeCapacity(obj.path);
699 }
700 }
683701
684 for (comp.c_object_table.keys()) |key| {702 for (comp.c_object_table.keys()) |key| {
685 try positionals.append(key.status.success.object_path);703 try positionals.append(key.status.success.object_path);
...@@ -886,12 +904,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -886,12 +904,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
886 try argv.append("dynamic_lookup");904 try argv.append("dynamic_lookup");
887 }905 }
888906
907 for (must_link_archives.keys()) |lib| {
908 try argv.append(try std.fmt.allocPrint(arena, "-force_load {s}", .{lib}));
909 }
910
889 Compilation.dump_argv(argv.items);911 Compilation.dump_argv(argv.items);
890 }912 }
891913
892 var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator);914 var dependent_libs = std.fifo.LinearFifo(Dylib.Id, .Dynamic).init(self.base.allocator);
893 defer dependent_libs.deinit();915 defer dependent_libs.deinit();
894 try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs);916 try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs);
917 try self.parseAndForceLoadStaticArchives(must_link_archives.keys());
895 try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs);918 try self.parseLibs(libs.items, self.base.options.sysroot, &dependent_libs);
896 try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs);919 try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs);
897 }920 }
...@@ -993,6 +1016,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -993,6 +1016,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
993 try self.writeAtoms();1016 try self.writeAtoms();
994 }1017 }
9951018
1019 if (self.rustc_section_index) |id| {
1020 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment;
1021 const sect = &seg.sections.items[id];
1022 sect.size = self.rustc_section_size;
1023 }
996 if (self.bss_section_index) |idx| {1024 if (self.bss_section_index) |idx| {
997 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment;1025 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment;
998 const sect = &seg.sections.items[idx];1026 const sect = &seg.sections.items[idx];
...@@ -1195,7 +1223,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool {...@@ -1195,7 +1223,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool {
1195 return true;1223 return true;
1196}1224}
11971225
1198fn parseArchive(self: *MachO, path: []const u8) !bool {1226fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {
1199 const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {1227 const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
1200 error.FileNotFound => return false,1228 error.FileNotFound => return false,
1201 else => |e| return e,1229 else => |e| return e,
...@@ -1218,7 +1246,23 @@ fn parseArchive(self: *MachO, path: []const u8) !bool {...@@ -1218,7 +1246,23 @@ fn parseArchive(self: *MachO, path: []const u8) !bool {
1218 else => |e| return e,1246 else => |e| return e,
1219 };1247 };
12201248
1221 try self.archives.append(self.base.allocator, archive);1249 if (force_load) {
1250 defer archive.deinit(self.base.allocator);
1251 // Get all offsets from the ToC
1252 var offsets = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
1253 defer offsets.deinit();
1254 for (archive.toc.values()) |offs| {
1255 for (offs.items) |off| {
1256 _ = try offsets.getOrPut(off);
1257 }
1258 }
1259 for (offsets.keys()) |off| {
1260 const object = try self.objects.addOne(self.base.allocator);
1261 object.* = try archive.parseObject(self.base.allocator, self.base.options.target, off);
1262 }
1263 } else {
1264 try self.archives.append(self.base.allocator, archive);
1265 }
12221266
1223 return true;1267 return true;
1224}1268}
...@@ -1303,7 +1347,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const...@@ -1303,7 +1347,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
1303 log.debug("parsing input file path '{s}'", .{full_path});1347 log.debug("parsing input file path '{s}'", .{full_path});
13041348
1305 if (try self.parseObject(full_path)) continue;1349 if (try self.parseObject(full_path)) continue;
1306 if (try self.parseArchive(full_path)) continue;1350 if (try self.parseArchive(full_path, false)) continue;
1307 if (try self.parseDylib(full_path, .{1351 if (try self.parseDylib(full_path, .{
1308 .syslibroot = syslibroot,1352 .syslibroot = syslibroot,
1309 .dependent_libs = dependent_libs,1353 .dependent_libs = dependent_libs,
...@@ -1313,6 +1357,21 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const...@@ -1313,6 +1357,21 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
1313 }1357 }
1314}1358}
13151359
1360fn parseAndForceLoadStaticArchives(self: *MachO, files: []const []const u8) !void {
1361 for (files) |file_name| {
1362 const full_path = full_path: {
1363 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
1364 const path = try fs.realpath(file_name, &buffer);
1365 break :full_path try self.base.allocator.dupe(u8, path);
1366 };
1367 defer self.base.allocator.free(full_path);
1368 log.debug("parsing and force loading static archive '{s}'", .{full_path});
1369
1370 if (try self.parseArchive(full_path, true)) continue;
1371 log.warn("unknown filetype: expected static archive: '{s}'", .{file_name});
1372 }
1373}
1374
1316fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void {1375fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, dependent_libs: anytype) !void {
1317 for (libs) |lib| {1376 for (libs) |lib| {
1318 log.debug("parsing lib path '{s}'", .{lib});1377 log.debug("parsing lib path '{s}'", .{lib});
...@@ -1320,7 +1379,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, de...@@ -1320,7 +1379,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8, de
1320 .syslibroot = syslibroot,1379 .syslibroot = syslibroot,
1321 .dependent_libs = dependent_libs,1380 .dependent_libs = dependent_libs,
1322 })) continue;1381 })) continue;
1323 if (try self.parseArchive(lib)) continue;1382 if (try self.parseArchive(lib, false)) continue;
13241383
1325 log.warn("unknown filetype for a library: '{s}'", .{lib});1384 log.warn("unknown filetype for a library: '{s}'", .{lib});
1326 }1385 }
...@@ -1886,6 +1945,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1886,6 +1945,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1886 .seg = self.data_segment_cmd_index.?,1945 .seg = self.data_segment_cmd_index.?,
1887 .sect = self.objc_data_section_index.?,1946 .sect = self.objc_data_section_index.?,
1888 };1947 };
1948 } else if (mem.eql(u8, sectname, ".rustc")) {
1949 if (self.rustc_section_index == null) {
1950 self.rustc_section_index = try self.initSection(
1951 self.data_segment_cmd_index.?,
1952 ".rustc",
1953 sect.size,
1954 sect.@"align",
1955 .{},
1956 );
1957 // We need to preserve the section size for rustc to properly
1958 // decompress the metadata.
1959 self.rustc_section_size = sect.size;
1960 }
1961
1962 break :blk .{
1963 .seg = self.data_segment_cmd_index.?,
1964 .sect = self.rustc_section_index.?,
1965 };
1889 } else {1966 } else {
1890 if (self.data_section_index == null) {1967 if (self.data_section_index == null) {
1891 self.data_section_index = try self.initSection(1968 self.data_section_index = try self.initSection(
...@@ -5212,6 +5289,7 @@ fn sortSections(self: *MachO) !void {...@@ -5212,6 +5289,7 @@ fn sortSections(self: *MachO) !void {
52125289
5213 // __DATA segment5290 // __DATA segment
5214 const indices = &[_]*?u16{5291 const indices = &[_]*?u16{
5292 &self.rustc_section_index,
5215 &self.la_symbol_ptr_section_index,5293 &self.la_symbol_ptr_section_index,
5216 &self.objc_const_section_index,5294 &self.objc_const_section_index,
5217 &self.objc_selrefs_section_index,5295 &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
...@@ -1128,7 +1128,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1128,7 +1128,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
11281128
1129 comptime assert(Compilation.link_hash_implementation_version == 1);1129 comptime assert(Compilation.link_hash_implementation_version == 1);
11301130
1131 try man.addListOfFiles(self.base.options.objects);1131 for (self.base.options.objects) |obj| {
1132 _ = try man.addFile(obj.path, null);
1133 man.hash.add(obj.must_link);
1134 }
1132 for (comp.c_object_table.keys()) |key| {1135 for (comp.c_object_table.keys()) |key| {
1133 _ = try man.addFile(key.status.success.object_path, null);1136 _ = try man.addFile(key.status.success.object_path, null);
1134 }1137 }
...@@ -1181,7 +1184,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1181,7 +1184,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1181 // build-obj. See also the corresponding TODO in linkAsArchive.1184 // build-obj. See also the corresponding TODO in linkAsArchive.
1182 const the_object_path = blk: {1185 const the_object_path = blk: {
1183 if (self.base.options.objects.len != 0)1186 if (self.base.options.objects.len != 0)
1184 break :blk self.base.options.objects[0];1187 break :blk self.base.options.objects[0].path;
11851188
1186 if (comp.c_object_table.count() != 0)1189 if (comp.c_object_table.count() != 0)
1187 break :blk comp.c_object_table.keys()[0].status.success.object_path;1190 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -1346,7 +1349,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1346,7 +1349,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1346 }1349 }
13471350
1348 // Positional arguments to the linker such as object files.1351 // Positional arguments to the linker such as object files.
1349 try argv.appendSlice(self.base.options.objects);1352 try argv.ensureUnusedCapacity(self.base.options.objects.len);
1353 for (self.base.options.objects) |obj| {
1354 argv.appendAssumeCapacity(obj.path);
1355 }
13501356
1351 for (comp.c_object_table.keys()) |key| {1357 for (comp.c_object_table.keys()) |key| {
1352 try argv.append(key.status.success.object_path);1358 try argv.append(key.status.success.object_path);
src/main.zig+14-5
...@@ -705,7 +705,7 @@ fn buildOutputType(...@@ -705,7 +705,7 @@ fn buildOutputType(
705 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa);705 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa);
706 defer c_source_files.deinit();706 defer c_source_files.deinit();
707707
708 var link_objects = std.ArrayList([]const u8).init(gpa);708 var link_objects = std.ArrayList(Compilation.LinkObject).init(gpa);
709 defer link_objects.deinit();709 defer link_objects.deinit();
710710
711 var framework_dirs = std.ArrayList([]const u8).init(gpa);711 var framework_dirs = std.ArrayList([]const u8).init(gpa);
...@@ -1238,7 +1238,7 @@ fn buildOutputType(...@@ -1238,7 +1238,7 @@ fn buildOutputType(
1238 }1238 }
1239 } else switch (Compilation.classifyFileExt(arg)) {1239 } else switch (Compilation.classifyFileExt(arg)) {
1240 .object, .static_library, .shared_library => {1240 .object, .static_library, .shared_library => {
1241 try link_objects.append(arg);1241 try link_objects.append(.{ .path = arg });
1242 },1242 },
1243 .assembly, .c, .cpp, .h, .ll, .bc, .m, .mm => {1243 .assembly, .c, .cpp, .h, .ll, .bc, .m, .mm => {
1244 try c_source_files.append(.{1244 try c_source_files.append(.{
...@@ -1309,7 +1309,7 @@ fn buildOutputType(...@@ -1309,7 +1309,7 @@ fn buildOutputType(
1309 switch (file_ext) {1309 switch (file_ext) {
1310 .assembly, .c, .cpp, .ll, .bc, .h, .m, .mm => try c_source_files.append(.{ .src_path = it.only_arg }),1310 .assembly, .c, .cpp, .ll, .bc, .h, .m, .mm => try c_source_files.append(.{ .src_path = it.only_arg }),
1311 .unknown, .shared_library, .object, .static_library => {1311 .unknown, .shared_library, .object, .static_library => {
1312 try link_objects.append(it.only_arg);1312 try link_objects.append(.{ .path = it.only_arg });
1313 },1313 },
1314 .zig => {1314 .zig => {
1315 if (root_src_file) |other| {1315 if (root_src_file) |other| {
...@@ -1748,6 +1748,15 @@ fn buildOutputType(...@@ -1748,6 +1748,15 @@ fn buildOutputType(
1748 fatal("expected linker arg after '{s}'", .{arg});1748 fatal("expected linker arg after '{s}'", .{arg});
1749 }1749 }
1750 install_name = linker_args.items[i];1750 install_name = linker_args.items[i];
1751 } else if (mem.eql(u8, arg, "-force_load")) {
1752 i += 1;
1753 if (i >= linker_args.items.len) {
1754 fatal("expected linker arg after '{s}'", .{arg});
1755 }
1756 try link_objects.append(.{
1757 .path = linker_args.items[i],
1758 .must_link = true,
1759 });
1751 } else {1760 } else {
1752 warn("unsupported linker arg: {s}", .{arg});1761 warn("unsupported linker arg: {s}", .{arg});
1753 }1762 }
...@@ -1842,7 +1851,7 @@ fn buildOutputType(...@@ -1842,7 +1851,7 @@ fn buildOutputType(
1842 const basename = fs.path.basename(c_source_files.items[0].src_path);1851 const basename = fs.path.basename(c_source_files.items[0].src_path);
1843 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];1852 break :blk basename[0 .. basename.len - fs.path.extension(basename).len];
1844 } else if (link_objects.items.len >= 1) {1853 } else if (link_objects.items.len >= 1) {
1845 const basename = fs.path.basename(link_objects.items[0]);1854 const basename = fs.path.basename(link_objects.items[0].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 (emit_bin == .yes) {1856 } else if (emit_bin == .yes) {
1848 const basename = fs.path.basename(emit_bin.yes);1857 const basename = fs.path.basename(emit_bin.yes);
...@@ -2045,7 +2054,7 @@ fn buildOutputType(...@@ -2045,7 +2054,7 @@ fn buildOutputType(
2045 test_path.items, @errorName(e),2054 test_path.items, @errorName(e),
2046 }),2055 }),
2047 };2056 };
2048 try link_objects.append(try arena.dupe(u8, test_path.items));2057 try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) });
2049 break;2058 break;
2050 } else {2059 } else {
2051 var search_paths = std.ArrayList(u8).init(arena);2060 var search_paths = std.ArrayList(u8).init(arena);