Commit b004c3da15

gracefu <81774659+gracefuu@users.noreply.github.com>
2021-04-11 10:41:49
stage2 x86_64: try to fix RIP-relative offset to GOT for macho
1 parent 0409f9e
Changed files (1)
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,