aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgracefu <81774659+gracefuu@users.noreply.github.com>2021-04-11 16:41:49 +0800
committergracefu <81774659+gracefuu@users.noreply.github.com>2021-04-16 15:21:17 +0800
commitb004c3da159645cf4a3387f808ab3e8a6277ba2f (patch)
treeb8657e250daa840659c573a61948cdd8a230cdcf /src
parent0409f9e0244aebab5c47f0ec24114e101c3f54e6 (diff)
downloadzig-b004c3da159645cf4a3387f808ab3e8a6277ba2f.tar.gz
zig-b004c3da159645cf4a3387f808ab3e8a6277ba2f.zip
stage2 x86_64: try to fix RIP-relative offset to GOT for macho
Diffstat (limited to 'src')
-rw-r--r--src/codegen.zig31
1 files changed, 17 insertions, 14 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 27a60597d4..e24d197d54 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -3860,32 +3860,35 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.memory => |x| {
if (self.bin_file.options.pie) {
// RIP-relative displacement to the entry in the GOT table.
+ const abi_size = ty.abiSize(self.target.*);
+ const encoder = try X8664Encoder.init(self.code, 7);
+
+ // LEA reg, [<offset>]
+
+ // We encode the instruction FIRST because prefixes may or may not appear.
+ // After we encode the instruction, we will know that the displacement bytes
+ // for [<offset>] will be at self.code.items.len - 4.
+ encoder.rex(.{
+ .w = abi_size == 64,
+ .r = reg.isExtended(),
+ });
+ encoder.opcode_1byte(0x8D);
+ encoder.modRm_RIPDisp32(reg.low_id());
+ encoder.disp32(0);
+
// TODO we should come up with our own, backend independent relocation types
// which each backend (Elf, MachO, etc.) would then translate into an actual
// fixup when linking.
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
try macho_file.pie_fixups.append(self.bin_file.allocator, .{
.target_addr = x,
- .offset = self.code.items.len + 3,
+ .offset = self.code.items.len - 4,
.size = 4,
});
} else {
return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{});
}
- const abi_size = ty.abiSize(self.target.*);
- const encoder = try X8664Encoder.init(self.code, 7);
- // LEA reg, [<offset>]
- // TODO: Check if this breaks on macho if abi_size != 64 and reg is not extended
- // this causes rex byte to be omitted, which might mean the offset (+3) above is wrong.
- encoder.rex(.{
- .w = abi_size == 64,
- .r = reg.isExtended(),
- });
- encoder.opcode_1byte(0x8D);
- encoder.modRm_RIPDisp32(reg.low_id());
- encoder.disp32(0);
-
// MOV reg, [reg]
encoder.rex(.{
.w = abi_size == 64,