coff: generate relocations for branch, GOT, direct refs

This commit is contained in:
Jakub Konka 2022-11-04 13:29:05 +01:00
parent 62ae365308
commit 53a9661c1a
2 changed files with 82 additions and 9 deletions

View File

@ -674,13 +674,14 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
assert(emit.mir.instructions.items(.tag)[inst] == .call_extern);
const relocation = emit.mir.instructions.items(.data)[inst].relocation;
const offset = blk: {
const offset = @intCast(u32, emit.code.items.len);
// bl
try emit.writeInstruction(Instruction.bl(0));
break :blk offset;
};
if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
const offset = blk: {
const offset = @intCast(u32, emit.code.items.len);
// bl
try emit.writeInstruction(Instruction.bl(0));
break :blk offset;
};
// Add relocation to the decl.
const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
const target = macho_file.getGlobalByIndex(relocation.sym_index);
@ -692,8 +693,20 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
.pcrel = true,
.length = 2,
});
} else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
// Add relocation to the decl.
const atom = coff_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
const target = coff_file.getGlobalByIndex(relocation.sym_index);
try atom.addRelocation(coff_file, .{
.@"type" = .branch_26,
.target = target,
.offset = offset,
.addend = 0,
.pcrel = true,
.length = 2,
});
} else {
return emit.fail("Implement call_extern for linking backends != MachO", .{});
return emit.fail("Implement call_extern for linking backends != {{ COFF, MachO }}", .{});
}
}
@ -926,6 +939,40 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
else => unreachable,
},
});
} else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
const atom = coff_file.getAtomForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;
try atom.addRelocation(coff_file, .{
.target = .{ .sym_index = data.sym_index, .file = null },
.offset = offset,
.addend = 0,
.pcrel = true,
.length = 2,
.@"type" = switch (tag) {
.load_memory_got,
.load_memory_ptr_got,
=> .got_page,
.load_memory_direct,
.load_memory_ptr_direct,
=> .page,
else => unreachable,
},
});
try atom.addRelocation(coff_file, .{
.target = .{ .sym_index = data.sym_index, .file = null },
.offset = offset + 4,
.addend = 0,
.pcrel = false,
.length = 2,
.@"type" = switch (tag) {
.load_memory_got,
.load_memory_ptr_got,
=> .got_pageoff,
.load_memory_direct,
.load_memory_ptr_direct,
=> .pageoff,
else => unreachable,
},
});
} else {
return emit.fail("TODO implement load_memory for PIE GOT indirection on this platform", .{});
}

View File

@ -125,9 +125,17 @@ const Entry = struct {
pub const Reloc = struct {
@"type": enum {
// x86, x86_64
got,
direct,
import,
// aarch64
branch_26,
got_page,
got_pageoff,
page,
pageoff,
},
target: SymbolWithLoc,
offset: u32,
@ -139,8 +147,17 @@ pub const Reloc = struct {
/// Returns an Atom which is the target node of this relocation edge (if any).
fn getTargetAtom(self: Reloc, coff_file: *Coff) ?*Atom {
switch (self.@"type") {
.got => return coff_file.getGotAtomForSymbol(self.target),
.direct => return coff_file.getAtomForSymbol(self.target),
.got,
.got_page,
.got_pageoff,
=> return coff_file.getGotAtomForSymbol(self.target),
.direct,
.branch_26,
.page,
.pageoff,
=> return coff_file.getAtomForSymbol(self.target),
.import => return coff_file.getImportAtomForSymbol(self.target),
}
}
@ -878,6 +895,15 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
file_offset + reloc.offset,
});
switch (reloc.@"type") {
.branch_26 => @panic("TODO branch26"),
.got_page => @panic("TODO got_page"),
.got_pageoff => @panic("TODO got_pageoff"),
.page => @panic("TODO page"),
.pageoff => @panic("TODO pageoff"),
else => {},
}
reloc.dirty = false;
if (reloc.pcrel) {