| ... | ... | @@ -2523,21 +2523,25 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2523 | 2523 | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 2524 | 2524 | const decl = func_payload.data; |
| 2525 | 2525 | const where_index = try macho_file.addExternFn(mem.spanZ(decl.name)); |
| 2526 | | const offset = @intCast(u32, self.code.items.len); |
| 2527 | | switch (arch) { |
| 2528 | | .x86_64 => { |
| 2529 | | // callq |
| 2530 | | try self.code.ensureCapacity(self.code.items.len + 5); |
| 2531 | | self.code.appendSliceAssumeCapacity(&[5]u8{ 0xe8, 0x0, 0x0, 0x0, 0x0 }); |
| 2532 | | }, |
| 2533 | | .aarch64 => { |
| 2534 | | // bl |
| 2535 | | writeInt(u32, try self.code.addManyAsArray(4), Instruction.bl(0).toU32()); |
| 2536 | | }, |
| 2537 | | else => unreachable, // unsupported architecture on MachO |
| 2538 | | } |
| 2526 | const offset = blk: { |
| 2527 | switch (arch) { |
| 2528 | .x86_64 => { |
| 2529 | // callq |
| 2530 | try self.code.ensureCapacity(self.code.items.len + 5); |
| 2531 | self.code.appendSliceAssumeCapacity(&[5]u8{ 0xe8, 0x0, 0x0, 0x0, 0x0 }); |
| 2532 | break :blk @intCast(u32, self.code.items.len) - 4; |
| 2533 | }, |
| 2534 | .aarch64 => { |
| 2535 | const offset = @intCast(u32, self.code.items.len); |
| 2536 | // bl |
| 2537 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.bl(0).toU32()); |
| 2538 | break :blk offset; |
| 2539 | }, |
| 2540 | else => unreachable, // unsupported architecture on MachO |
| 2541 | } |
| 2542 | }; |
| 2539 | 2543 | // Add relocation to the decl. |
| 2540 | | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ |
| 2544 | try macho_file.active_decl.?.link.macho.relocs.append(self.bin_file.allocator, .{ |
| 2541 | 2545 | .offset = offset, |
| 2542 | 2546 | .where = .import, |
| 2543 | 2547 | .where_index = where_index, |
| ... | ... | @@ -3879,19 +3883,29 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3879 | 3883 | }).toU32()); |
| 3880 | 3884 | |
| 3881 | 3885 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 3886 | // TODO this is super awkward. We are reversing the address of the GOT entry here. |
| 3887 | // We should probably have it cached or move the reloc adding somewhere else. |
| 3888 | const got_addr = blk: { |
| 3889 | const seg = macho_file.load_commands.items[macho_file.data_const_segment_cmd_index.?].Segment; |
| 3890 | const got = seg.sections.items[macho_file.got_section_index.?]; |
| 3891 | break :blk got.addr; |
| 3892 | }; |
| 3893 | const where_index = blk: for (macho_file.got_entries.items) |key, id| { |
| 3894 | if (got_addr + id * @sizeOf(u64) == addr) break :blk key.where_index; |
| 3895 | } else unreachable; |
| 3882 | 3896 | const decl = macho_file.active_decl.?; |
| 3883 | 3897 | // Page reloc for adrp instruction. |
| 3884 | 3898 | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ |
| 3885 | 3899 | .offset = offset, |
| 3886 | 3900 | .where = .local, |
| 3887 | | .where_index = decl.link.macho.local_sym_index, |
| 3901 | .where_index = where_index, |
| 3888 | 3902 | .payload = .{ .page = .{ .kind = .got } }, |
| 3889 | 3903 | }); |
| 3890 | 3904 | // Pageoff reloc for adrp instruction. |
| 3891 | 3905 | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ |
| 3892 | 3906 | .offset = offset + 4, |
| 3893 | 3907 | .where = .local, |
| 3894 | | .where_index = decl.link.macho.local_sym_index, |
| 3908 | .where_index = where_index, |
| 3895 | 3909 | .payload = .{ .page_off = .{ .kind = .got } }, |
| 3896 | 3910 | }); |
| 3897 | 3911 | } else { |
| ... | ... | @@ -4136,7 +4150,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4136 | 4150 | const abi_size = ty.abiSize(self.target.*); |
| 4137 | 4151 | const encoder = try X8664Encoder.init(self.code, 10); |
| 4138 | 4152 | |
| 4139 | | const offset = @intCast(u32, self.code.items.len); |
| 4140 | 4153 | // LEA reg, [<offset>] |
| 4141 | 4154 | |
| 4142 | 4155 | // We encode the instruction FIRST because prefixes may or may not appear. |
| ... | ... | @@ -4150,13 +4163,25 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4150 | 4163 | encoder.modRm_RIPDisp32(reg.low_id()); |
| 4151 | 4164 | encoder.disp32(0); |
| 4152 | 4165 | |
| 4166 | const offset = @intCast(u32, self.code.items.len); |
| 4167 | |
| 4153 | 4168 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4169 | // TODO this is super awkward. We are reversing the address of the GOT entry here. |
| 4170 | // We should probably have it cached or move the reloc adding somewhere else. |
| 4171 | const got_addr = blk: { |
| 4172 | const seg = macho_file.load_commands.items[macho_file.data_const_segment_cmd_index.?].Segment; |
| 4173 | const got = seg.sections.items[macho_file.got_section_index.?]; |
| 4174 | break :blk got.addr; |
| 4175 | }; |
| 4176 | const where_index = blk: for (macho_file.got_entries.items) |key, id| { |
| 4177 | if (got_addr + id * @sizeOf(u64) == x) break :blk key.where_index; |
| 4178 | } else unreachable; |
| 4154 | 4179 | const decl = macho_file.active_decl.?; |
| 4155 | 4180 | // Load reloc for LEA instruction. |
| 4156 | 4181 | try decl.link.macho.relocs.append(self.bin_file.allocator, .{ |
| 4157 | | .offset = offset, |
| 4182 | .offset = offset - 4, |
| 4158 | 4183 | .where = .local, |
| 4159 | | .where_index = decl.link.macho.local_sym_index, |
| 4184 | .where_index = where_index, |
| 4160 | 4185 | .payload = .{ .load = .{ .kind = .got } }, |
| 4161 | 4186 | }); |
| 4162 | 4187 | } else { |