From 01fc33c949cb8609324cfbcdf7f0524b93ff2561 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sat, 13 Jul 2024 07:29:42 +0200 Subject: [PATCH] macho: emit relocs for non-zig-sections in ZigObject --- src/link/MachO/Atom.zig | 1 + src/link/MachO/ZigObject.zig | 31 +++++++++++++++++++++++++++++++ src/link/MachO/relocatable.zig | 1 + 3 files changed, 33 insertions(+) diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index b928542600..df2327f6bc 100644 --- a/src/link/MachO/Atom.zig +++ b/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, diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index b48a7d7dde..a84a95da7e 100644 --- a/src/link/MachO/ZigObject.zig +++ b/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(); diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index 2d4a3411db..1039b6557c 100644 --- a/src/link/MachO/relocatable.zig +++ b/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); }