From 853ca403c4164a67f32773a069b8f5f5579c4542 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 12 Jul 2024 15:56:26 +0200 Subject: [PATCH] macho: bring back relocatable mode for ZigObject --- src/link/MachO/ZigObject.zig | 43 ++++++++++++++++++++++++++++++++-- src/link/MachO/relocatable.zig | 31 +++++++++++++++++------- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index bddd5379f4..b48a7d7dde 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -437,9 +437,48 @@ pub fn calcNumRelocs(self: *ZigObject, macho_file: *MachO) void { for (self.getAtoms()) |atom_index| { const atom = self.getAtom(atom_index) orelse continue; if (!atom.flags.alive) continue; - if (!macho_file.isZigSection(atom.out_n_sect) and !macho_file.isDebugSection(atom.out_n_sect)) continue; const header = &macho_file.sections.items(.header)[atom.out_n_sect]; - header.nreloc += atom.calcNumRelocs(macho_file); + if (header.isZerofill()) continue; + if (!macho_file.isZigSection(atom.out_n_sect) and !macho_file.isDebugSection(atom.out_n_sect)) continue; + const nreloc = atom.calcNumRelocs(macho_file); + atom.addExtra(.{ .rel_out_index = header.nreloc, .rel_out_count = nreloc }, macho_file); + header.nreloc += nreloc; + } +} + +pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) !void { + const gpa = macho_file.base.comp.gpa; + + for (self.getAtoms()) |atom_index| { + const atom = self.getAtom(atom_index) orelse continue; + if (!atom.flags.alive) continue; + const header = macho_file.sections.items(.header)[atom.out_n_sect]; + const relocs = macho_file.sections.items(.relocs)[atom.out_n_sect].items; + if (header.isZerofill()) continue; + if (!macho_file.isZigSection(atom.out_n_sect) and !macho_file.isDebugSection(atom.out_n_sect)) continue; + if (atom.getRelocs(macho_file).len == 0) continue; + const extra = atom.getExtra(macho_file); + const atom_size = std.math.cast(usize, atom.size) orelse return error.Overflow; + const code = try gpa.alloc(u8, atom_size); + defer gpa.free(code); + self.getAtomData(macho_file, atom.*, code) catch |err| switch (err) { + error.InputOutput => { + try macho_file.reportUnexpectedError("fetching code for '{s}' failed", .{ + atom.getName(macho_file), + }); + return error.FlushFailure; + }, + else => |e| { + try macho_file.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{ + atom.getName(macho_file), + @errorName(e), + }); + return error.FlushFailure; + }, + }; + const file_offset = header.offset + atom.value; + try atom.writeRelocs(macho_file, code, relocs[extra.rel_out_index..][0..extra.rel_out_count]); + try macho_file.base.file.?.pwriteAll(code, file_offset); } } diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index c3d15c2241..2d4a3411db 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -372,6 +372,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { if (macho_file.getZigObject()) |zo| { // TODO this will create a race zo.calcNumRelocs(macho_file); + zo.calcSymtabSize(macho_file); } if (macho_file.eh_frame_sect_index) |_| { @@ -390,7 +391,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { if (macho_file.unwind_info_sect_index) |_| { calcCompactUnwindSize(macho_file); } - calcSymtabSize(macho_file); + try calcSymtabSize(macho_file); } fn calcSectionSize(macho_file: *MachO, sect_id: u8) void { @@ -445,19 +446,27 @@ fn calcCompactUnwindSize(macho_file: *MachO) void { sect.@"align" = 3; } -fn calcSymtabSize(macho_file: *MachO) void { +fn calcSymtabSize(macho_file: *MachO) error{OutOfMemory}!void { const tracy = trace(@src()); defer tracy.end(); + const gpa = macho_file.base.comp.gpa; + var nlocals: u32 = 0; var nstabs: u32 = 0; var nexports: u32 = 0; var nimports: u32 = 0; var strsize: u32 = 1; - for (macho_file.objects.items) |index| { - const object = macho_file.getFile(index).?.object; - const ctx = &object.output_symtab_ctx; + var objects = try std.ArrayList(File.Index).initCapacity(gpa, macho_file.objects.items.len + 1); + defer objects.deinit(); + if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); + objects.appendSliceAssumeCapacity(macho_file.objects.items); + + for (objects.items) |index| { + const ctx = switch (macho_file.getFile(index).?) { + inline else => |x| &x.output_symtab_ctx, + }; ctx.ilocal = nlocals; ctx.istab = nstabs; ctx.iexport = nexports; @@ -470,9 +479,10 @@ fn calcSymtabSize(macho_file: *MachO) void { strsize += ctx.strsize; } - for (macho_file.objects.items) |index| { - const object = macho_file.getFile(index).?.object; - const ctx = &object.output_symtab_ctx; + for (objects.items) |index| { + const ctx = switch (macho_file.getFile(index).?) { + inline else => |x| &x.output_symtab_ctx, + }; ctx.istab += nlocals; ctx.iexport += nlocals + nstabs; ctx.iimport += nlocals + nstabs + nexports; @@ -645,6 +655,11 @@ fn writeSections(macho_file: *MachO) !void { macho_file.getFile(index).?.writeSymtab(macho_file, macho_file); } + if (macho_file.getZigObject()) |zo| { + try zo.writeRelocs(macho_file); + zo.writeSymtab(macho_file, macho_file); + } + if (macho_file.eh_frame_sect_index) |_| { try writeEhFrame(macho_file); }