Commit 387a71fa5b

Jakub Konka <kubkon@jakubkonka.com>
2024-07-13 10:22:02
macho: re-enable writing out static archive with ZigObject
1 parent 84189f9
Changed files (3)
src/link/MachO/file.zig
@@ -293,8 +293,6 @@ pub const File = union(enum) {
     pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, macho_file: *MachO) error{OutOfMemory}!void {
         return switch (file) {
             .dylib, .internal => unreachable,
-            // TODO
-            .zig_object => unreachable,
             inline else => |x| x.updateArSymtab(ar_symtab, macho_file),
         };
     }
@@ -302,9 +300,7 @@ pub const File = union(enum) {
     pub fn updateArSize(file: File, macho_file: *MachO) !void {
         return switch (file) {
             .dylib, .internal => unreachable,
-            // TODO
-            .zig_object => unreachable,
-            // .zig_object => |x| x.updateArSize(),
+            .zig_object => |x| x.updateArSize(),
             .object => |x| x.updateArSize(macho_file),
         };
     }
@@ -312,9 +308,7 @@ pub const File = union(enum) {
     pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void {
         return switch (file) {
             .dylib, .internal => unreachable,
-            // TODO
-            .zig_object => unreachable,
-            // .zig_object => |x| x.writeAr(ar_format, writer),
+            .zig_object => |x| x.writeAr(ar_format, writer),
             .object => |x| x.writeAr(ar_format, macho_file, writer),
         };
     }
src/link/MachO/relocatable.zig
@@ -110,56 +110,42 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
 
     if (comp.link_errors.items.len > 0) return error.FlushFailure;
 
-    // TODO re-enable
-    // // First, we flush relocatable object file generated with our backends.
-    // if (macho_file.getZigObject()) |zo| {
-    //     zo.resolveSymbols(macho_file);
-    //     zo.asFile().markExportsRelocatable(macho_file);
-    //     zo.asFile().claimUnresolvedRelocatable(macho_file);
-    //     try macho_file.sortSections();
-    //     try macho_file.addAtomsToSections();
-    //     try calcSectionSizes(macho_file);
-    //     try createSegment(macho_file);
-    //     try allocateSections(macho_file);
-    //     allocateSegment(macho_file);
-
-    //     var off = off: {
-    //         const seg = macho_file.segments.items[0];
-    //         const off = math.cast(u32, seg.fileoff + seg.filesize) orelse return error.Overflow;
-    //         break :off mem.alignForward(u32, off, @alignOf(macho.relocation_info));
-    //     };
-    //     off = allocateSectionsRelocs(macho_file, off);
-
-    //     if (build_options.enable_logging) {
-    //         state_log.debug("{}", .{macho_file.dumpState()});
-    //     }
-
-    //     try macho_file.calcSymtabSize();
-    //     try writeAtoms(macho_file);
-
-    //     off = mem.alignForward(u32, off, @alignOf(u64));
-    //     off = try macho_file.writeDataInCode(0, off);
-    //     off = mem.alignForward(u32, off, @alignOf(u64));
-    //     off = try macho_file.writeSymtab(off);
-    //     off = mem.alignForward(u32, off, @alignOf(u64));
-    //     off = try macho_file.writeStrtab(off);
-
-    //     // In order to please Apple ld (and possibly other MachO linkers in the wild),
-    //     // we will now sanitize segment names of Zig-specific segments.
-    //     sanitizeZigSections(macho_file);
-
-    //     const ncmds, const sizeofcmds = try writeLoadCommands(macho_file);
-    //     try writeHeader(macho_file, ncmds, sizeofcmds);
-
-    //     // TODO we can avoid reading in the file contents we just wrote if we give the linker
-    //     // ability to write directly to a buffer.
-    //     try zo.readFileContents(off, macho_file);
-    // }
+    // First, we flush relocatable object file generated with our backends.
+    if (macho_file.getZigObject()) |zo| {
+        try zo.resolveSymbols(macho_file);
+        zo.asFile().markExportsRelocatable(macho_file);
+        zo.asFile().claimUnresolvedRelocatable(macho_file);
+        try macho_file.sortSections();
+        try macho_file.addAtomsToSections();
+        try calcSectionSizes(macho_file);
+        try createSegment(macho_file);
+        try allocateSections(macho_file);
+        allocateSegment(macho_file);
+
+        if (build_options.enable_logging) {
+            state_log.debug("{}", .{macho_file.dumpState()});
+        }
+
+        try writeSections(macho_file);
+        sortRelocs(macho_file);
+        try writeSectionsToFile(macho_file);
+
+        // In order to please Apple ld (and possibly other MachO linkers in the wild),
+        // we will now sanitize segment names of Zig-specific segments.
+        sanitizeZigSections(macho_file);
+
+        const ncmds, const sizeofcmds = try writeLoadCommands(macho_file);
+        try writeHeader(macho_file, ncmds, sizeofcmds);
+
+        // TODO we can avoid reading in the file contents we just wrote if we give the linker
+        // ability to write directly to a buffer.
+        try zo.readFileContents(macho_file);
+    }
 
     var files = std.ArrayList(File.Index).init(gpa);
     defer files.deinit();
     try files.ensureTotalCapacityPrecise(macho_file.objects.items.len + 1);
-    // if (macho_file.getZigObject()) |zo| files.appendAssumeCapacity(zo.index);
+    if (macho_file.getZigObject()) |zo| files.appendAssumeCapacity(zo.index);
     for (macho_file.objects.items) |index| files.appendAssumeCapacity(index);
 
     const format: Archive.Format = .p32;
src/link/MachO/ZigObject.zig
@@ -313,7 +313,9 @@ pub fn dedupLiterals(self: *ZigObject, lp: MachO.LiteralPool, macho_file: *MachO
 /// This is just a temporary helper function that allows us to re-read what we wrote to file into a buffer.
 /// We need this so that we can write to an archive.
 /// TODO implement writing ZigObject data directly to a buffer instead.
-pub fn readFileContents(self: *ZigObject, size: usize, macho_file: *MachO) !void {
+pub fn readFileContents(self: *ZigObject, macho_file: *MachO) !void {
+    // Size of the output object file is always the offset + size of the strtab
+    const size = macho_file.symtab_cmd.stroff + macho_file.symtab_cmd.strsize;
     const gpa = macho_file.base.comp.gpa;
     try self.data.resize(gpa, size);
     const amt = try macho_file.base.file.?.preadAll(self.data.items, 0);
@@ -322,9 +324,9 @@ pub fn readFileContents(self: *ZigObject, size: usize, macho_file: *MachO) !void
 
 pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, macho_file: *MachO) error{OutOfMemory}!void {
     const gpa = macho_file.base.comp.gpa;
-    for (self.symbols.items) |sym_index| {
-        const sym = macho_file.getSymbol(sym_index);
-        const file = sym.getFile(macho_file).?;
+    for (self.symbols.items, 0..) |sym, i| {
+        const ref = self.getSymbolRef(@intCast(i), macho_file);
+        const file = ref.getFile(macho_file).?;
         assert(file.getIndex() == self.index);
         if (!sym.flags.@"export") continue;
         const off = try ar_symtab.strtab.insert(gpa, sym.getName(macho_file));