authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-22 10:29:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-24 18:56:33+02:00
log0736365fa45fe4f3649a98a63fa82ccf8fc70d40
treeeb49de851ace7808d585a9b996f3f6322d8b2a55
parentd1fcb998484c8dec6e931b51a89ce4b2999254f5

zld: fix finding pointers for rebasing


1 files changed, 33 insertions(+), 10 deletions(-)

src/link/MachO/Zld.zig+33-10
......@@ -1948,29 +1948,52 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
19481948 args.source_target_sect_addr = source_sect.inner.addr;
19491949 }
19501950
1951 rebases: {
1952 var hit: bool = false;
1953 if (target_map.segment_id == self.data_segment_cmd_index.?) {
1954 if (self.data_section_index) |index| {
1955 if (index == target_map.section_id) hit = true;
1951 const flags = @truncate(u8, target_sect.flags & 0xff);
1952 const should_rebase = rebase: {
1953 if (!unsigned.is_64bit) break :rebase false;
1954
1955 // TODO actually, a check similar to what dyld is doing, that is, verifying
1956 // that the segment is writable should be enough here.
1957 const is_right_segment = blk: {
1958 if (self.data_segment_cmd_index) |idx| {
1959 if (target_map.segment_id == idx) {
1960 break :blk true;
1961 }
19561962 }
1963 if (self.data_const_segment_cmd_index) |idx| {
1964 if (target_map.segment_id == idx) {
1965 break :blk true;
1966 }
1967 }
1968 break :blk false;
1969 };
1970
1971 if (!is_right_segment) break :rebase false;
1972 if (flags != macho.S_LITERAL_POINTERS and
1973 flags != macho.S_REGULAR)
1974 {
1975 break :rebase false;
19571976 }
1958 if (target_map.segment_id == self.data_const_segment_cmd_index.?) {
1959 if (self.data_const_section_index) |index| {
1960 if (index == target_map.section_id) hit = true;
1977 if (rel.target == .symbol) {
1978 const final = rel.target.symbol.getTopmostAlias();
1979 if (final.cast(Symbol.Proxy)) |_| {
1980 break :rebase false;
19611981 }
19621982 }
19631983
1964 if (!hit) break :rebases;
1984 break :rebase true;
1985 };
19651986
1987 if (should_rebase) {
19661988 try self.local_rebases.append(self.allocator, .{
19671989 .offset = source_addr - target_seg.inner.vmaddr,
19681990 .segment_id = target_map.segment_id,
19691991 });
19701992 }
1993
19711994 // TLV is handled via a separate offset mechanism.
19721995 // Calculate the offset to the initializer.
1973 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1996 if (flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
19741997 // TODO we don't want to save offset to tlv_bootstrap
19751998 if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv;
19761999