| ... | ... | @@ -175,6 +175,22 @@ libsystem_cmd_dirty: bool = false, |
| 175 | 175 | text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, |
| 176 | 176 | /// Pointer to the last allocated text block |
| 177 | 177 | last_text_block: ?*TextBlock = null, |
| 178 | /// A list of all PIE fixups required for this run of the linker. |
| 179 | /// Warning, this is currently NOT thread-safe. See the TODO below. |
| 180 | /// TODO Move this list inside `updateDecl` where it should be allocated |
| 181 | /// prior to calling `generateSymbol`, and then immediately deallocated |
| 182 | /// rather than sitting in the global scope. |
| 183 | pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{}, |
| 184 | |
| 185 | pub const PieFixup = struct { |
| 186 | /// Target address we wanted to address in absolute terms. |
| 187 | address: u64, |
| 188 | /// Where in the byte stream we should perform the fixup. |
| 189 | start: usize, |
| 190 | /// The length of the byte stream. For x86_64, this will be |
| 191 | /// variable. For aarch64, it will be fixed at 4 bytes. |
| 192 | len: usize, |
| 193 | }; |
| 178 | 194 | |
| 179 | 195 | /// `alloc_num / alloc_den` is the factor of padding when allocating. |
| 180 | 196 | const alloc_num = 4; |
| ... | ... | @@ -215,20 +231,10 @@ pub const TextBlock = struct { |
| 215 | 231 | /// Unlike in Elf, we need to store the size of this symbol as part of |
| 216 | 232 | /// the TextBlock since macho.nlist_64 lacks this information. |
| 217 | 233 | size: u64, |
| 218 | | /// List of PIE fixups in the code. |
| 219 | | /// This is a table of all position-relative positions that will need fixups |
| 220 | | /// after codegen when linker assigns addresses to GOT entries. |
| 221 | | pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{}, |
| 222 | 234 | /// Points to the previous and next neighbours |
| 223 | 235 | prev: ?*TextBlock, |
| 224 | 236 | next: ?*TextBlock, |
| 225 | 237 | |
| 226 | | pub const PieFixup = struct { |
| 227 | | address: u64, |
| 228 | | start: usize, |
| 229 | | len: usize, |
| 230 | | }; |
| 231 | | |
| 232 | 238 | pub const empty = TextBlock{ |
| 233 | 239 | .local_sym_index = 0, |
| 234 | 240 | .offset_table_index = undefined, |
| ... | ... | @@ -237,14 +243,6 @@ pub const TextBlock = struct { |
| 237 | 243 | .next = null, |
| 238 | 244 | }; |
| 239 | 245 | |
| 240 | | pub fn addPieFixup(self: *TextBlock, alloc: *Allocator, fixup: PieFixup) !void { |
| 241 | | return self.pie_fixups.append(alloc, fixup); |
| 242 | | } |
| 243 | | |
| 244 | | fn deinit(self: *TextBlock, alloc: *Allocator) void { |
| 245 | | self.pie_fixups.deinit(alloc); |
| 246 | | } |
| 247 | | |
| 248 | 246 | /// Returns how much room there is to grow in virtual address space. |
| 249 | 247 | /// File offset relocation happens transparently, so it is not included in |
| 250 | 248 | /// this calculation. |
| ... | ... | @@ -849,9 +847,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 { |
| 849 | 847 | } |
| 850 | 848 | |
| 851 | 849 | pub fn deinit(self: *MachO) void { |
| 852 | | for (self.text_block_free_list.items) |tb| { |
| 853 | | tb.deinit(self.base.allocator); |
| 854 | | } |
| 850 | self.pie_fixups.deinit(self.base.allocator); |
| 855 | 851 | self.text_block_free_list.deinit(self.base.allocator); |
| 856 | 852 | self.offset_table.deinit(self.base.allocator); |
| 857 | 853 | self.offset_table_free_list.deinit(self.base.allocator); |
| ... | ... | @@ -894,9 +890,7 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void { |
| 894 | 890 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { |
| 895 | 891 | // The free list is heuristics, it doesn't have to be perfect, so we can ignore |
| 896 | 892 | // the OOM here. |
| 897 | | self.text_block_free_list.append(self.base.allocator, prev) catch { |
| 898 | | prev.deinit(self.base.allocator); |
| 899 | | }; |
| 893 | self.text_block_free_list.append(self.base.allocator, prev) catch {}; |
| 900 | 894 | } |
| 901 | 895 | } else { |
| 902 | 896 | text_block.prev = null; |
| ... | ... | @@ -1018,7 +1012,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1018 | 1012 | |
| 1019 | 1013 | // Perform PIE fixups (if any) |
| 1020 | 1014 | const got_section = self.sections.items[self.got_section_index.?]; |
| 1021 | | while (decl.link.macho.pie_fixups.popOrNull()) |fixup| { |
| 1015 | while (self.pie_fixups.popOrNull()) |fixup| { |
| 1022 | 1016 | const target_addr = fixup.address; |
| 1023 | 1017 | const this_addr = symbol.n_value + fixup.start; |
| 1024 | 1018 | if (self.base.options.target.cpu.arch == .x86_64) { |
| ... | ... | @@ -1761,7 +1755,7 @@ fn writeCodeSignature(self: *MachO) !void { |
| 1761 | 1755 | } |
| 1762 | 1756 | |
| 1763 | 1757 | fn writeExportTrie(self: *MachO) !void { |
| 1764 | | assert(self.global_symbols.items.len > 0); |
| 1758 | if (self.global_symbols.items.len == 0) return; |
| 1765 | 1759 | |
| 1766 | 1760 | var trie: Trie = .{}; |
| 1767 | 1761 | defer trie.deinit(self.base.allocator); |