Commit 9c7aade488

David Rubin <daviru007@icloud.com>
2024-07-31 20:43:47
riscv: fix `.got` symbol loading
1 parent 0008934
Changed files (4)
src
src/arch/riscv64/Emit.zig
@@ -63,6 +63,9 @@ pub fn emitMir(emit: *Emit) Error!void {
 
                         hi_r_type = Elf.R_ZIG_GOT_HI20;
                         lo_r_type = Elf.R_ZIG_GOT_LO12;
+                    } else if (sym.flags.needs_got) {
+                        hi_r_type = Elf.R_GOT_HI20_STATIC; // TODO: rework this #20887
+                        lo_r_type = Elf.R_GOT_LO12_I_STATIC; // TODO: rework this #20887
                     }
 
                     try atom_ptr.addReloc(elf_file, .{
src/link/Elf/Atom.zig
@@ -2016,6 +2016,10 @@ const riscv = struct {
                     assert(symbol.flags.has_zig_got);
                 },
 
+                Elf.R_GOT_HI20_STATIC,
+                Elf.R_GOT_LO12_I_STATIC,
+                => symbol.flags.needs_got = true,
+
                 else => try atom.reportUnhandledRelocError(rel, elf_file),
             },
         }
@@ -2161,16 +2165,28 @@ const riscv = struct {
                 // Zig custom relocations
                 Elf.R_ZIG_GOT_HI20 => {
                     assert(target.flags.has_zig_got);
-                    const disp: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow);
+                    const disp: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow);
                     riscv_util.writeInstU(code[r_offset..][0..4], disp);
                 },
 
                 Elf.R_ZIG_GOT_LO12 => {
                     assert(target.flags.has_zig_got);
-                    const value: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow);
+                    const value: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow);
                     riscv_util.writeInstI(code[r_offset..][0..4], value);
                 },
 
+                Elf.R_GOT_HI20_STATIC => {
+                    assert(target.flags.has_got);
+                    const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow);
+                    riscv_util.writeInstU(code[r_offset..][0..4], disp);
+                },
+
+                Elf.R_GOT_LO12_I_STATIC => {
+                    assert(target.flags.has_got);
+                    const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow);
+                    riscv_util.writeInstI(code[r_offset..][0..4], disp);
+                },
+
                 else => try atom.reportUnhandledRelocError(rel, elf_file),
             },
         }
src/link/Elf/relocation.zig
@@ -115,6 +115,10 @@ fn formatRelocType(
     switch (r_type) {
         Elf.R_ZIG_GOT32 => try writer.writeAll("R_ZIG_GOT32"),
         Elf.R_ZIG_GOTPCREL => try writer.writeAll("R_ZIG_GOTPCREL"),
+        Elf.R_ZIG_GOT_HI20 => try writer.writeAll("R_ZIG_GOT_HI20"),
+        Elf.R_ZIG_GOT_LO12 => try writer.writeAll("R_ZIG_GOT_LO12"),
+        Elf.R_GOT_HI20_STATIC => try writer.writeAll("R_GOT_HI20_STATIC"),
+        Elf.R_GOT_LO12_I_STATIC => try writer.writeAll("R_GOT_LO12_I_STATIC"),
         else => switch (ctx.cpu_arch) {
             .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),
             .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}),
src/link/Elf.zig
@@ -6059,11 +6059,40 @@ const RelaSection = struct {
 };
 const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
 
-// TODO: add comptime check we don't clobber any reloc for any ISA
 pub const R_ZIG_GOT32: u32 = 0xff00;
 pub const R_ZIG_GOTPCREL: u32 = 0xff01;
 pub const R_ZIG_GOT_HI20: u32 = 0xff02;
 pub const R_ZIG_GOT_LO12: u32 = 0xff03;
+pub const R_GOT_HI20_STATIC: u32 = 0xff04;
+pub const R_GOT_LO12_I_STATIC: u32 = 0xff05;
+
+// Comptime asserts that no Zig relocs overlap with another ISA's reloc number
+comptime {
+    const zig_relocs = .{
+        R_ZIG_GOT32,
+        R_ZIG_GOT_HI20,
+        R_ZIG_GOT_LO12,
+        R_ZIG_GOTPCREL,
+        R_GOT_HI20_STATIC,
+        R_GOT_LO12_I_STATIC,
+    };
+
+    const other_relocs = .{
+        elf.R_X86_64,
+        elf.R_AARCH64,
+        elf.R_RISCV,
+        elf.R_PPC64,
+    };
+
+    @setEvalBranchQuota(@min(other_relocs.len * zig_relocs.len * 256, 6200));
+    for (other_relocs) |relocs| {
+        for (@typeInfo(relocs).Enum.fields) |reloc| {
+            for (zig_relocs) |zig_reloc| {
+                assert(reloc.value != zig_reloc);
+            }
+        }
+    }
+}
 
 fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
     return switch (cpu_arch) {