Skip to content

Commit ab741f5

Browse files
committed
link: support basic relocations for LoongArch64
1 parent f4889cb commit ab741f5

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

src/arch/loongarch/bits.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub const Register = enum(u8) {
3636
pub const tp = Register.r2;
3737
pub const sp = Register.r3;
3838
pub const fp = Register.r22;
39+
pub const t0 = Register.r12;
40+
pub const t1 = Register.r13;
41+
pub const t2 = Register.r14;
42+
pub const t3 = Register.r15;
3943

4044
pub const Class = enum {
4145
int,

src/link/Elf/Atom.zig

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
354354
error.RelocFailure => has_reloc_errors = true,
355355
else => |e| return e,
356356
},
357+
.loongarch64, .loongarch32 => loongarch.scanReloc(self, elf_file, rel, symbol, code, &it) catch |err| switch (err) {
358+
error.RelocFailure => has_reloc_errors = true,
359+
else => |e| return e,
360+
},
357361
else => return error.UnsupportedCpuArch,
358362
}
359363
}
@@ -688,6 +692,12 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
688692
=> has_reloc_errors = true,
689693
else => |e| return e,
690694
},
695+
.loongarch64, .loongarch32 => loongarch.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {
696+
error.RelocFailure,
697+
error.RelaxFailure,
698+
=> has_reloc_errors = true,
699+
else => |e| return e,
700+
},
691701
else => return error.UnsupportedCpuArch,
692702
}
693703
}
@@ -878,6 +888,10 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
878888
error.RelocFailure => has_reloc_errors = true,
879889
else => |e| return e,
880890
},
891+
.loongarch64, .loongarch32 => loongarch.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {
892+
error.RelocFailure => has_reloc_errors = true,
893+
else => |e| return e,
894+
},
881895
else => return error.UnsupportedCpuArch,
882896
}
883897
}
@@ -2084,6 +2098,169 @@ const riscv = struct {
20842098
const riscv_util = @import("../riscv.zig");
20852099
};
20862100

2101+
const loongarch = struct {
2102+
fn scanReloc(
2103+
atom: Atom,
2104+
elf_file: *Elf,
2105+
rel: elf.Elf64_Rela,
2106+
symbol: *Symbol,
2107+
code: ?[]const u8,
2108+
it: *RelocsIterator,
2109+
) !void {
2110+
_ = code;
2111+
_ = it;
2112+
2113+
const r_type: elf.R_LARCH = @enumFromInt(rel.r_type());
2114+
const is_dyn_lib = elf_file.isEffectivelyDynLib();
2115+
2116+
switch (r_type) {
2117+
.@"32" => try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file),
2118+
.@"64" => try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file),
2119+
.@"32_PCREL" => try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file),
2120+
.@"64_PCREL" => try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file),
2121+
2122+
.B26, .PCALA_HI20, .CALL36 => if (symbol.flags.import) {
2123+
symbol.flags.needs_plt = true;
2124+
},
2125+
.GOT_HI20, .GOT_PC_HI20 => symbol.flags.needs_got = true,
2126+
.TLS_IE_HI20, .TLS_IE_PC_HI20 => symbol.flags.needs_gottp = true,
2127+
.TLS_GD_PC_HI20, .TLS_LD_PC_HI20, .TLS_GD_HI20, .TLS_LD_HI20 => symbol.flags.needs_tlsgd = true,
2128+
.TLS_DESC_CALL => symbol.flags.needs_tlsdesc = true,
2129+
2130+
.TLS_LE_HI20,
2131+
.TLS_LE_LO12,
2132+
.TLS_LE64_LO20,
2133+
.TLS_LE64_HI12,
2134+
.TLS_LE_HI20_R,
2135+
.TLS_LE_LO12_R,
2136+
=> if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file),
2137+
2138+
.B16,
2139+
.B21,
2140+
.ABS_HI20,
2141+
.ABS_LO12,
2142+
.ABS64_LO20,
2143+
.ABS64_HI12,
2144+
.PCALA_LO12,
2145+
.PCALA64_LO20,
2146+
.PCALA64_HI12,
2147+
.GOT_PC_LO12,
2148+
.GOT64_PC_LO20,
2149+
.GOT64_PC_HI12,
2150+
.GOT_LO12,
2151+
.GOT64_LO20,
2152+
.GOT64_HI12,
2153+
.TLS_IE_PC_LO12,
2154+
.TLS_IE64_PC_LO20,
2155+
.TLS_IE64_PC_HI12,
2156+
.TLS_IE_LO12,
2157+
.TLS_IE64_LO20,
2158+
.TLS_IE64_HI12,
2159+
.ADD6,
2160+
.SUB6,
2161+
.ADD8,
2162+
.SUB8,
2163+
.ADD16,
2164+
.SUB16,
2165+
.ADD32,
2166+
.SUB32,
2167+
.ADD64,
2168+
.SUB64,
2169+
.ADD_ULEB128,
2170+
.SUB_ULEB128,
2171+
.TLS_DESC_PC_HI20,
2172+
.TLS_DESC_PC_LO12,
2173+
.TLS_DESC_LD,
2174+
.TLS_LE_ADD_R,
2175+
=> {},
2176+
2177+
else => try atom.reportUnhandledRelocError(rel, elf_file),
2178+
}
2179+
}
2180+
2181+
fn resolveRelocAlloc(
2182+
atom: Atom,
2183+
elf_file: *Elf,
2184+
rel: elf.Elf64_Rela,
2185+
target: *const Symbol,
2186+
args: ResolveArgs,
2187+
it: *RelocsIterator,
2188+
code: []u8,
2189+
stream: anytype,
2190+
) !void {
2191+
const diags = &elf_file.base.comp.link_diags;
2192+
const r_type: elf.R_LARCH = @enumFromInt(rel.r_type());
2193+
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
2194+
const cwriter = stream.writer();
2195+
2196+
const P, const A, const S, const GOT, const G, const TP, const DTP = args;
2197+
_ = TP;
2198+
_ = DTP;
2199+
_ = P;
2200+
_ = GOT;
2201+
_ = G;
2202+
_ = r_offset;
2203+
_ = diags;
2204+
_ = it;
2205+
_ = code;
2206+
2207+
switch (r_type) {
2208+
.NONE => unreachable,
2209+
2210+
.@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
2211+
2212+
.@"64" => {
2213+
try atom.resolveDynAbsReloc(
2214+
target,
2215+
rel,
2216+
dynAbsRelocAction(target, elf_file),
2217+
elf_file,
2218+
cwriter,
2219+
);
2220+
},
2221+
2222+
else => try atom.reportUnhandledRelocError(rel, elf_file),
2223+
}
2224+
}
2225+
2226+
fn resolveRelocNonAlloc(
2227+
atom: Atom,
2228+
elf_file: *Elf,
2229+
rel: elf.Elf64_Rela,
2230+
target: *const Symbol,
2231+
args: ResolveArgs,
2232+
it: *RelocsIterator,
2233+
code: []u8,
2234+
stream: anytype,
2235+
) !void {
2236+
_ = it;
2237+
2238+
const r_type: elf.R_LARCH = @enumFromInt(rel.r_type());
2239+
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
2240+
const cwriter = stream.writer();
2241+
2242+
_, const A, const S, const GOT, _, _, const DTP = args;
2243+
_ = GOT;
2244+
_ = DTP;
2245+
_ = r_offset;
2246+
_ = code;
2247+
2248+
switch (r_type) {
2249+
.NONE => unreachable,
2250+
2251+
.@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),
2252+
.@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
2253+
try cwriter.writeInt(u64, value, .little)
2254+
else
2255+
try cwriter.writeInt(i64, S + A, .little),
2256+
2257+
else => try atom.reportUnhandledRelocError(rel, elf_file),
2258+
}
2259+
}
2260+
2261+
const la_util = @import("../loongarch.zig");
2262+
};
2263+
20872264
const ResolveArgs = struct { i64, i64, i64, i64, i64, i64, i64 };
20882265

20892266
const RelocError = error{

0 commit comments

Comments
 (0)