| ... | @@ -1948,29 +1948,52 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { | ... | @@ -1948,29 +1948,52 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1948 | args.source_target_sect_addr = source_sect.inner.addr; | 1948 | args.source_target_sect_addr = source_sect.inner.addr; |
| 1949 | } | 1949 | } |
| 1950 | | 1950 | |
| 1951 | rebases: { | 1951 | const flags = @truncate(u8, target_sect.flags & 0xff); |
| 1952 | var hit: bool = false; | 1952 | const should_rebase = rebase: { |
| 1953 | if (target_map.segment_id == self.data_segment_cmd_index.?) { | 1953 | if (!unsigned.is_64bit) break :rebase false; |
| 1954 | if (self.data_section_index) |index| { | 1954 | |
| 1955 | if (index == target_map.section_id) hit = true; | 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 | } |
| 1956 | } | 1962 | } |
| | 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; |
| 1957 | } | 1976 | } |
| 1958 | if (target_map.segment_id == self.data_const_segment_cmd_index.?) { | 1977 | if (rel.target == .symbol) { |
| 1959 | if (self.data_const_section_index) |index| { | 1978 | const final = rel.target.symbol.getTopmostAlias(); |
| 1960 | if (index == target_map.section_id) hit = true; | 1979 | if (final.cast(Symbol.Proxy)) |_| { |
| | 1980 | break :rebase false; |
| 1961 | } | 1981 | } |
| 1962 | } | 1982 | } |
| 1963 | | 1983 | |
| 1964 | if (!hit) break :rebases; | 1984 | break :rebase true; |
| | 1985 | }; |
| 1965 | | 1986 | |
| | 1987 | if (should_rebase) { |
| 1966 | try self.local_rebases.append(self.allocator, .{ | 1988 | try self.local_rebases.append(self.allocator, .{ |
| 1967 | .offset = source_addr - target_seg.inner.vmaddr, | 1989 | .offset = source_addr - target_seg.inner.vmaddr, |
| 1968 | .segment_id = target_map.segment_id, | 1990 | .segment_id = target_map.segment_id, |
| 1969 | }); | 1991 | }); |
| 1970 | } | 1992 | } |
| | 1993 | |
| 1971 | // TLV is handled via a separate offset mechanism. | 1994 | // TLV is handled via a separate offset mechanism. |
| 1972 | // Calculate the offset to the initializer. | 1995 | // 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: { |
| 1974 | // TODO we don't want to save offset to tlv_bootstrap | 1997 | // TODO we don't want to save offset to tlv_bootstrap |
| 1975 | if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv; | 1998 | if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv; |
| 1976 | | 1999 | |