Commit 53a9661c1a

Jakub Konka <kubkon@jakubkonka.com>
2022-11-04 13:29:05
coff: generate relocations for branch, GOT, direct refs
1 parent 62ae365
Changed files (2)
src
arch
aarch64
link
src/arch/aarch64/Emit.zig
@@ -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", .{});
     }
src/link/Coff.zig
@@ -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) {