From 10942e3f86c03d30833cc221371f30b78a4bd710 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 25 Nov 2020 11:10:17 +0100 Subject: [PATCH] stage2 macho: Hello, Silicon! --- src/codegen.zig | 26 ++++++++++++++++++++++---- src/link/MachO.zig | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index f75ad079ae..1482e8de7e 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1689,6 +1689,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }, .aarch64 => { try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr }); + // blr x30 writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32()); }, else => unreachable, // unsupported architecture on MachO @@ -2583,10 +2584,27 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }, .register => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}), .memory => |addr| { - // The value is in memory at a hard-coded address. - // If the type is a pointer, it means the pointer address is at this memory location. - try self.genSetReg(src, reg, .{ .immediate = addr }); - mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .rn = reg }).toU32()); + if (self.bin_file.cast(link.File.MachO)) |macho_file| { + // For MachO, the binary, with the exception of object files, has to be a PIE. + // Therefore we cannot load an absolute address. + // Instead, we need to make use of PC-relative addressing. + // if (reg.id() == 0) { // x0 is special-cased + try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{ + .address = addr, + .start = self.code.items.len, + .len = 4, + }); + // bl [label] + mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bl(0).toU32()); + // } else { + // unreachable; // TODO + // } + } else { + // The value is in memory at a hard-coded address. + // If the type is a pointer, it means the pointer address is at this memory location. + try self.genSetReg(src, reg, .{ .immediate = addr }); + mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .rn = reg }).toU32()); + } }, else => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}), }, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 20d9c3e78e..b6f5cb9ce8 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -7,6 +7,7 @@ const fs = std.fs; const log = std.log.scoped(.link); const macho = std.macho; const codegen = @import("../codegen.zig"); +const aarch64 = @import("../codegen/aarch64.zig"); const math = std.math; const mem = std.mem; @@ -1020,9 +1021,15 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { while (decl.link.macho.pie_fixups.popOrNull()) |fixup| { const target_addr = fixup.address; const this_addr = symbol.n_value + fixup.start; - const displacement = @intCast(u32, target_addr - this_addr - fixup.len); - var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; - mem.writeIntSliceLittle(u32, placeholder, displacement); + if (self.base.options.target.cpu.arch == .x86_64) { + const displacement = @intCast(u32, target_addr - this_addr - fixup.len); + var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; + mem.writeIntSliceLittle(u32, placeholder, displacement); + } else { + const displacement = @intCast(u27, target_addr - this_addr); + var placeholder = code_buffer.items[fixup.start..][0..fixup.len]; + mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.bl(@intCast(i28, displacement)).toU32()); + } } const text_section = self.sections.items[self.text_section_index.?]; @@ -1646,22 +1653,28 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u16) u64 { fn writeOffsetTableEntry(self: *MachO, index: usize) !void { const sect = &self.sections.items[self.got_section_index.?]; - const endian = self.base.options.target.cpu.arch.endian(); - const off = sect.offset + @sizeOf(u64) * index; const vmaddr = sect.addr + @sizeOf(u64) * index; - const pos_symbol_off = @truncate(u31, vmaddr - self.offset_table.items[index] + 7); - const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1); var code: [8]u8 = undefined; - // lea %rax, [rip - disp] - code[0] = 0x48; - code[1] = 0x8D; - code[2] = 0x5; - mem.writeInt(u32, code[3..7], symbol_off, endian); - // ret - code[7] = 0xC3; - + if (self.base.options.target.cpu.arch == .x86_64) { + const pos_symbol_off = @intCast(u31, vmaddr - self.offset_table.items[index] + 7); + const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1); + // lea %rax, [rip - disp] + code[0] = 0x48; + code[1] = 0x8D; + code[2] = 0x5; + mem.writeIntLittle(u32, code[3..7], symbol_off); + // ret + code[7] = 0xC3; + } else { + const pos_symbol_off = @intCast(u20, vmaddr - self.offset_table.items[index]); + const symbol_off = @intCast(i21, pos_symbol_off) * -1; + // adr .x0 [-disp] + mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x1, symbol_off).toU32()); + // ret + mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ret(null).toU32()); + } log.debug("writing offset table entry 0x{x} at 0x{x}\n", .{ self.offset_table.items[index], off }); try self.base.file.?.pwriteAll(&code, off); }