aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-06-22 10:29:58 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-06-24 18:56:33 +0200
commit0736365fa45fe4f3649a98a63fa82ccf8fc70d40 (patch)
treeeb49de851ace7808d585a9b996f3f6322d8b2a55 /src
parentd1fcb998484c8dec6e931b51a89ce4b2999254f5 (diff)
downloadzig-0736365fa45fe4f3649a98a63fa82ccf8fc70d40.tar.gz
zig-0736365fa45fe4f3649a98a63fa82ccf8fc70d40.zip
zld: fix finding pointers for rebasing
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO/Zld.zig43
1 files changed, 33 insertions, 10 deletions
diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig
index 31f1eef303..8a302ea06c 100644
--- a/src/link/MachO/Zld.zig
+++ b/src/link/MachO/Zld.zig
@@ -1948,29 +1948,52 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
args.source_target_sect_addr = source_sect.inner.addr;
}
- rebases: {
- var hit: bool = false;
- if (target_map.segment_id == self.data_segment_cmd_index.?) {
- if (self.data_section_index) |index| {
- if (index == target_map.section_id) hit = true;
+ const flags = @truncate(u8, target_sect.flags & 0xff);
+ const should_rebase = rebase: {
+ if (!unsigned.is_64bit) break :rebase false;
+
+ // TODO actually, a check similar to what dyld is doing, that is, verifying
+ // that the segment is writable should be enough here.
+ const is_right_segment = blk: {
+ if (self.data_segment_cmd_index) |idx| {
+ if (target_map.segment_id == idx) {
+ break :blk true;
+ }
}
+ if (self.data_const_segment_cmd_index) |idx| {
+ if (target_map.segment_id == idx) {
+ break :blk true;
+ }
+ }
+ break :blk false;
+ };
+
+ if (!is_right_segment) break :rebase false;
+ if (flags != macho.S_LITERAL_POINTERS and
+ flags != macho.S_REGULAR)
+ {
+ break :rebase false;
}
- if (target_map.segment_id == self.data_const_segment_cmd_index.?) {
- if (self.data_const_section_index) |index| {
- if (index == target_map.section_id) hit = true;
+ if (rel.target == .symbol) {
+ const final = rel.target.symbol.getTopmostAlias();
+ if (final.cast(Symbol.Proxy)) |_| {
+ break :rebase false;
}
}
- if (!hit) break :rebases;
+ break :rebase true;
+ };
+ if (should_rebase) {
try self.local_rebases.append(self.allocator, .{
.offset = source_addr - target_seg.inner.vmaddr,
.segment_id = target_map.segment_id,
});
}
+
// TLV is handled via a separate offset mechanism.
// Calculate the offset to the initializer.
- if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
+ if (flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
// TODO we don't want to save offset to tlv_bootstrap
if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv;