mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
macho: re-read atom code from ZigObject when resolving relocs
This commit is contained in:
parent
7647db3273
commit
a112241f64
@ -596,6 +596,47 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
|
||||
state_log.debug("{}", .{self.dumpState()});
|
||||
|
||||
try self.initDyldInfoSections();
|
||||
|
||||
// Beyond this point, everything has been allocated a virtual address and we can resolve
|
||||
// the relocations, and commit objects to file.
|
||||
if (self.getZigObject()) |zo| {
|
||||
var has_resolve_error = false;
|
||||
|
||||
for (zo.atoms.items) |atom_index| {
|
||||
const atom = self.getAtom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const sect = &self.sections.items(.header)[atom.out_n_sect];
|
||||
if (sect.isZerofill()) continue;
|
||||
const code = zo.getAtomDataAlloc(self, atom.*) 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;
|
||||
},
|
||||
};
|
||||
defer gpa.free(code);
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
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;
|
||||
}
|
||||
|
||||
self.writeAtoms() catch |err| switch (err) {
|
||||
error.ResolveFailed => return error.FlushFailure,
|
||||
else => |e| {
|
||||
@ -1955,6 +1996,28 @@ pub fn sortSections(self: *MachO) !void {
|
||||
self.sections.appendAssumeCapacity(slice.get(sorted.index));
|
||||
}
|
||||
|
||||
if (self.getZigObject()) |zo| {
|
||||
for (zo.atoms.items) |atom_index| {
|
||||
const atom = self.getAtom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
atom.out_n_sect = backlinks[atom.out_n_sect];
|
||||
}
|
||||
|
||||
for (zo.symtab.items(.nlist)) |*sym| {
|
||||
if (sym.sect()) {
|
||||
sym.n_sect = backlinks[sym.n_sect];
|
||||
}
|
||||
}
|
||||
|
||||
for (zo.symbols.items) |sym_index| {
|
||||
const sym = self.getSymbol(sym_index);
|
||||
const atom = sym.getAtom(self) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
if (sym.getFile(self).?.getIndex() != zo.index) continue;
|
||||
sym.out_n_sect = backlinks[sym.out_n_sect];
|
||||
}
|
||||
}
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
for (self.getFile(index).?.object.atoms.items) |atom_index| {
|
||||
const atom = self.getAtom(atom_index) orelse continue;
|
||||
@ -1962,6 +2025,7 @@ pub fn sortSections(self: *MachO) !void {
|
||||
atom.out_n_sect = backlinks[atom.out_n_sect];
|
||||
}
|
||||
}
|
||||
|
||||
if (self.getInternalObject()) |object| {
|
||||
for (object.atoms.items) |atom_index| {
|
||||
const atom = self.getAtom(atom_index) orelse continue;
|
||||
@ -2517,6 +2581,7 @@ fn writeAtoms(self: *MachO) !void {
|
||||
const atom = self.getAtom(atom_index).?;
|
||||
assert(atom.flags.alive);
|
||||
const off = atom.value - header.addr;
|
||||
@memcpy(buffer[off..][0..atom.size], atom.getFile(self).object.getAtomData(atom.*));
|
||||
atom.resolveRelocs(self, buffer[off..][0..atom.size]) catch |err| switch (err) {
|
||||
error.ResolveFailed => has_resolve_error = true,
|
||||
else => |e| return e,
|
||||
@ -2757,7 +2822,8 @@ pub fn calcSymtabSize(self: *MachO) !void {
|
||||
|
||||
var files = std.ArrayList(File.Index).init(gpa);
|
||||
defer files.deinit();
|
||||
try files.ensureTotalCapacityPrecise(self.objects.items.len + self.dylibs.items.len + 1);
|
||||
try files.ensureTotalCapacityPrecise(self.objects.items.len + self.dylibs.items.len + 2);
|
||||
if (self.zig_object) |index| files.appendAssumeCapacity(index);
|
||||
for (self.objects.items) |index| files.appendAssumeCapacity(index);
|
||||
for (self.dylibs.items) |index| files.appendAssumeCapacity(index);
|
||||
if (self.internal_object) |index| files.appendAssumeCapacity(index);
|
||||
@ -2816,6 +2882,9 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 {
|
||||
try self.symtab.resize(gpa, cmd.nsyms);
|
||||
try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1);
|
||||
|
||||
if (self.getZigObject()) |zo| {
|
||||
zo.writeSymtab(self);
|
||||
}
|
||||
for (self.objects.items) |index| {
|
||||
self.getFile(index).?.writeSymtab(self);
|
||||
}
|
||||
@ -3752,7 +3821,7 @@ fn reportDependencyError(
|
||||
try err.addNote(self, "a dependency of {}", .{self.getFile(parent).?.fmtPath()});
|
||||
}
|
||||
|
||||
fn reportUnexpectedError(self: *MachO, comptime format: []const u8, args: anytype) error{OutOfMemory}!void {
|
||||
pub fn reportUnexpectedError(self: *MachO, comptime format: []const u8, args: anytype) error{OutOfMemory}!void {
|
||||
var err = try self.addErrorWithNotes(1);
|
||||
try err.addMsg(self, format, args);
|
||||
try err.addNote(self, "please report this as a linker bug on https://github.com/ziglang/zig/issues/new/choose", .{});
|
||||
|
||||
@ -50,14 +50,6 @@ pub fn getFile(self: Atom, macho_file: *MachO) File {
|
||||
return macho_file.getFile(self.file).?;
|
||||
}
|
||||
|
||||
pub fn getData(self: Atom, macho_file: *MachO) []const u8 {
|
||||
return switch (self.getFile(macho_file)) {
|
||||
.zig_object => @panic("TODO Atom.getData"),
|
||||
.object => |x| x.getAtomData(self),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getRelocs(self: Atom, macho_file: *MachO) []const Relocation {
|
||||
return switch (self.getFile(macho_file)) {
|
||||
.zig_object => |x| x.getAtomRelocs(self),
|
||||
@ -538,7 +530,6 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
|
||||
const file = self.getFile(macho_file);
|
||||
const name = self.getName(macho_file);
|
||||
const relocs = self.getRelocs(macho_file);
|
||||
@memcpy(buffer, self.getData(macho_file));
|
||||
|
||||
relocs_log.debug("{x}: {s}", .{ self.value, name });
|
||||
|
||||
@ -1153,7 +1144,7 @@ const macho = std.macho;
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const log = std.log.scoped(.link);
|
||||
const relocs_log = std.log.scoped(.relocs);
|
||||
const relocs_log = std.log.scoped(.link_relocs);
|
||||
const std = @import("std");
|
||||
const trace = @import("../../tracy.zig").trace;
|
||||
|
||||
|
||||
@ -128,6 +128,20 @@ pub fn addAtom(self: *ZigObject, macho_file: *MachO) !Symbol.Index {
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
/// Caller owns the memory.
|
||||
pub fn getAtomDataAlloc(self: ZigObject, macho_file: *MachO, atom: Atom) ![]u8 {
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
assert(atom.file == self.index);
|
||||
const sect = macho_file.sections.items(.header)[atom.out_n_sect];
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
const size = std.math.cast(usize, atom.size) orelse return error.Overflow;
|
||||
const code = try gpa.alloc(u8, size);
|
||||
errdefer gpa.free(code);
|
||||
const amt = try macho_file.base.file.?.preadAll(code, file_offset);
|
||||
if (amt != code.len) return error.InputOutput;
|
||||
return code;
|
||||
}
|
||||
|
||||
pub fn getAtomRelocs(self: *ZigObject, atom: Atom) []const Relocation {
|
||||
const relocs = self.relocs.items[atom.relocs.pos];
|
||||
return relocs.items[0..atom.relocs.len];
|
||||
@ -659,7 +673,7 @@ fn updateDeclCode(
|
||||
|
||||
if (old_size > 0) {
|
||||
const capacity = atom.capacity(macho_file);
|
||||
const need_realloc = code.len > capacity or !required_alignment.check(sym.getAddress(.{}, macho_file));
|
||||
const need_realloc = code.len > capacity or !required_alignment.check(atom.value);
|
||||
|
||||
if (need_realloc) {
|
||||
try atom.grow(macho_file);
|
||||
@ -678,7 +692,7 @@ fn updateDeclCode(
|
||||
} else if (code.len < old_size) {
|
||||
atom.shrink(macho_file);
|
||||
} else if (macho_file.getAtom(atom.next_index) == null) {
|
||||
const needed_size = (sym.getAddress(.{}, macho_file) + code.len) - sect.addr;
|
||||
const needed_size = atom.value + code.len - sect.addr;
|
||||
sect.size = needed_size;
|
||||
}
|
||||
} else {
|
||||
@ -696,7 +710,7 @@ fn updateDeclCode(
|
||||
}
|
||||
|
||||
if (!sect.isZerofill()) {
|
||||
const file_offset = sect.offset + sym.getAddress(.{}, macho_file) - sect.addr;
|
||||
const file_offset = sect.offset + atom.value - sect.addr;
|
||||
try macho_file.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ fn writeAtoms(macho_file: *MachO) !void {
|
||||
const atom = macho_file.getAtom(atom_index).?;
|
||||
assert(atom.flags.alive);
|
||||
const off = atom.value - header.addr;
|
||||
@memcpy(code[off..][0..atom.size], atom.getData(macho_file));
|
||||
@memcpy(code[off..][0..atom.size], atom.getFile(macho_file).object.getAtomData(atom.*));
|
||||
try atom.writeRelocs(macho_file, code[off..][0..atom.size], &relocs);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user