Commit 30247fbb6a

Jakub Konka <kubkon@jakubkonka.com>
2021-08-18 11:46:45
macho: remove redundant writeStubHelperCommon codepath
1 parent 8167456
Changed files (1)
src
src/link/MachO.zig
@@ -376,10 +376,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
     try self.populateMissingMetadata();
     try self.writeLocalSymbol(0);
 
-    if (self.stub_helper_stubs_start_off == null) {
-        try self.writeStubHelperPreamble();
-    }
-
     if (self.d_sym) |*ds| {
         try ds.populateMissingMetadata(allocator);
         try ds.writeLocalSymbol(0);
@@ -762,6 +758,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
         try self.resolveSymbols();
         try self.resolveDyldStubBinder();
 
+        if (!use_stage1) {
+            // TODO this should be made common when I figure out how to prealloc space for traditional linker path.
+            try self.writeStubHelperPreamble();
+        }
+
         // Apply pending updates
         var still_pending = std.ArrayList(PendingUpdate).init(self.base.allocator);
         defer still_pending.deinit();
@@ -824,6 +825,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
             try self.allocateDataSegment();
             self.allocateLinkeditSegment();
             try self.allocateTextBlocks();
+            try self.writeStubHelperPreamble();
             try self.flushZld();
         } else {
             try self.flushModule(comp);
@@ -1943,7 +1945,7 @@ fn writeTextBlocks(self: *MachO) !void {
     }
 }
 
-fn writeStubHelperCommon(self: *MachO) !void {
+fn writeStubHelperPreamble(self: *MachO) !void {
     const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
     const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
     const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
@@ -2074,14 +2076,6 @@ fn writeStubHelperCommon(self: *MachO) !void {
             else => unreachable,
         }
     };
-
-    for (self.stubs.items) |_, i| {
-        const index = @intCast(u32, i);
-        // TODO weak bound pointers
-        try self.writeLazySymbolPointer(index);
-        try self.writeStub(index);
-        try self.writeStubInStubHelper(index);
-    }
 }
 
 fn resolveSymbolsInObject(
@@ -2616,7 +2610,14 @@ fn addLoadDylibLCs(self: *MachO) !void {
 
 fn flushZld(self: *MachO) !void {
     try self.writeTextBlocks();
-    try self.writeStubHelperCommon();
+
+    for (self.stubs.items) |_, i| {
+        const index = @intCast(u32, i);
+        // TODO weak bound pointers
+        try self.writeLazySymbolPointer(index);
+        try self.writeStub(index);
+        try self.writeStubInStubHelper(index);
+    }
 
     if (self.common_section_index) |index| {
         const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
@@ -4540,133 +4541,6 @@ fn writeLazySymbolPointer(self: *MachO, index: u32) !void {
     try self.base.file.?.pwriteAll(&buf, off);
 }
 
-fn writeStubHelperPreamble(self: *MachO) !void {
-    const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
-    const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
-    const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
-    const got = &data_const_segment.sections.items[self.got_section_index.?];
-    const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
-    const data = &data_segment.sections.items[self.data_section_index.?];
-
-    switch (self.base.options.target.cpu.arch) {
-        .x86_64 => {
-            const code_size = 15;
-            var code: [code_size]u8 = undefined;
-            // lea %r11, [rip + disp]
-            code[0] = 0x4c;
-            code[1] = 0x8d;
-            code[2] = 0x1d;
-            {
-                const target_addr = data.addr;
-                const displacement = try math.cast(u32, target_addr - stub_helper.addr - 7);
-                mem.writeIntLittle(u32, code[3..7], displacement);
-            }
-            // push %r11
-            code[7] = 0x41;
-            code[8] = 0x53;
-            // jmp [rip + disp]
-            code[9] = 0xff;
-            code[10] = 0x25;
-            {
-                const displacement = try math.cast(u32, got.addr - stub_helper.addr - code_size);
-                mem.writeIntLittle(u32, code[11..], displacement);
-            }
-            try self.base.file.?.pwriteAll(&code, stub_helper.offset);
-            self.stub_helper_stubs_start_off = stub_helper.offset + code_size;
-        },
-        .aarch64 => {
-            var code: [6 * @sizeOf(u32)]u8 = undefined;
-
-            data_blk_outer: {
-                const this_addr = stub_helper.addr;
-                const target_addr = data.addr;
-                data_blk: {
-                    const displacement = math.cast(i21, target_addr - this_addr) catch break :data_blk;
-                    // adr x17, disp
-                    mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x17, displacement).toU32());
-                    // nop
-                    mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.nop().toU32());
-                    break :data_blk_outer;
-                }
-                data_blk: {
-                    const new_this_addr = this_addr + @sizeOf(u32);
-                    const displacement = math.cast(i21, target_addr - new_this_addr) catch break :data_blk;
-                    // nop
-                    mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.nop().toU32());
-                    // adr x17, disp
-                    mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.adr(.x17, displacement).toU32());
-                    break :data_blk_outer;
-                }
-                // Jump is too big, replace adr with adrp and add.
-                const this_page = @intCast(i32, this_addr >> 12);
-                const target_page = @intCast(i32, target_addr >> 12);
-                const pages = @intCast(i21, target_page - this_page);
-                // adrp x17, pages
-                mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adrp(.x17, pages).toU32());
-                const narrowed = @truncate(u12, target_addr);
-                mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.add(.x17, .x17, narrowed, false).toU32());
-            }
-
-            // stp x16, x17, [sp, #-16]!
-            mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.stp(
-                .x16,
-                .x17,
-                aarch64.Register.sp,
-                aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
-            ).toU32());
-
-            binder_blk_outer: {
-                const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
-                const target_addr = got.addr;
-                binder_blk: {
-                    const displacement = math.divExact(u64, target_addr - this_addr, 4) catch break :binder_blk;
-                    const literal = math.cast(u18, displacement) catch break :binder_blk;
-                    // ldr x16, label
-                    mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.ldr(.x16, .{
-                        .literal = literal,
-                    }).toU32());
-                    // nop
-                    mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.nop().toU32());
-                    break :binder_blk_outer;
-                }
-                binder_blk: {
-                    const new_this_addr = this_addr + @sizeOf(u32);
-                    const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch break :binder_blk;
-                    const literal = math.cast(u18, displacement) catch break :binder_blk;
-                    // nop
-                    mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.nop().toU32());
-                    // ldr x16, label
-                    mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
-                        .literal = literal,
-                    }).toU32());
-                    break :binder_blk_outer;
-                }
-                // Jump is too big, replace ldr with adrp and ldr(register).
-                const this_page = @intCast(i32, this_addr >> 12);
-                const target_page = @intCast(i32, target_addr >> 12);
-                const pages = @intCast(i21, target_page - this_page);
-                // adrp x16, pages
-                mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.adrp(.x16, pages).toU32());
-                const narrowed = @truncate(u12, target_addr);
-                const offset = try math.divExact(u12, narrowed, 8);
-                // ldr x16, x16, offset
-                mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
-                    .register = .{
-                        .rn = .x16,
-                        .offset = aarch64.Instruction.LoadStoreOffset.imm(offset),
-                    },
-                }).toU32());
-            }
-
-            // br x16
-            mem.writeIntLittle(u32, code[20..24], aarch64.Instruction.br(.x16).toU32());
-            try self.base.file.?.pwriteAll(&code, stub_helper.offset);
-            self.stub_helper_stubs_start_off = stub_helper.offset + code.len;
-        },
-        else => unreachable,
-    }
-}
-
 fn writeStub(self: *MachO, index: u32) !void {
     const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
     const stubs = text_segment.sections.items[self.stubs_section_index.?];