Commit 01fc33c949

Jakub Konka <kubkon@jakubkonka.com>
2024-07-13 07:29:42
macho: emit relocs for non-zig-sections in ZigObject
1 parent 853ca40
Changed files (3)
src/link/MachO/Atom.zig
@@ -979,6 +979,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
         defer i += 1;
         const rel_offset = rel.offset - self.off;
         const r_address: i32 = math.cast(i32, self.value + rel_offset) orelse return error.Overflow;
+        assert(r_address >= 0);
         const r_symbolnum = r_symbolnum: {
             const r_symbolnum: u32 = switch (rel.tag) {
                 .local => rel.getTargetAtom(self, macho_file).out_n_sect + 1,
src/link/MachO/relocatable.zig
@@ -657,6 +657,7 @@ fn writeSections(macho_file: *MachO) !void {
 
     if (macho_file.getZigObject()) |zo| {
         try zo.writeRelocs(macho_file);
+        try zo.writeAtomsRelocatable(macho_file);
         zo.writeSymtab(macho_file, macho_file);
     }
 
src/link/MachO/ZigObject.zig
@@ -482,6 +482,37 @@ pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) !void {
     }
 }
 
+// TODO we need this because not everything gets written out incrementally.
+// For example, TLS data gets written out via traditional route.
+// Is there any better way of handling this?
+pub fn writeAtomsRelocatable(self: *ZigObject, macho_file: *MachO) !void {
+    const tracy = trace(@src());
+    defer tracy.end();
+
+    for (self.getAtoms()) |atom_index| {
+        const atom = self.getAtom(atom_index) orelse continue;
+        if (!atom.flags.alive) continue;
+        const sect = atom.getInputSection(macho_file);
+        if (sect.isZerofill()) continue;
+        if (macho_file.isZigSection(atom.out_n_sect)) continue;
+        const off = atom.value;
+        const buffer = macho_file.sections.items(.out)[atom.out_n_sect].items;
+        try self.getAtomData(macho_file, atom.*, buffer[off..][0..atom.size]);
+        const relocs = macho_file.sections.items(.relocs)[atom.out_n_sect].items;
+        const extra = atom.getExtra(macho_file);
+        try atom.writeRelocs(macho_file, buffer[off..][0..atom.size], relocs[extra.rel_out_index..][0..extra.rel_out_count]);
+    }
+}
+
+// TODO we need this because not everything gets written out incrementally.
+// For example, TLS data gets written out via traditional route.
+// Is there any better way of handling this?
+pub fn writeAtoms(self: *ZigObject, macho_file: *MachO) !void {
+    const gpa = macho_file.base.comp.gpa;
+    _ = gpa;
+    _ = self;
+}
+
 pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
     const tracy = trace(@src());
     defer tracy.end();