diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-04 19:31:26 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-05 05:57:09 +0200 |
| commit | a503724801e7b221aababd88aefe790a33c4135e (patch) | |
| tree | 175181974bd7d28ec51f78013a3cf7f810a89791 /src | |
| parent | f372995e1ef2a6dda4bc30eeaf817b0d947704e7 (diff) | |
| download | zig-a503724801e7b221aababd88aefe790a33c4135e.tar.gz zig-a503724801e7b221aababd88aefe790a33c4135e.zip | |
macho: reapply relocation dirtying logic from coff linker
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 17 | ||||
| -rw-r--r-- | src/link/MachO/Atom.zig | 11 | ||||
| -rw-r--r-- | src/link/MachO/Relocation.zig | 8 |
3 files changed, 29 insertions, 7 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 7192ce58e1..e8fab08912 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1128,8 +1128,15 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { const file_offset = section.header.offset + sym.n_value - section.header.addr; log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset }); - if (self.relocs.get(atom_index)) |relocs| { - Atom.resolveRelocations(self, atom_index, relocs.items, code); + // Gather relocs which can be resolved. + var relocs = std.ArrayList(*Relocation).init(self.base.allocator); + defer relocs.deinit(); + + if (self.relocs.getPtr(atom_index)) |rels| { + try relocs.ensureTotalCapacityPrecise(rels.items.len); + for (rels.items) |*reloc| { + if (reloc.isResolvable(self)) relocs.appendAssumeCapacity(reloc); + } } if (is_hot_update_compatible) { @@ -1144,7 +1151,13 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { } } + Atom.resolveRelocations(self, atom_index, relocs.items, code); try self.base.file.?.pwriteAll(code, file_offset); + + // Now we can mark the relocs as resolved. + while (relocs.popOrNull()) |reloc| { + reloc.dirty = false; + } } fn updateAtomInMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void { diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index c601cfa440..bd1a21a04f 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -179,12 +179,15 @@ pub fn addLazyBinding(macho_file: *MachO, atom_index: Index, binding: Binding) ! try gop.value_ptr.append(gpa, binding); } -pub fn resolveRelocations(macho_file: *MachO, atom_index: Index, relocs: []Relocation, code: []u8) void { +pub fn resolveRelocations( + macho_file: *MachO, + atom_index: Index, + relocs: []*const Relocation, + code: []u8, +) void { log.debug("relocating '{s}'", .{macho_file.getAtom(atom_index).getName(macho_file)}); - for (relocs) |*reloc| { - if (!reloc.dirty) continue; + for (relocs) |reloc| { reloc.resolve(macho_file, atom_index, code); - reloc.dirty = false; } } diff --git a/src/link/MachO/Relocation.zig b/src/link/MachO/Relocation.zig index cc565742d1..32f24f243d 100644 --- a/src/link/MachO/Relocation.zig +++ b/src/link/MachO/Relocation.zig @@ -21,6 +21,12 @@ pcrel: bool, length: u2, dirty: bool = true, +/// Returns true if and only if the reloc is dirty AND the target address is available. +pub fn isResolvable(self: Relocation, macho_file: *MachO) bool { + _ = self.getTargetAtomIndex(macho_file) orelse return false; + return self.dirty; +} + pub fn fmtType(self: Relocation, target: std.Target) []const u8 { switch (target.cpu.arch) { .aarch64 => return @tagName(@intToEnum(macho.reloc_type_arm64, self.type)), @@ -56,7 +62,7 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod const source_sym = atom.getSymbol(macho_file); const source_addr = source_sym.n_value + self.offset; - const target_atom_index = self.getTargetAtomIndex(macho_file) orelse return; + const target_atom_index = self.getTargetAtomIndex(macho_file).?; // Oops, you didn't check if the relocation can be resolved with isResolvable(). const target_atom = macho_file.getAtom(target_atom_index); const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend; |
