diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-21 14:00:45 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-21 22:44:28 +0200 |
| commit | 14dfbbc21365131c7ac85f08f543058f43fca0c2 (patch) | |
| tree | 01029705c92e87c9abf59710ae25826c69b7a73f /src | |
| parent | 9a181f367d51acc653379c173b7661f9c69e5ad4 (diff) | |
| download | zig-14dfbbc21365131c7ac85f08f543058f43fca0c2.tar.gz zig-14dfbbc21365131c7ac85f08f543058f43fca0c2.zip | |
macho: rebase lazy pointers and apply corrected base offset
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 8975f38570..47954f8871 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3000,6 +3000,28 @@ fn writeLinkeditSegmentData(self: *MachO) !void { seg.vmsize = mem.alignForwardGeneric(u64, seg.filesize, self.page_size); } +fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void { + const header = self.sections.items(.header)[sect_id]; + const segment_index = self.sections.items(.segment_index)[sect_id]; + const segment = self.segments.items[segment_index]; + const base_offset = header.addr - segment.vmaddr; + const is_got = if (self.got_section_index) |index| index == sect_id else false; + + try rebase.entries.ensureUnusedCapacity(self.base.allocator, table.entries.items.len); + + for (table.entries.items, 0..) |entry, i| { + if (!table.lookup.contains(entry)) continue; + const sym = self.getSymbol(entry); + if (is_got and sym.undf()) continue; + const offset = i * @sizeOf(u64); + log.debug(" | rebase at {x}", .{base_offset + offset}); + rebase.entries.appendAssumeCapacity(.{ + .offset = base_offset + offset, + .segment_id = segment_index, + }); + } +} + fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { const gpa = self.base.allocator; const slice = self.sections.slice(); @@ -3027,49 +3049,36 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { } } - // Gather GOT pointers - try rebase.entries.ensureUnusedCapacity(gpa, self.got_table.entries.items.len); - const segment_index = self.sections.items(.segment_index)[self.got_section_index.?]; - for (self.got_table.entries.items, 0..) |entry, i| { - if (!self.got_table.lookup.contains(entry)) continue; - const sym = self.getSymbol(entry); - if (sym.undf()) continue; - const offset = i * @sizeOf(u64); - log.debug(" | rebase at {x}", .{offset}); - rebase.entries.appendAssumeCapacity(.{ - .offset = offset, - .segment_id = segment_index, - }); - } + try self.collectRebaseDataFromTableSection(self.got_section_index.?, rebase, self.got_table); + try self.collectRebaseDataFromTableSection(self.la_symbol_ptr_section_index.?, rebase, self.stub_table); try rebase.finalize(gpa); } fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, table: anytype) !void { + const header = self.sections.items(.header)[sect_id]; const segment_index = self.sections.items(.segment_index)[sect_id]; + const segment = self.segments.items[segment_index]; + const base_offset = header.addr - segment.vmaddr; try bind.entries.ensureUnusedCapacity(self.base.allocator, table.entries.items.len); for (table.entries.items, 0..) |entry, i| { if (!table.lookup.contains(entry)) continue; - const bind_sym = self.getSymbol(entry); if (!bind_sym.undf()) continue; - const offset = i * @sizeOf(u64); - log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{ - offset, + base_offset + offset, self.getSymbolName(entry), @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER), }); if (bind_sym.weakRef()) { log.debug(" | marking as weak ref ", .{}); } - bind.entries.appendAssumeCapacity(.{ .target = entry, - .offset = offset, + .offset = base_offset + offset, .segment_id = segment_index, .addend = 0, }); |
