| author | |
| committer | |
| log | a503724801e7b221aababd88aefe790a33c4135e |
| tree | 175181974bd7d28ec51f78013a3cf7f810a89791 |
| parent | f372995e1ef2a6dda4bc30eeaf817b0d947704e7 |
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 }); |
| 1130 | 1130 | ||
| 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 | } |
| 1134 | 1141 | ||
| 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 | } |
| 1146 | 1153 | ||
| 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 | } |
| 1149 | 1162 | ||
| 1150 | fn updateAtomInMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void { | 1163 | fn 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 | } |
| 181 | 181 | ||
| 182 | pub fn resolveRelocations(macho_file: *MachO, atom_index: Index, relocs: []Relocation, code: []u8) void { | 182 | pub 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 | } |
| 190 | 193 |
src/link/MachO/Relocation.zig+7-1| ... | @@ -21,6 +21,12 @@ pcrel: bool, | ... | @@ -21,6 +21,12 @@ pcrel: bool, |
| 21 | length: u2, | 21 | length: u2, |
| 22 | dirty: bool = true, | 22 | dirty: bool = true, |
| 23 | 23 | ||
| 24 | /// Returns true if and only if the reloc is dirty AND the target address is available. | ||
| 25 | pub fn isResolvable(self: Relocation, macho_file: *MachO) bool { | ||
| 26 | _ = self.getTargetAtomIndex(macho_file) orelse return false; | ||
| 27 | return self.dirty; | ||
| 28 | } | ||
| 29 | |||
| 24 | pub fn fmtType(self: Relocation, target: std.Target) []const u8 { | 30 | pub 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; |
| 58 | 64 | ||
| 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; |
| 62 | 68 |