authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-25 22:02:59+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-26 11:50:09+01:00
log64eae8f39240109ce23c21e975c1d29191b4692a
tree4a5bbbb6e06459889640b2d5ee5bbd08bef2a3d3
parentc749b78df50160bedae40f90765442dd1f49de3a

stage2 macho: move PIE fixups to link file; fix tests


2 files changed, 24 insertions(+), 30 deletions(-)

src/codegen.zig+4-4
...@@ -2601,7 +2601,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2601,7 +2601,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2601 }).toU32());2601 }).toU32());
2602 // adr x28, #82602 // adr x28, #8
2603 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());2603 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());
2604 try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{2604 try macho_file.pie_fixups.append(self.bin_file.allocator, .{
2605 .address = addr,2605 .address = addr,
2606 .start = self.code.items.len,2606 .start = self.code.items.len,
2607 .len = 4,2607 .len = 4,
...@@ -2626,7 +2626,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2626,7 +2626,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2626 }).toU32());2626 }).toU32());
2627 // adr x28, #82627 // adr x28, #8
2628 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());2628 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());
2629 try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{2629 try macho_file.pie_fixups.append(self.bin_file.allocator, .{
2630 .address = addr,2630 .address = addr,
2631 .start = self.code.items.len,2631 .start = self.code.items.len,
2632 .len = 4,2632 .len = 4,
...@@ -2838,7 +2838,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2838,7 +2838,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2838 // later in the linker.2838 // later in the linker.
2839 if (reg.id() == 0) { // %rax is special-cased2839 if (reg.id() == 0) { // %rax is special-cased
2840 try self.code.ensureCapacity(self.code.items.len + 5);2840 try self.code.ensureCapacity(self.code.items.len + 5);
2841 try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{2841 try macho_file.pie_fixups.append(self.bin_file.allocator, .{
2842 .address = x,2842 .address = x,
2843 .start = self.code.items.len,2843 .start = self.code.items.len,
2844 .len = 5,2844 .len = 5,
...@@ -2855,7 +2855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2855,7 +2855,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2855 try self.code.ensureCapacity(self.code.items.len + 10);2855 try self.code.ensureCapacity(self.code.items.len + 10);
2856 // push %rax2856 // push %rax
2857 self.code.appendSliceAssumeCapacity(&[_]u8{0x50});2857 self.code.appendSliceAssumeCapacity(&[_]u8{0x50});
2858 try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{2858 try macho_file.pie_fixups.append(self.bin_file.allocator, .{
2859 .address = x,2859 .address = x,
2860 .start = self.code.items.len,2860 .start = self.code.items.len,
2861 .len = 5,2861 .len = 5,
src/link/MachO.zig+20-26
...@@ -175,6 +175,22 @@ libsystem_cmd_dirty: bool = false,...@@ -175,6 +175,22 @@ libsystem_cmd_dirty: bool = false,
175text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{},175text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{},
176/// Pointer to the last allocated text block176/// Pointer to the last allocated text block
177last_text_block: ?*TextBlock = null,177last_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.
183pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{},
184
185pub 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};
178194
179/// `alloc_num / alloc_den` is the factor of padding when allocating.195/// `alloc_num / alloc_den` is the factor of padding when allocating.
180const alloc_num = 4;196const alloc_num = 4;
...@@ -215,20 +231,10 @@ pub const TextBlock = struct {...@@ -215,20 +231,10 @@ pub const TextBlock = struct {
215 /// Unlike in Elf, we need to store the size of this symbol as part of231 /// Unlike in Elf, we need to store the size of this symbol as part of
216 /// the TextBlock since macho.nlist_64 lacks this information.232 /// the TextBlock since macho.nlist_64 lacks this information.
217 size: u64,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 /// Points to the previous and next neighbours234 /// Points to the previous and next neighbours
223 prev: ?*TextBlock,235 prev: ?*TextBlock,
224 next: ?*TextBlock,236 next: ?*TextBlock,
225237
226 pub const PieFixup = struct {
227 address: u64,
228 start: usize,
229 len: usize,
230 };
231
232 pub const empty = TextBlock{238 pub const empty = TextBlock{
233 .local_sym_index = 0,239 .local_sym_index = 0,
234 .offset_table_index = undefined,240 .offset_table_index = undefined,
...@@ -237,14 +243,6 @@ pub const TextBlock = struct {...@@ -237,14 +243,6 @@ pub const TextBlock = struct {
237 .next = null,243 .next = null,
238 };244 };
239245
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 /// Returns how much room there is to grow in virtual address space.246 /// Returns how much room there is to grow in virtual address space.
249 /// File offset relocation happens transparently, so it is not included in247 /// File offset relocation happens transparently, so it is not included in
250 /// this calculation.248 /// this calculation.
...@@ -849,9 +847,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {...@@ -849,9 +847,7 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {
849}847}
850848
851pub fn deinit(self: *MachO) void {849pub fn deinit(self: *MachO) void {
852 for (self.text_block_free_list.items) |tb| {850 self.pie_fixups.deinit(self.base.allocator);
853 tb.deinit(self.base.allocator);
854 }
855 self.text_block_free_list.deinit(self.base.allocator);851 self.text_block_free_list.deinit(self.base.allocator);
856 self.offset_table.deinit(self.base.allocator);852 self.offset_table.deinit(self.base.allocator);
857 self.offset_table_free_list.deinit(self.base.allocator);853 self.offset_table_free_list.deinit(self.base.allocator);
...@@ -894,9 +890,7 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {...@@ -894,9 +890,7 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
894 if (!already_have_free_list_node and prev.freeListEligible(self.*)) {890 if (!already_have_free_list_node and prev.freeListEligible(self.*)) {
895 // The free list is heuristics, it doesn't have to be perfect, so we can ignore891 // The free list is heuristics, it doesn't have to be perfect, so we can ignore
896 // the OOM here.892 // the OOM here.
897 self.text_block_free_list.append(self.base.allocator, prev) catch {893 self.text_block_free_list.append(self.base.allocator, prev) catch {};
898 prev.deinit(self.base.allocator);
899 };
900 }894 }
901 } else {895 } else {
902 text_block.prev = null;896 text_block.prev = null;
...@@ -1018,7 +1012,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1018,7 +1012,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
10181012
1019 // Perform PIE fixups (if any)1013 // Perform PIE fixups (if any)
1020 const got_section = self.sections.items[self.got_section_index.?];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 const target_addr = fixup.address;1016 const target_addr = fixup.address;
1023 const this_addr = symbol.n_value + fixup.start;1017 const this_addr = symbol.n_value + fixup.start;
1024 if (self.base.options.target.cpu.arch == .x86_64) {1018 if (self.base.options.target.cpu.arch == .x86_64) {
...@@ -1761,7 +1755,7 @@ fn writeCodeSignature(self: *MachO) !void {...@@ -1761,7 +1755,7 @@ fn writeCodeSignature(self: *MachO) !void {
1761}1755}
17621756
1763fn writeExportTrie(self: *MachO) !void {1757fn writeExportTrie(self: *MachO) !void {
1764 assert(self.global_symbols.items.len > 0);1758 if (self.global_symbols.items.len == 0) return;
17651759
1766 var trie: Trie = .{};1760 var trie: Trie = .{};
1767 defer trie.deinit(self.base.allocator);1761 defer trie.deinit(self.base.allocator);