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