diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2020-11-25 22:02:59 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2020-11-26 11:50:09 +0100 |
| commit | 64eae8f39240109ce23c21e975c1d29191b4692a (patch) | |
| tree | 4a5bbbb6e06459889640b2d5ee5bbd08bef2a3d3 /src | |
| parent | c749b78df50160bedae40f90765442dd1f49de3a (diff) | |
| download | zig-64eae8f39240109ce23c21e975c1d29191b4692a.tar.gz zig-64eae8f39240109ce23c21e975c1d29191b4692a.zip | |
stage2 macho: move PIE fixups to link file; fix tests
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.zig | 8 | ||||
| -rw-r--r-- | src/link/MachO.zig | 46 |
2 files changed, 24 insertions, 30 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index 35443ba0b1..af91e7e909 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -2601,7 +2601,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }).toU32()); // adr x28, #8 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); - try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{ + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ .address = addr, .start = self.code.items.len, .len = 4, @@ -2626,7 +2626,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }).toU32()); // adr x28, #8 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); - try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{ + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ .address = addr, .start = self.code.items.len, .len = 4, @@ -2838,7 +2838,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // later in the linker. if (reg.id() == 0) { // %rax is special-cased try self.code.ensureCapacity(self.code.items.len + 5); - try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{ + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ .address = x, .start = self.code.items.len, .len = 5, @@ -2855,7 +2855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { try self.code.ensureCapacity(self.code.items.len + 10); // push %rax self.code.appendSliceAssumeCapacity(&[_]u8{0x50}); - try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{ + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ .address = x, .start = self.code.items.len, .len = 5, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index e0d5cc0d3c..e66b6ab413 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -175,6 +175,22 @@ libsystem_cmd_dirty: bool = false, text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, /// Pointer to the last allocated text block last_text_block: ?*TextBlock = null, +/// A list of all PIE fixups required for this run of the linker. +/// Warning, this is currently NOT thread-safe. See the TODO below. +/// TODO Move this list inside `updateDecl` where it should be allocated +/// prior to calling `generateSymbol`, and then immediately deallocated +/// rather than sitting in the global scope. +pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{}, + +pub const PieFixup = struct { + /// Target address we wanted to address in absolute terms. + address: u64, + /// Where in the byte stream we should perform the fixup. + start: usize, + /// The length of the byte stream. For x86_64, this will be + /// variable. For aarch64, it will be fixed at 4 bytes. + len: usize, +}; /// `alloc_num / alloc_den` is the factor of padding when allocating. const alloc_num = 4; @@ -215,20 +231,10 @@ pub const TextBlock = struct { /// Unlike in Elf, we need to store the size of this symbol as part of /// the TextBlock since macho.nlist_64 lacks this information. size: u64, - /// List of PIE fixups in the code. - /// This is a table of all position-relative positions that will need fixups - /// after codegen when linker assigns addresses to GOT entries. - pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{}, /// Points to the previous and next neighbours prev: ?*TextBlock, next: ?*TextBlock, - pub const PieFixup = struct { - address: u64, - start: usize, - len: usize, - }; - pub const empty = TextBlock{ .local_sym_index = 0, .offset_table_index = undefined, @@ -237,14 +243,6 @@ pub const TextBlock = struct { .next = null, }; - pub fn addPieFixup(self: *TextBlock, alloc: *Allocator, fixup: PieFixup) !void { - return self.pie_fixups.append(alloc, fixup); - } - - fn deinit(self: *TextBlock, alloc: *Allocator) void { - self.pie_fixups.deinit(alloc); - } - /// Returns how much room there is to grow in virtual address space. /// File offset relocation happens transparently, so it is not included in /// this calculation. @@ -849,9 +847,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 { } pub fn deinit(self: *MachO) void { - for (self.text_block_free_list.items) |tb| { - tb.deinit(self.base.allocator); - } + self.pie_fixups.deinit(self.base.allocator); self.text_block_free_list.deinit(self.base.allocator); self.offset_table.deinit(self.base.allocator); self.offset_table_free_list.deinit(self.base.allocator); @@ -894,9 +890,7 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void { if (!already_have_free_list_node and prev.freeListEligible(self.*)) { // The free list is heuristics, it doesn't have to be perfect, so we can ignore // the OOM here. - self.text_block_free_list.append(self.base.allocator, prev) catch { - prev.deinit(self.base.allocator); - }; + self.text_block_free_list.append(self.base.allocator, prev) catch {}; } } else { text_block.prev = null; @@ -1018,7 +1012,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { // Perform PIE fixups (if any) const got_section = self.sections.items[self.got_section_index.?]; - while (decl.link.macho.pie_fixups.popOrNull()) |fixup| { + while (self.pie_fixups.popOrNull()) |fixup| { const target_addr = fixup.address; const this_addr = symbol.n_value + fixup.start; if (self.base.options.target.cpu.arch == .x86_64) { @@ -1761,7 +1755,7 @@ fn writeCodeSignature(self: *MachO) !void { } fn writeExportTrie(self: *MachO) !void { - assert(self.global_symbols.items.len > 0); + if (self.global_symbols.items.len == 0) return; var trie: Trie = .{}; defer trie.deinit(self.base.allocator); |
