From 4aff0ec394cb6ef42db982df86caf8976b558d43 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 12 Jul 2024 06:50:57 +0200 Subject: [PATCH] macho: move relocs re-resolution logic to ZigObject --- src/link/MachO.zig | 45 +++------------------------------ src/link/MachO/ZigObject.zig | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 2b4005c1fe..e99fd6bf58 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -567,47 +567,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n try self.resizeSections(); if (self.getZigObject()) |zo| { - var has_resolve_error = false; - - for (zo.getAtoms()) |atom_index| { - const atom = zo.getAtom(atom_index) orelse continue; - if (!atom.flags.alive) continue; - const sect = &self.sections.items(.header)[atom.out_n_sect]; - if (sect.isZerofill()) continue; - if (!self.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately - if (atom.getRelocs(self).len == 0) continue; - // TODO: we will resolve and write ZigObject's TLS data twice: - // once here, and once in writeAtoms - const atom_size = math.cast(usize, atom.size) orelse return error.Overflow; - const code = try gpa.alloc(u8, atom_size); - defer gpa.free(code); - zo.getAtomData(self, atom.*, code) catch |err| switch (err) { - error.InputOutput => { - try self.reportUnexpectedError("fetching code for '{s}' failed", .{ - atom.getName(self), - }); - return error.FlushFailure; - }, - else => |e| { - try self.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{ - atom.getName(self), - @errorName(e), - }); - return error.FlushFailure; - }, - }; - const file_offset = sect.offset + atom.value; - atom.resolveRelocs(self, code) catch |err| switch (err) { - error.ResolveFailed => has_resolve_error = true, - else => |e| { - try self.reportUnexpectedError("unexpected error while resolving relocations", .{}); - return e; - }, - }; - try self.base.file.?.pwriteAll(code, file_offset); - } - - if (has_resolve_error) return error.FlushFailure; + zo.resolveRelocs(self) catch |err| switch (err) { + error.ResolveFailed => return error.FlushFailure, + else => |e| return e, + }; } self.writeSectionsAndUpdateLinkeditSizes() catch |err| { switch (err) { diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 661a88904e..79e563ac1a 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -383,6 +383,55 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void { } } +pub fn resolveRelocs(self: *ZigObject, macho_file: *MachO) !void { + const gpa = macho_file.base.comp.gpa; + var has_error = false; + for (self.getAtoms()) |atom_index| { + const atom = self.getAtom(atom_index) orelse continue; + if (!atom.flags.alive) continue; + const sect = &macho_file.sections.items(.header)[atom.out_n_sect]; + if (sect.isZerofill()) continue; + if (!macho_file.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately + if (atom.getRelocs(macho_file).len == 0) continue; + // TODO: we will resolve and write ZigObject's TLS data twice: + // once here, and once in writeAtoms + 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), + }); + }, + else => |e| { + try macho_file.reportUnexpectedError("unexpected error while fetching code for '{s}': {s}", .{ + atom.getName(macho_file), + @errorName(e), + }); + }, + } + has_error = true; + continue; + }; + const file_offset = sect.offset + atom.value; + atom.resolveRelocs(macho_file, code) catch |err| { + switch (err) { + error.ResolveFailed => {}, + else => |e| { + try macho_file.reportUnexpectedError("unexpected error while resolving relocations: {s}", .{@errorName(e)}); + }, + } + has_error = true; + continue; + }; + try macho_file.base.file.?.pwriteAll(code, file_offset); + } + + if (has_error) return error.ResolveFailed; +} + pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void { const tracy = trace(@src()); defer tracy.end();