authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-18 11:46:45+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-18 11:46:45+02:00
log30247fbb6a46231154f051119228829c6a0dfd90
tree19f83e4f9700e44081bee975c314d0855dec8075
parent8167456c58270fe9586ac93dbd6a6ee1a8ae7915

macho: remove redundant writeStubHelperCommon codepath


1 files changed, 15 insertions(+), 141 deletions(-)

src/link/MachO.zig+15-141
......@@ -376,10 +376,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
376376 try self.populateMissingMetadata();
377377 try self.writeLocalSymbol(0);
378378
379 if (self.stub_helper_stubs_start_off == null) {
380 try self.writeStubHelperPreamble();
381 }
382
383379 if (self.d_sym) |*ds| {
384380 try ds.populateMissingMetadata(allocator);
385381 try ds.writeLocalSymbol(0);
......@@ -762,6 +758,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
762758 try self.resolveSymbols();
763759 try self.resolveDyldStubBinder();
764760
761 if (!use_stage1) {
762 // TODO this should be made common when I figure out how to prealloc space for traditional linker path.
763 try self.writeStubHelperPreamble();
764 }
765
765766 // Apply pending updates
766767 var still_pending = std.ArrayList(PendingUpdate).init(self.base.allocator);
767768 defer still_pending.deinit();
......@@ -824,6 +825,7 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
824825 try self.allocateDataSegment();
825826 self.allocateLinkeditSegment();
826827 try self.allocateTextBlocks();
828 try self.writeStubHelperPreamble();
827829 try self.flushZld();
828830 } else {
829831 try self.flushModule(comp);
......@@ -1943,7 +1945,7 @@ fn writeTextBlocks(self: *MachO) !void {
19431945 }
19441946}
19451947
1946fn writeStubHelperCommon(self: *MachO) !void {
1948fn writeStubHelperPreamble(self: *MachO) !void {
19471949 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
19481950 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
19491951 const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
......@@ -2074,14 +2076,6 @@ fn writeStubHelperCommon(self: *MachO) !void {
20742076 else => unreachable,
20752077 }
20762078 };
2077
2078 for (self.stubs.items) |_, i| {
2079 const index = @intCast(u32, i);
2080 // TODO weak bound pointers
2081 try self.writeLazySymbolPointer(index);
2082 try self.writeStub(index);
2083 try self.writeStubInStubHelper(index);
2084 }
20852079}
20862080
20872081fn resolveSymbolsInObject(
......@@ -2616,7 +2610,14 @@ fn addLoadDylibLCs(self: *MachO) !void {
26162610
26172611fn flushZld(self: *MachO) !void {
26182612 try self.writeTextBlocks();
2619 try self.writeStubHelperCommon();
2613
2614 for (self.stubs.items) |_, i| {
2615 const index = @intCast(u32, i);
2616 // TODO weak bound pointers
2617 try self.writeLazySymbolPointer(index);
2618 try self.writeStub(index);
2619 try self.writeStubInStubHelper(index);
2620 }
26202621
26212622 if (self.common_section_index) |index| {
26222623 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
......@@ -4540,133 +4541,6 @@ fn writeLazySymbolPointer(self: *MachO, index: u32) !void {
45404541 try self.base.file.?.pwriteAll(&buf, off);
45414542}
45424543
4543fn writeStubHelperPreamble(self: *MachO) !void {
4544 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
4545 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
4546 const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
4547 const got = &data_const_segment.sections.items[self.got_section_index.?];
4548 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
4549 const data = &data_segment.sections.items[self.data_section_index.?];
4550
4551 switch (self.base.options.target.cpu.arch) {
4552 .x86_64 => {
4553 const code_size = 15;
4554 var code: [code_size]u8 = undefined;
4555 // lea %r11, [rip + disp]
4556 code[0] = 0x4c;
4557 code[1] = 0x8d;
4558 code[2] = 0x1d;
4559 {
4560 const target_addr = data.addr;
4561 const displacement = try math.cast(u32, target_addr - stub_helper.addr - 7);
4562 mem.writeIntLittle(u32, code[3..7], displacement);
4563 }
4564 // push %r11
4565 code[7] = 0x41;
4566 code[8] = 0x53;
4567 // jmp [rip + disp]
4568 code[9] = 0xff;
4569 code[10] = 0x25;
4570 {
4571 const displacement = try math.cast(u32, got.addr - stub_helper.addr - code_size);
4572 mem.writeIntLittle(u32, code[11..], displacement);
4573 }
4574 try self.base.file.?.pwriteAll(&code, stub_helper.offset);
4575 self.stub_helper_stubs_start_off = stub_helper.offset + code_size;
4576 },
4577 .aarch64 => {
4578 var code: [6 * @sizeOf(u32)]u8 = undefined;
4579
4580 data_blk_outer: {
4581 const this_addr = stub_helper.addr;
4582 const target_addr = data.addr;
4583 data_blk: {
4584 const displacement = math.cast(i21, target_addr - this_addr) catch break :data_blk;
4585 // adr x17, disp
4586 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x17, displacement).toU32());
4587 // nop
4588 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.nop().toU32());
4589 break :data_blk_outer;
4590 }
4591 data_blk: {
4592 const new_this_addr = this_addr + @sizeOf(u32);
4593 const displacement = math.cast(i21, target_addr - new_this_addr) catch break :data_blk;
4594 // nop
4595 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.nop().toU32());
4596 // adr x17, disp
4597 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.adr(.x17, displacement).toU32());
4598 break :data_blk_outer;
4599 }
4600 // Jump is too big, replace adr with adrp and add.
4601 const this_page = @intCast(i32, this_addr >> 12);
4602 const target_page = @intCast(i32, target_addr >> 12);
4603 const pages = @intCast(i21, target_page - this_page);
4604 // adrp x17, pages
4605 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adrp(.x17, pages).toU32());
4606 const narrowed = @truncate(u12, target_addr);
4607 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.add(.x17, .x17, narrowed, false).toU32());
4608 }
4609
4610 // stp x16, x17, [sp, #-16]!
4611 mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.stp(
4612 .x16,
4613 .x17,
4614 aarch64.Register.sp,
4615 aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
4616 ).toU32());
4617
4618 binder_blk_outer: {
4619 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
4620 const target_addr = got.addr;
4621 binder_blk: {
4622 const displacement = math.divExact(u64, target_addr - this_addr, 4) catch break :binder_blk;
4623 const literal = math.cast(u18, displacement) catch break :binder_blk;
4624 // ldr x16, label
4625 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.ldr(.x16, .{
4626 .literal = literal,
4627 }).toU32());
4628 // nop
4629 mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.nop().toU32());
4630 break :binder_blk_outer;
4631 }
4632 binder_blk: {
4633 const new_this_addr = this_addr + @sizeOf(u32);
4634 const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch break :binder_blk;
4635 const literal = math.cast(u18, displacement) catch break :binder_blk;
4636 // nop
4637 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.nop().toU32());
4638 // ldr x16, label
4639 mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
4640 .literal = literal,
4641 }).toU32());
4642 break :binder_blk_outer;
4643 }
4644 // Jump is too big, replace ldr with adrp and ldr(register).
4645 const this_page = @intCast(i32, this_addr >> 12);
4646 const target_page = @intCast(i32, target_addr >> 12);
4647 const pages = @intCast(i21, target_page - this_page);
4648 // adrp x16, pages
4649 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.adrp(.x16, pages).toU32());
4650 const narrowed = @truncate(u12, target_addr);
4651 const offset = try math.divExact(u12, narrowed, 8);
4652 // ldr x16, x16, offset
4653 mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
4654 .register = .{
4655 .rn = .x16,
4656 .offset = aarch64.Instruction.LoadStoreOffset.imm(offset),
4657 },
4658 }).toU32());
4659 }
4660
4661 // br x16
4662 mem.writeIntLittle(u32, code[20..24], aarch64.Instruction.br(.x16).toU32());
4663 try self.base.file.?.pwriteAll(&code, stub_helper.offset);
4664 self.stub_helper_stubs_start_off = stub_helper.offset + code.len;
4665 },
4666 else => unreachable,
4667 }
4668}
4669
46704544fn writeStub(self: *MachO, index: u32) !void {
46714545 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
46724546 const stubs = text_segment.sections.items[self.stubs_section_index.?];