diff --git a/src/codegen.zig b/src/codegen.zig index 8bd08af15c..74800aa22e 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -2601,11 +2601,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }).toU32()); // adr x28, #8 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); - try macho_file.pie_fixups.append(self.bin_file.allocator, .{ - .address = addr, - .start = self.code.items.len, - .len = 4, - }); + if (self.bin_file.cast(link.File.MachO)) |macho_file| { + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ + .address = addr, + .start = self.code.items.len, + .len = 4, + }); + } else { + return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); + } // b [label] mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); // mov r, x0 @@ -2626,11 +2630,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }).toU32()); // adr x28, #8 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); - try macho_file.pie_fixups.append(self.bin_file.allocator, .{ - .address = addr, - .start = self.code.items.len, - .len = 4, - }); + if (self.bin_file.cast(link.File.MachO)) |macho_file| { + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ + .address = addr, + .start = self.code.items.len, + .len = 4, + }); + } else { + return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); + } // b [label] mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); // mov r, x0 @@ -2828,7 +2836,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { self.code.appendSliceAssumeCapacity(&[_]u8{ 0x8B, R }); }, .memory => |x| { - if (self.bin_file.cast(link.File.MachO)) |macho_file| { + if (self.bin_file.options.pie) { // For MachO, the binary, with the exception of object files, has to be a PIE. // Therefore, we cannot load an absolute address. assert(x > math.maxInt(u32)); // 32bit direct addressing is not supported by MachO. @@ -2838,11 +2846,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // later in the linker. if (reg.id() == 0) { // %rax is special-cased try self.code.ensureCapacity(self.code.items.len + 5); - try macho_file.pie_fixups.append(self.bin_file.allocator, .{ - .address = x, - .start = self.code.items.len, - .len = 5, - }); + if (self.bin_file.cast(link.File.MachO)) |macho_file| { + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ + .address = x, + .start = self.code.items.len, + .len = 5, + }); + } else { + return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); + } // call [label] self.code.appendSliceAssumeCapacity(&[_]u8{ 0xE8, @@ -2855,11 +2867,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { try self.code.ensureCapacity(self.code.items.len + 10); // push %rax self.code.appendSliceAssumeCapacity(&[_]u8{0x50}); - try macho_file.pie_fixups.append(self.bin_file.allocator, .{ - .address = x, - .start = self.code.items.len, - .len = 5, - }); + if (self.bin_file.cast(link.File.MachO)) |macho_file| { + try macho_file.pie_fixups.append(self.bin_file.allocator, .{ + .address = x, + .start = self.code.items.len, + .len = 5, + }); + } else { + return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); + } // call [label] self.code.appendSliceAssumeCapacity(&[_]u8{ 0xE8, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index e66b6ab413..d2a03cae18 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1015,14 +1015,18 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { while (self.pie_fixups.popOrNull()) |fixup| { const target_addr = fixup.address; const this_addr = symbol.n_value + fixup.start; - 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.b(@intCast(i28, displacement)).toU32()); + switch (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); + }, + .aarch64 => { + const displacement = @intCast(u27, target_addr - this_addr); + var placeholder = code_buffer.items[fixup.start..][0..fixup.len]; + mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.b(@intCast(i28, displacement)).toU32()); + }, + else => unreachable, // unsupported target architecture } } @@ -1651,23 +1655,27 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void { const vmaddr = sect.addr + @sizeOf(u64) * index; var code: [8]u8 = undefined; - 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(.x0, symbol_off).toU32()); - // ret x28 - mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ret(.x28).toU32()); + switch (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; + }, + .aarch64 => { + 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(.x0, symbol_off).toU32()); + // ret x28 + mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ret(.x28).toU32()); + }, + else => unreachable, // unsupported target architecture } 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);