authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-04 19:31:26+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-05 05:57:09+02:00
loga503724801e7b221aababd88aefe790a33c4135e
tree175181974bd7d28ec51f78013a3cf7f810a89791
parentf372995e1ef2a6dda4bc30eeaf817b0d947704e7

macho: reapply relocation dirtying logic from coff linker


3 files changed, 29 insertions(+), 7 deletions(-)

src/link/MachO.zig+15-2
...@@ -1128,8 +1128,15 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {...@@ -1128,8 +1128,15 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {
1128 const file_offset = section.header.offset + sym.n_value - section.header.addr;1128 const file_offset = section.header.offset + sym.n_value - section.header.addr;
1129 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });1129 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });
11301130
1131 if (self.relocs.get(atom_index)) |relocs| {1131 // Gather relocs which can be resolved.
1132 Atom.resolveRelocations(self, atom_index, relocs.items, code);1132 var relocs = std.ArrayList(*Relocation).init(self.base.allocator);
1133 defer relocs.deinit();
1134
1135 if (self.relocs.getPtr(atom_index)) |rels| {
1136 try relocs.ensureTotalCapacityPrecise(rels.items.len);
1137 for (rels.items) |*reloc| {
1138 if (reloc.isResolvable(self)) relocs.appendAssumeCapacity(reloc);
1139 }
1133 }1140 }
11341141
1135 if (is_hot_update_compatible) {1142 if (is_hot_update_compatible) {
...@@ -1144,7 +1151,13 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {...@@ -1144,7 +1151,13 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {
1144 }1151 }
1145 }1152 }
11461153
1154 Atom.resolveRelocations(self, atom_index, relocs.items, code);
1147 try self.base.file.?.pwriteAll(code, file_offset);1155 try self.base.file.?.pwriteAll(code, file_offset);
1156
1157 // Now we can mark the relocs as resolved.
1158 while (relocs.popOrNull()) |reloc| {
1159 reloc.dirty = false;
1160 }
1148}1161}
11491162
1150fn updateAtomInMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void {1163fn updateAtomInMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void {
src/link/MachO/Atom.zig+7-4
...@@ -179,12 +179,15 @@ pub fn addLazyBinding(macho_file: *MachO, atom_index: Index, binding: Binding) !...@@ -179,12 +179,15 @@ pub fn addLazyBinding(macho_file: *MachO, atom_index: Index, binding: Binding) !
179 try gop.value_ptr.append(gpa, binding);179 try gop.value_ptr.append(gpa, binding);
180}180}
181181
182pub fn resolveRelocations(macho_file: *MachO, atom_index: Index, relocs: []Relocation, code: []u8) void {182pub fn resolveRelocations(
183 macho_file: *MachO,
184 atom_index: Index,
185 relocs: []*const Relocation,
186 code: []u8,
187) void {
183 log.debug("relocating '{s}'", .{macho_file.getAtom(atom_index).getName(macho_file)});188 log.debug("relocating '{s}'", .{macho_file.getAtom(atom_index).getName(macho_file)});
184 for (relocs) |*reloc| {189 for (relocs) |reloc| {
185 if (!reloc.dirty) continue;
186 reloc.resolve(macho_file, atom_index, code);190 reloc.resolve(macho_file, atom_index, code);
187 reloc.dirty = false;
188 }191 }
189}192}
190193
src/link/MachO/Relocation.zig+7-1
...@@ -21,6 +21,12 @@ pcrel: bool,...@@ -21,6 +21,12 @@ pcrel: bool,
21length: u2,21length: u2,
22dirty: bool = true,22dirty: bool = true,
2323
24/// Returns true if and only if the reloc is dirty AND the target address is available.
25pub fn isResolvable(self: Relocation, macho_file: *MachO) bool {
26 _ = self.getTargetAtomIndex(macho_file) orelse return false;
27 return self.dirty;
28}
29
24pub fn fmtType(self: Relocation, target: std.Target) []const u8 {30pub fn fmtType(self: Relocation, target: std.Target) []const u8 {
25 switch (target.cpu.arch) {31 switch (target.cpu.arch) {
26 .aarch64 => return @tagName(@intToEnum(macho.reloc_type_arm64, self.type)),32 .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...@@ -56,7 +62,7 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod
56 const source_sym = atom.getSymbol(macho_file);62 const source_sym = atom.getSymbol(macho_file);
57 const source_addr = source_sym.n_value + self.offset;63 const source_addr = source_sym.n_value + self.offset;
5864
59 const target_atom_index = self.getTargetAtomIndex(macho_file) orelse return;65 const target_atom_index = self.getTargetAtomIndex(macho_file).?; // Oops, you didn't check if the relocation can be resolved with isResolvable().
60 const target_atom = macho_file.getAtom(target_atom_index);66 const target_atom = macho_file.getAtom(target_atom_index);
61 const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend;67 const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend;
6268