| author | |
| committer | |
| log | 5ed76268c9f0ecca8c5d62cb7e56da05aa8f1f7c |
| tree | 6f8e91dd2bef0543d309003e7447c96df127f127 |
| parent | 02baaac506d0d64d1c946219335b7492222c4b64 |
2 files changed, 70 insertions(+), 46 deletions(-)
src/codegen.zig+37-21| ... | ... | @@ -2601,11 +2601,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2601 | 2601 | }).toU32()); |
| 2602 | 2602 | // adr x28, #8 |
| 2603 | 2603 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); |
| 2604 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2605 | .address = addr, | |
| 2606 | .start = self.code.items.len, | |
| 2607 | .len = 4, | |
| 2608 | }); | |
| 2604 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 2605 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2606 | .address = addr, | |
| 2607 | .start = self.code.items.len, | |
| 2608 | .len = 4, | |
| 2609 | }); | |
| 2610 | } else { | |
| 2611 | return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); | |
| 2612 | } | |
| 2609 | 2613 | // b [label] |
| 2610 | 2614 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); |
| 2611 | 2615 | // mov r, x0 |
| ... | ... | @@ -2626,11 +2630,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2626 | 2630 | }).toU32()); |
| 2627 | 2631 | // adr x28, #8 |
| 2628 | 2632 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); |
| 2629 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2630 | .address = addr, | |
| 2631 | .start = self.code.items.len, | |
| 2632 | .len = 4, | |
| 2633 | }); | |
| 2633 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 2634 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2635 | .address = addr, | |
| 2636 | .start = self.code.items.len, | |
| 2637 | .len = 4, | |
| 2638 | }); | |
| 2639 | } else { | |
| 2640 | return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); | |
| 2641 | } | |
| 2634 | 2642 | // b [label] |
| 2635 | 2643 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); |
| 2636 | 2644 | // mov r, x0 |
| ... | ... | @@ -2828,7 +2836,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2828 | 2836 | self.code.appendSliceAssumeCapacity(&[_]u8{ 0x8B, R }); |
| 2829 | 2837 | }, |
| 2830 | 2838 | .memory => |x| { |
| 2831 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 2839 | if (self.bin_file.options.pie) { | |
| 2832 | 2840 | // For MachO, the binary, with the exception of object files, has to be a PIE. |
| 2833 | 2841 | // Therefore, we cannot load an absolute address. |
| 2834 | 2842 | 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 { |
| 2838 | 2846 | // later in the linker. |
| 2839 | 2847 | if (reg.id() == 0) { // %rax is special-cased |
| 2840 | 2848 | try self.code.ensureCapacity(self.code.items.len + 5); |
| 2841 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2842 | .address = x, | |
| 2843 | .start = self.code.items.len, | |
| 2844 | .len = 5, | |
| 2845 | }); | |
| 2849 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 2850 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2851 | .address = x, | |
| 2852 | .start = self.code.items.len, | |
| 2853 | .len = 5, | |
| 2854 | }); | |
| 2855 | } else { | |
| 2856 | return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); | |
| 2857 | } | |
| 2846 | 2858 | // call [label] |
| 2847 | 2859 | self.code.appendSliceAssumeCapacity(&[_]u8{ |
| 2848 | 2860 | 0xE8, |
| ... | ... | @@ -2855,11 +2867,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2855 | 2867 | try self.code.ensureCapacity(self.code.items.len + 10); |
| 2856 | 2868 | // push %rax |
| 2857 | 2869 | self.code.appendSliceAssumeCapacity(&[_]u8{0x50}); |
| 2858 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2859 | .address = x, | |
| 2860 | .start = self.code.items.len, | |
| 2861 | .len = 5, | |
| 2862 | }); | |
| 2870 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 2871 | try macho_file.pie_fixups.append(self.bin_file.allocator, .{ | |
| 2872 | .address = x, | |
| 2873 | .start = self.code.items.len, | |
| 2874 | .len = 5, | |
| 2875 | }); | |
| 2876 | } else { | |
| 2877 | return self.fail(src, "TODO implement genSetReg for PIE on this platform", .{}); | |
| 2878 | } | |
| 2863 | 2879 | // call [label] |
| 2864 | 2880 | self.code.appendSliceAssumeCapacity(&[_]u8{ |
| 2865 | 2881 | 0xE8, |
src/link/MachO.zig+33-25| ... | ... | @@ -1015,14 +1015,18 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1015 | 1015 | while (self.pie_fixups.popOrNull()) |fixup| { |
| 1016 | 1016 | const target_addr = fixup.address; |
| 1017 | 1017 | const this_addr = symbol.n_value + fixup.start; |
| 1018 | if (self.base.options.target.cpu.arch == .x86_64) { | |
| 1019 | const displacement = @intCast(u32, target_addr - this_addr - fixup.len); | |
| 1020 | var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; | |
| 1021 | mem.writeIntSliceLittle(u32, placeholder, displacement); | |
| 1022 | } else { | |
| 1023 | const displacement = @intCast(u27, target_addr - this_addr); | |
| 1024 | var placeholder = code_buffer.items[fixup.start..][0..fixup.len]; | |
| 1025 | mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.b(@intCast(i28, displacement)).toU32()); | |
| 1018 | switch (self.base.options.target.cpu.arch) { | |
| 1019 | .x86_64 => { | |
| 1020 | const displacement = @intCast(u32, target_addr - this_addr - fixup.len); | |
| 1021 | var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; | |
| 1022 | mem.writeIntSliceLittle(u32, placeholder, displacement); | |
| 1023 | }, | |
| 1024 | .aarch64 => { | |
| 1025 | const displacement = @intCast(u27, target_addr - this_addr); | |
| 1026 | var placeholder = code_buffer.items[fixup.start..][0..fixup.len]; | |
| 1027 | mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.b(@intCast(i28, displacement)).toU32()); | |
| 1028 | }, | |
| 1029 | else => unreachable, // unsupported target architecture | |
| 1026 | 1030 | } |
| 1027 | 1031 | } |
| 1028 | 1032 | |
| ... | ... | @@ -1651,23 +1655,27 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void { |
| 1651 | 1655 | const vmaddr = sect.addr + @sizeOf(u64) * index; |
| 1652 | 1656 | |
| 1653 | 1657 | var code: [8]u8 = undefined; |
| 1654 | if (self.base.options.target.cpu.arch == .x86_64) { | |
| 1655 | const pos_symbol_off = @intCast(u31, vmaddr - self.offset_table.items[index] + 7); | |
| 1656 | const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1); | |
| 1657 | // lea %rax, [rip - disp] | |
| 1658 | code[0] = 0x48; | |
| 1659 | code[1] = 0x8D; | |
| 1660 | code[2] = 0x5; | |
| 1661 | mem.writeIntLittle(u32, code[3..7], symbol_off); | |
| 1662 | // ret | |
| 1663 | code[7] = 0xC3; | |
| 1664 | } else { | |
| 1665 | const pos_symbol_off = @intCast(u20, vmaddr - self.offset_table.items[index]); | |
| 1666 | const symbol_off = @intCast(i21, pos_symbol_off) * -1; | |
| 1667 | // adr x0, #-disp | |
| 1668 | mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x0, symbol_off).toU32()); | |
| 1669 | // ret x28 | |
| 1670 | mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ret(.x28).toU32()); | |
| 1658 | switch (self.base.options.target.cpu.arch) { | |
| 1659 | .x86_64 => { | |
| 1660 | const pos_symbol_off = @intCast(u31, vmaddr - self.offset_table.items[index] + 7); | |
| 1661 | const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1); | |
| 1662 | // lea %rax, [rip - disp] | |
| 1663 | code[0] = 0x48; | |
| 1664 | code[1] = 0x8D; | |
| 1665 | code[2] = 0x5; | |
| 1666 | mem.writeIntLittle(u32, code[3..7], symbol_off); | |
| 1667 | // ret | |
| 1668 | code[7] = 0xC3; | |
| 1669 | }, | |
| 1670 | .aarch64 => { | |
| 1671 | const pos_symbol_off = @intCast(u20, vmaddr - self.offset_table.items[index]); | |
| 1672 | const symbol_off = @intCast(i21, pos_symbol_off) * -1; | |
| 1673 | // adr x0, #-disp | |
| 1674 | mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x0, symbol_off).toU32()); | |
| 1675 | // ret x28 | |
| 1676 | mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ret(.x28).toU32()); | |
| 1677 | }, | |
| 1678 | else => unreachable, // unsupported target architecture | |
| 1671 | 1679 | } |
| 1672 | 1680 | log.debug("writing offset table entry 0x{x} at 0x{x}\n", .{ self.offset_table.items[index], off }); |
| 1673 | 1681 | try self.base.file.?.pwriteAll(&code, off); |