macho: move relocs re-resolution logic to ZigObject

This commit is contained in:
Jakub Konka 2024-07-12 06:50:57 +02:00
parent b62281a9c8
commit 4aff0ec394
2 changed files with 53 additions and 41 deletions

View File

@ -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) {

View File

@ -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();