Commit 845c906e6a
Changed files (2)
src
src/link/MachO.zig
@@ -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);
src/codegen.zig
@@ -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", .{});