| ... | @@ -1146,7 +1146,9 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { | ... | @@ -1146,7 +1146,9 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { |
| 1146 | if (self.relocs.getPtr(atom_index)) |rels| { | 1146 | if (self.relocs.getPtr(atom_index)) |rels| { |
| 1147 | try relocs.ensureTotalCapacityPrecise(rels.items.len); | 1147 | try relocs.ensureTotalCapacityPrecise(rels.items.len); |
| 1148 | for (rels.items) |*reloc| { | 1148 | for (rels.items) |*reloc| { |
| 1149 | if (reloc.isResolvable(self)) relocs.appendAssumeCapacity(reloc); | 1149 | if (reloc.isResolvable(self) and reloc.dirty) { |
| | 1150 | relocs.appendAssumeCapacity(reloc); |
| | 1151 | } |
| 1150 | } | 1152 | } |
| 1151 | } | 1153 | } |
| 1152 | | 1154 | |
| ... | @@ -1332,18 +1334,33 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { | ... | @@ -1332,18 +1334,33 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { |
| 1332 | | 1334 | |
| 1333 | fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { | 1335 | fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { |
| 1334 | log.debug("marking relocs dirty by address: {x}", .{addr}); | 1336 | log.debug("marking relocs dirty by address: {x}", .{addr}); |
| | 1337 | |
| | 1338 | const got_moved = blk: { |
| | 1339 | const sect_id = self.got_section_index orelse break :blk false; |
| | 1340 | break :blk self.sections.items(.header)[sect_id].addr > addr; |
| | 1341 | }; |
| | 1342 | const stubs_moved = blk: { |
| | 1343 | const sect_id = self.stubs_section_index orelse break :blk false; |
| | 1344 | break :blk self.sections.items(.header)[sect_id].addr > addr; |
| | 1345 | }; |
| | 1346 | |
| 1335 | for (self.relocs.values()) |*relocs| { | 1347 | for (self.relocs.values()) |*relocs| { |
| 1336 | for (relocs.items) |*reloc| { | 1348 | for (relocs.items) |*reloc| { |
| 1337 | const target_addr = reloc.getTargetBaseAddress(self) orelse continue; | 1349 | if (reloc.isGotIndirection()) { |
| 1338 | if (target_addr < addr) continue; | 1350 | reloc.dirty = reloc.dirty or got_moved; |
| 1339 | reloc.dirty = true; | 1351 | } else if (reloc.isStubTrampoline(self)) { |
| | 1352 | reloc.dirty = reloc.dirty or stubs_moved; |
| | 1353 | } else { |
| | 1354 | const target_addr = reloc.getTargetBaseAddress(self) orelse continue; |
| | 1355 | if (target_addr > addr) reloc.dirty = true; |
| | 1356 | } |
| 1340 | } | 1357 | } |
| 1341 | } | 1358 | } |
| 1342 | | 1359 | |
| 1343 | // TODO: dirty only really affected GOT cells | 1360 | // TODO: dirty only really affected GOT cells |
| 1344 | for (self.got_table.entries.items) |entry| { | 1361 | for (self.got_table.entries.items) |entry| { |
| 1345 | const target_addr = self.getSymbol(entry).n_value; | 1362 | const target_addr = self.getSymbol(entry).n_value; |
| 1346 | if (target_addr >= addr) { | 1363 | if (target_addr > addr) { |
| 1347 | self.got_table_contents_dirty = true; | 1364 | self.got_table_contents_dirty = true; |
| 1348 | break; | 1365 | break; |
| 1349 | } | 1366 | } |
| ... | @@ -1353,7 +1370,7 @@ fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { | ... | @@ -1353,7 +1370,7 @@ fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { |
| 1353 | const stubs_addr = self.getSegment(self.stubs_section_index.?).vmaddr; | 1370 | const stubs_addr = self.getSegment(self.stubs_section_index.?).vmaddr; |
| 1354 | const stub_helper_addr = self.getSegment(self.stub_helper_section_index.?).vmaddr; | 1371 | const stub_helper_addr = self.getSegment(self.stub_helper_section_index.?).vmaddr; |
| 1355 | const laptr_addr = self.getSegment(self.la_symbol_ptr_section_index.?).vmaddr; | 1372 | const laptr_addr = self.getSegment(self.la_symbol_ptr_section_index.?).vmaddr; |
| 1356 | if (stubs_addr >= addr or stub_helper_addr >= addr or laptr_addr >= addr) | 1373 | if (stubs_addr > addr or stub_helper_addr > addr or laptr_addr > addr) |
| 1357 | self.stub_table_contents_dirty = true; | 1374 | self.stub_table_contents_dirty = true; |
| 1358 | } | 1375 | } |
| 1359 | } | 1376 | } |
| ... | @@ -2794,7 +2811,7 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { | ... | @@ -2794,7 +2811,7 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 2794 | | 2811 | |
| 2795 | const sect_vm_capacity = self.allocatedVirtualSize(segment.vmaddr); | 2812 | const sect_vm_capacity = self.allocatedVirtualSize(segment.vmaddr); |
| 2796 | if (needed_size > sect_vm_capacity) { | 2813 | if (needed_size > sect_vm_capacity) { |
| 2797 | self.markRelocsDirtyByAddress(segment.vmaddr + needed_size); | 2814 | self.markRelocsDirtyByAddress(segment.vmaddr + segment.vmsize); |
| 2798 | try self.growSectionVirtualMemory(sect_id, needed_size); | 2815 | try self.growSectionVirtualMemory(sect_id, needed_size); |
| 2799 | } | 2816 | } |
| 2800 | | 2817 | |
| ... | @@ -4067,11 +4084,12 @@ pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, p | ... | @@ -4067,11 +4084,12 @@ pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, p |
| 4067 | pub fn logSections(self: *MachO) void { | 4084 | pub fn logSections(self: *MachO) void { |
| 4068 | log.debug("sections:", .{}); | 4085 | log.debug("sections:", .{}); |
| 4069 | for (self.sections.items(.header), 0..) |header, i| { | 4086 | for (self.sections.items(.header), 0..) |header, i| { |
| 4070 | log.debug(" sect({d}): {s},{s} @{x}, sizeof({x})", .{ | 4087 | log.debug(" sect({d}): {s},{s} @{x} ({x}), sizeof({x})", .{ |
| 4071 | i + 1, | 4088 | i + 1, |
| 4072 | header.segName(), | 4089 | header.segName(), |
| 4073 | header.sectName(), | 4090 | header.sectName(), |
| 4074 | header.offset, | 4091 | header.offset, |
| | 4092 | header.addr, |
| 4075 | header.size, | 4093 | header.size, |
| 4076 | }); | 4094 | }); |
| 4077 | } | 4095 | } |