| 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 | 1128 | const file_offset = section.header.offset + sym.n_value - section.header.addr; |
| 1129 | 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| { | |
| 1132 | Atom.resolveRelocations(self, atom_index, relocs.items, code); | |
| 1131 | // Gather relocs which can be resolved. | |
| 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 | 1142 | if (is_hot_update_compatible) { |
| ... | ... | @@ -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 | 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 | 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 | 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 | 188 | log.debug("relocating '{s}'", .{macho_file.getAtom(atom_index).getName(macho_file)}); |
| 184 | for (relocs) |*reloc| { | |
| 185 | if (!reloc.dirty) continue; | |
| 189 | for (relocs) |reloc| { | |
| 186 | 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 | 21 | length: u2, |
| 22 | 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 | 30 | pub fn fmtType(self: Relocation, target: std.Target) []const u8 { |
| 25 | 31 | switch (target.cpu.arch) { |
| 26 | 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 | 62 | const source_sym = atom.getSymbol(macho_file); |
| 57 | 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 | 66 | const target_atom = macho_file.getAtom(target_atom_index); |
| 61 | 67 | const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend; |
| 62 | 68 |