mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
macho: add relocations for GOT cells
in self-hosted compiler.
This commit is contained in:
parent
3bfde76cff
commit
845c906e6a
@ -2506,7 +2506,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
}) orelse unreachable;
|
||||
break :blk got.addr + got_index * @sizeOf(u64);
|
||||
};
|
||||
log.debug("got_addr = 0x{x}", .{got_addr});
|
||||
switch (arch) {
|
||||
.x86_64 => {
|
||||
try self.genSetReg(inst.base.src, Type.initTag(.u64), .rax, .{ .memory = got_addr });
|
||||
@ -3864,19 +3863,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
.memory => |addr| {
|
||||
if (self.bin_file.options.pie) {
|
||||
// PC-relative displacement to the entry in the GOT table.
|
||||
// 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.
|
||||
// adrp reg, pages
|
||||
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try macho_file.pie_fixups.append(self.bin_file.allocator, .{
|
||||
.target_addr = addr,
|
||||
.offset = self.code.items.len,
|
||||
.size = 4,
|
||||
});
|
||||
} else {
|
||||
return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{});
|
||||
}
|
||||
// adrp
|
||||
const offset = @intCast(u32, self.code.items.len);
|
||||
mem.writeIntLittle(
|
||||
u32,
|
||||
try self.code.addManyAsArray(4),
|
||||
@ -3889,6 +3877,26 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
.offset = Instruction.LoadStoreOffset.imm(0),
|
||||
},
|
||||
}).toU32());
|
||||
|
||||
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const decl = macho_file.active_decl.?;
|
||||
// Page reloc for adrp instruction.
|
||||
try decl.link.macho.relocs.append(self.bin_file.allocator, .{
|
||||
.offset = offset,
|
||||
.where = .local,
|
||||
.where_index = decl.link.macho.local_sym_index,
|
||||
.payload = .{ .page = .{ .kind = .got } },
|
||||
});
|
||||
// Pageoff reloc for adrp instruction.
|
||||
try decl.link.macho.relocs.append(self.bin_file.allocator, .{
|
||||
.offset = offset + 4,
|
||||
.where = .local,
|
||||
.where_index = decl.link.macho.local_sym_index,
|
||||
.payload = .{ .page_off = .{ .kind = .got } },
|
||||
});
|
||||
} else {
|
||||
return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{});
|
||||
}
|
||||
} else {
|
||||
// The value is in memory at a hard-coded address.
|
||||
// If the type is a pointer, it means the pointer address is at this memory location.
|
||||
@ -4128,6 +4136,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
const abi_size = ty.abiSize(self.target.*);
|
||||
const encoder = try X8664Encoder.init(self.code, 10);
|
||||
|
||||
const offset = @intCast(u32, self.code.items.len);
|
||||
// LEA reg, [<offset>]
|
||||
|
||||
// We encode the instruction FIRST because prefixes may or may not appear.
|
||||
@ -4141,14 +4150,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
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 - 4,
|
||||
.size = 4,
|
||||
const decl = macho_file.active_decl.?;
|
||||
// Load reloc for LEA instruction.
|
||||
try decl.link.macho.relocs.append(self.bin_file.allocator, .{
|
||||
.offset = offset,
|
||||
.where = .local,
|
||||
.where_index = decl.link.macho.local_sym_index,
|
||||
.payload = .{ .load = .{ .kind = .got } },
|
||||
});
|
||||
} else {
|
||||
return self.fail(src, "TODO implement genSetReg for PIE GOT indirection on this platform", .{});
|
||||
|
||||
@ -203,14 +203,11 @@ blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{},
|
||||
/// TODO consolidate this.
|
||||
decls: std.ArrayListUnmanaged(*Module.Decl) = .{},
|
||||
|
||||
/// A list of all PIE fixups required for this run of the linker.
|
||||
/// Warning, this is currently NOT thread-safe. See the TODO below.
|
||||
/// TODO Move this list inside `updateDecl` where it should be allocated
|
||||
/// prior to calling `generateSymbol`, and then immediately deallocated
|
||||
/// rather than sitting in the global scope.
|
||||
/// TODO We should also rewrite this using generic relocations common to all
|
||||
/// backends.
|
||||
pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{},
|
||||
/// Currently active Module.Decl.
|
||||
/// TODO this might not be necessary if we figure out how to pass Module.Decl instance
|
||||
/// to codegen.genSetReg() or alterntively move PIE displacement for MCValue{ .memory = x }
|
||||
/// somewhere else in the codegen.
|
||||
active_decl: ?*Module.Decl = null,
|
||||
|
||||
const StringIndexContext = struct {
|
||||
strtab: *std.ArrayListUnmanaged(u8),
|
||||
@ -3279,7 +3276,6 @@ pub fn deinit(self: *MachO) void {
|
||||
}
|
||||
|
||||
self.pending_updates.deinit(self.base.allocator);
|
||||
self.pie_fixups.deinit(self.base.allocator);
|
||||
self.got_entries.deinit(self.base.allocator);
|
||||
self.got_entries_map.deinit(self.base.allocator);
|
||||
self.got_entries_free_list.deinit(self.base.allocator);
|
||||
@ -3497,6 +3493,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
}
|
||||
}
|
||||
|
||||
self.active_decl = decl;
|
||||
|
||||
const res = if (debug_buffers) |*dbg|
|
||||
try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
|
||||
.ty = decl.ty,
|
||||
@ -3522,8 +3520,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
break :blk decl.link.macho.code;
|
||||
},
|
||||
.fail => |em| {
|
||||
// Clear any PIE fixups for this decl.
|
||||
self.pie_fixups.shrinkRetainingCapacity(0);
|
||||
decl.analysis = .codegen_failure;
|
||||
try module.failed_decls.put(module.gpa, decl, em);
|
||||
return;
|
||||
@ -3600,46 +3596,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
try self.writeGotEntry(got_index);
|
||||
}
|
||||
|
||||
// Calculate displacements to target addr (if any).
|
||||
while (self.pie_fixups.popOrNull()) |fixup| {
|
||||
assert(fixup.size == 4);
|
||||
const this_addr = symbol.n_value + fixup.offset;
|
||||
const target_addr = fixup.target_addr;
|
||||
|
||||
switch (self.base.options.target.cpu.arch) {
|
||||
.x86_64 => {
|
||||
const displacement = try math.cast(u32, target_addr - this_addr - 4);
|
||||
mem.writeIntLittle(u32, decl.link.macho.code[fixup.offset..][0..4], displacement);
|
||||
},
|
||||
.aarch64 => {
|
||||
// TODO optimize instruction based on jump length (use ldr(literal) + nop if possible).
|
||||
{
|
||||
const inst = decl.link.macho.code[fixup.offset..][0..4];
|
||||
var parsed = mem.bytesAsValue(meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.pc_relative_address,
|
||||
), inst);
|
||||
const this_page = @intCast(i32, this_addr >> 12);
|
||||
const target_page = @intCast(i32, target_addr >> 12);
|
||||
const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
|
||||
parsed.immhi = @truncate(u19, pages >> 2);
|
||||
parsed.immlo = @truncate(u2, pages);
|
||||
}
|
||||
{
|
||||
const inst = decl.link.macho.code[fixup.offset + 4 ..][0..4];
|
||||
var parsed = mem.bytesAsValue(meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.load_store_register,
|
||||
), inst);
|
||||
const narrowed = @truncate(u12, target_addr);
|
||||
const offset = try math.divExact(u12, narrowed, 8);
|
||||
parsed.offset = offset;
|
||||
}
|
||||
},
|
||||
else => unreachable, // unsupported target architecture
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve relocations
|
||||
try decl.link.macho.resolveRelocs(self);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user