aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-08-21 18:55:15 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-08-21 18:55:15 +0200
commitd61d85abd2b998fea438e7317568537f927fa6a1 (patch)
tree2aa6ebc065b5a2efa52b76f83668b8094c8d9773 /src
parentd63d8ae1c00c240ac20836f1b54bff0093edcb61 (diff)
downloadzig-d61d85abd2b998fea438e7317568537f927fa6a1.tar.gz
zig-d61d85abd2b998fea438e7317568537f927fa6a1.zip
macho: implement aarch64 prong of createStubHelperAtom
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO.zig169
1 files changed, 78 insertions, 91 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 8bb139e624..f6dd0ddaba 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -807,7 +807,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
// TODO just a temp
const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const sect = seg.sections.items[self.stub_helper_section_index.?];
- self.stub_helper_stubs_start_off = sect.offset + 15;
+ self.stub_helper_stubs_start_off = sect.offset + switch (self.base.options.target.cpu.arch) {
+ .x86_64 => @intCast(u64, 15),
+ .aarch64 => @intCast(u64, 6 * @sizeOf(u32)),
+ else => unreachable,
+ };
}
try self.flushZld();
} else {
@@ -2018,11 +2022,12 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
const atom = try self.createEmptyAtom(match, local_sym_index, size, alignment);
switch (arch) {
.x86_64 => {
+ try atom.relocs.ensureUnusedCapacity(self.base.allocator, 2);
// lea %r11, [rip + disp]
atom.code.items[0] = 0x4c;
atom.code.items[1] = 0x8d;
atom.code.items[2] = 0x1d;
- try atom.relocs.append(self.base.allocator, .{
+ atom.relocs.appendAssumeCapacity(.{
.offset = 3,
.where = .local,
.where_index = self.dyld_private_sym_index.?,
@@ -2039,7 +2044,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
// jmp [rip + disp]
atom.code.items[9] = 0xff;
atom.code.items[10] = 0x25;
- try atom.relocs.append(self.base.allocator, .{
+ atom.relocs.appendAssumeCapacity(.{
.offset = 11,
.where = .undef,
.where_index = self.dyld_stub_binder_index.?,
@@ -2051,94 +2056,76 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
},
});
},
- // .aarch64 => {
- // var code: [6 * @sizeOf(u32)]u8 = undefined;
- // data_blk_outer: {
- // const this_addr = stub_helper.addr;
- // const target_addr = data.addr + data.size - @sizeOf(u64);
- // 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);
- // 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]!
- // code[8] = 0xf0;
- // code[9] = 0x47;
- // code[10] = 0xbf;
- // code[11] = 0xa9;
- // binder_blk_outer: {
- // const got_index = self.got_entries_map.get(.{
- // .where = .undef,
- // .where_index = self.dyld_stub_binder_index.?,
- // }) orelse unreachable;
- // const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
- // const target_addr = got.addr + got_index * @sizeOf(u64);
- // 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;
- // // Pad with nop to please division.
- // // 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;
- // }
- // // Use adrp followed by ldr(immediate).
- // const this_page = @intCast(i32, this_addr >> 12);
- // const target_page = @intCast(i32, target_addr >> 12);
- // const pages = @intCast(i21, target_page - this_page);
- // 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);
- // mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
- // .register = .{
- // .rn = .x16,
- // .offset = aarch64.Instruction.LoadStoreOffset.imm(offset),
- // },
- // }).toU32());
- // }
- // // br x16
- // code[20] = 0x00;
- // code[21] = 0x02;
- // code[22] = 0x1f;
- // code[23] = 0xd6;
- // try self.base.file.?.pwriteAll(&code, stub_helper.offset);
- // break :blk stub_helper.offset + 6 * @sizeOf(u32);
- // },
+ .aarch64 => {
+ try atom.relocs.ensureUnusedCapacity(self.base.allocator, 4);
+ // adrp x17, 0
+ mem.writeIntLittle(u32, atom.code.items[0..][0..4], aarch64.Instruction.adrp(.x17, 0).toU32());
+ atom.relocs.appendAssumeCapacity(.{
+ .offset = 0,
+ .where = .local,
+ .where_index = self.dyld_private_sym_index.?,
+ .payload = .{
+ .page = .{
+ .kind = .page,
+ .addend = 0,
+ },
+ },
+ });
+ // add x17, x17, 0
+ mem.writeIntLittle(u32, atom.code.items[4..][0..4], aarch64.Instruction.add(.x17, .x17, 0, false).toU32());
+ atom.relocs.appendAssumeCapacity(.{
+ .offset = 4,
+ .where = .local,
+ .where_index = self.dyld_private_sym_index.?,
+ .payload = .{
+ .page_off = .{
+ .kind = .page,
+ .addend = 0,
+ .op_kind = .arithmetic,
+ },
+ },
+ });
+ // stp x16, x17, [sp, #-16]!
+ mem.writeIntLittle(u32, atom.code.items[8..][0..4], aarch64.Instruction.stp(
+ .x16,
+ .x17,
+ aarch64.Register.sp,
+ aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
+ ).toU32());
+ // adrp x16, 0
+ mem.writeIntLittle(u32, atom.code.items[12..][0..4], aarch64.Instruction.adrp(.x16, 0).toU32());
+ atom.relocs.appendAssumeCapacity(.{
+ .offset = 12,
+ .where = .undef,
+ .where_index = self.dyld_stub_binder_index.?,
+ .payload = .{
+ .page = .{
+ .kind = .got,
+ .addend = 0,
+ },
+ },
+ });
+ // ldr x16, [x16, 0]
+ mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(.x16, .{
+ .register = .{
+ .rn = .x16,
+ .offset = aarch64.Instruction.LoadStoreOffset.imm(0),
+ },
+ }).toU32());
+ atom.relocs.appendAssumeCapacity(.{
+ .offset = 16,
+ .where = .undef,
+ .where_index = self.dyld_stub_binder_index.?,
+ .payload = .{
+ .page_off = .{
+ .kind = .got,
+ .addend = 0,
+ },
+ },
+ });
+ // br x16
+ mem.writeIntLittle(u32, atom.code.items[20..][0..4], aarch64.Instruction.br(.x16).toU32());
+ },
else => unreachable,
}
self.stub_preamble_sym_index = local_sym_index;