authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-07-06 19:18:39+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-07-09 10:54:47+02:00
loge6ae122839c4939ed4780e32261ea60c2bf9041b
tree24d9f4476793efdfd6a6f25393827a8e95fe49b3
parentf7c11ea389faa3184355af75ebc4f261359f2ab9
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Elf2: implement some generic symbol relocations for sparc


1 files changed, 216 insertions(+), 20 deletions(-)

src/link/Elf2.zig+216-20
......@@ -1132,19 +1132,25 @@ const SymbolReloc = struct {
11321132 /// This is only used targeting local symbols so can always be statically resolved.
11331133 dsorel32,
11341134
1135 abs64,
1135 abs8,
1136 abs16,
11361137 abs32,
11371138 abs32s,
1138 rel64,
1139 abs64,
1140 rel8,
1141 rel16,
11391142 rel32,
1140 pltrel64,
1143 rel64,
1144 pltabs32,
1145 pltabs64,
11411146 pltrel32,
1142 dtpoff64,
1147 pltrel64,
11431148 dtpoff32,
1144 tpoff64,
1149 dtpoff64,
11451150 tpoff32,
1146 size64,
1151 tpoff64,
11471152 size32,
1153 size64,
11481154
11491155 larch_abs32_lo12,
11501156 larch_rel32_hi20,
......@@ -1170,8 +1176,18 @@ const SymbolReloc = struct {
11701176 fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool {
11711177 return switch (elf.identClass()) {
11721178 .NONE, _ => unreachable,
1173 .@"32" => t == .abs32,
1174 .@"64" => t == .abs64,
1179 .@"32" => switch (t) {
1180 .abs32,
1181 .pltabs32,
1182 => true,
1183 else => false,
1184 },
1185 .@"64" => switch (t) {
1186 .abs64,
1187 .pltabs64,
1188 => true,
1189 else => false,
1190 },
11751191 };
11761192 }
11771193 };
......@@ -1190,11 +1206,31 @@ const SymbolReloc = struct {
11901206 .static => unreachable,
11911207 .dynamic => return, // the relocation happens at runtime
11921208 .static_relative => {
1193 assert(reloc.type.isAbsAddr(elf));
11941209 // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc.
11951210 // This is a simplified version of the general relocation handling logic, where we
11961211 // know we're using '.abs64' or '.abs32' (matching the ELF ident class).
1197 const value = reloc.target.value(elf) +% @as(u64, @bitCast(reloc.addend));
1212 const value = type: switch (reloc.type) {
1213 .abs32,
1214 .abs64,
1215 => reloc.target.value(elf) +% @as(u64, @bitCast(reloc.addend)),
1216 .pltabs32,
1217 .pltabs64,
1218 => value: {
1219 const plt_index = switch (reloc.target.unwrap()) {
1220 .local => continue :type .abs32,
1221 .global => |name| elf.plt.getIndex(name) orelse continue :type .abs32,
1222 };
1223 if (elf.pltEntryIsDead(plt_index)) continue :type .abs32;
1224 const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
1225 else => |machine| @panic(@tagName(machine)),
1226 .SPARCV9 => .{ elf.shndx.plt, 4, 32 },
1227 .X86_64 => .{ elf.shndx.plt_sec, 0, 16 },
1228 };
1229 const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size;
1230 break :value plt_entry +% @as(u64, @bitCast(reloc.addend));
1231 },
1232 else => unreachable,
1233 };
11981234 elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value);
11991235 return;
12001236 },
......@@ -1241,6 +1277,13 @@ const SymbolReloc = struct {
12411277 @intCast(@as(i64, @bitCast(target_value))),
12421278 target_endian,
12431279 ),
1280 .abs16 => std.mem.writeInt(
1281 u16,
1282 dest_slice[0..2],
1283 @intCast(target_value),
1284 target_endian,
1285 ),
1286 .abs8 => dest_slice[0] = @intCast(target_value),
12441287 .rel64 => std.mem.writeInt(
12451288 i64,
12461289 dest_slice[0..8],
......@@ -1253,17 +1296,65 @@ const SymbolReloc = struct {
12531296 @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))),
12541297 target_endian,
12551298 ),
1299 .rel16 => std.mem.writeInt(
1300 i16,
1301 dest_slice[0..2],
1302 @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))),
1303 target_endian,
1304 ),
1305 .rel8 => dest_slice[0] = @bitCast(@as(i8, @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))))),
1306 .pltabs64 => {
1307 const plt_index = switch (reloc.target.unwrap()) {
1308 .local => continue :type .abs64,
1309 .global => |name| elf.plt.getIndex(name) orelse continue :type .abs64,
1310 };
1311 if (elf.pltEntryIsDead(plt_index)) continue :type .abs64;
1312 const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
1313 else => |machine| @panic(@tagName(machine)),
1314 .SPARCV9 => .{ elf.shndx.plt, 4, 32 },
1315 .X86_64 => .{ elf.shndx.plt_sec, 0, 16 },
1316 };
1317 const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size;
1318 std.mem.writeInt(
1319 i64,
1320 dest_slice[0..8],
1321 @bitCast(plt_entry +% @as(u64, @bitCast(reloc.addend))),
1322 target_endian,
1323 );
1324 },
1325 .pltabs32 => {
1326 const plt_index = switch (reloc.target.unwrap()) {
1327 .local => continue :type .abs32,
1328 .global => |name| elf.plt.getIndex(name) orelse continue :type .abs32,
1329 };
1330 if (elf.pltEntryIsDead(plt_index)) continue :type .abs32;
1331 const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
1332 else => |machine| @panic(@tagName(machine)),
1333 .SPARCV9 => .{ elf.shndx.plt, 4, 32 },
1334 .X86_64 => .{ elf.shndx.plt_sec, 0, 16 },
1335 };
1336 const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size;
1337 std.mem.writeInt(
1338 i32,
1339 dest_slice[0..4],
1340 @intCast(@as(i64, @bitCast(
1341 plt_entry +% @as(u64, @bitCast(reloc.addend)),
1342 ))),
1343 target_endian,
1344 );
1345 },
12561346 .pltrel64 => {
12571347 const plt_index = switch (reloc.target.unwrap()) {
12581348 .local => continue :type .rel64,
12591349 .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64,
12601350 };
12611351 if (elf.pltEntryIsDead(plt_index)) continue :type .rel64;
1262 const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
1352 const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
12631353 else => |machine| @panic(@tagName(machine)),
1264 .X86_64 => .{ elf.shndx.plt_sec, 16 },
1354 .SPARCV9 => .{ elf.shndx.plt, 4, 32 },
1355 .X86_64 => .{ elf.shndx.plt_sec, 0, 16 },
12651356 };
1266 const plt_entry = plt_shndx.vaddr(elf) +% plt_index * plt_entry_size;
1357 const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size;
12671358 std.mem.writeInt(
12681359 i64,
12691360 dest_slice[0..8],
......@@ -1277,11 +1368,12 @@ const SymbolReloc = struct {
12771368 .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32,
12781369 };
12791370 if (elf.pltEntryIsDead(plt_index)) continue :type .rel32;
1280 const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
1371 const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) {
12811372 else => |machine| @panic(@tagName(machine)),
1282 .X86_64 => .{ elf.shndx.plt_sec, 16 },
1373 .SPARCV9 => .{ elf.shndx.plt, 4, 32 },
1374 .X86_64 => .{ elf.shndx.plt_sec, 0, 16 },
12831375 };
1284 const plt_entry = plt_shndx.vaddr(elf) +% plt_index * plt_entry_size;
1376 const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size;
12851377 std.mem.writeInt(
12861378 i32,
12871379 dest_slice[0..4],
......@@ -6110,11 +6202,69 @@ fn addRelocAssumeCapacity(
61106202 _,
61116203 .NONE,
61126204 .COPY,
6205 .GLOB_DAT,
61136206 .JMP_SLOT,
61146207 .RELATIVE,
61156208 .IRELATIVE,
61166209 => std.debug.panic("TODO: error for illegal or unsupported input relocation, {t}", .{@"type".SPARC}),
61176210
6211 inline .WDISP30,
6212 .WDISP22,
6213 .HI22,
6214 .@"22",
6215 .@"13",
6216 .LO10,
6217 .PC10,
6218 .PC22,
6219 .WPLT30,
6220 .HIPLT22,
6221 .LOPLT10,
6222 .PCPLT22,
6223 .PCPLT10,
6224 .@"10",
6225 .@"11",
6226 .OLO10,
6227 .HH22,
6228 .HM10,
6229 .LM22,
6230 .PC_HH22,
6231 .PC_HM10,
6232 .PC_LM22,
6233 .WDISP16,
6234 .WDISP19,
6235 .@"7",
6236 .@"5",
6237 .@"6",
6238 .HIX22,
6239 .LOX10,
6240 .H44,
6241 .M44,
6242 .L44,
6243 .REGISTER,
6244 .H34,
6245 .WDISP10,
6246 => |t| @panic("TODO: " ++ @tagName(t)),
6247
6248 // Relocations targeting a symbol
6249 .@"8" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs8),
6250 .@"16" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs16),
6251 .@"32" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32),
6252 .DISP8 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel8),
6253 .DISP16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel16),
6254 .DISP32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32),
6255 .UA32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32),
6256 .PLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltabs32),
6257 .PCPLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltrel32),
6258 .@"64" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64),
6259 .DISP64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64),
6260 .PLT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltabs64),
6261 .UA64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64),
6262 .UA16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs16),
6263 .SIZE32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .size32),
6264 .SIZE64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .size64),
6265
6266 // Relocations targeting a TLS symbol
6267
61186268 // Relocations targeting a GOT entry
61196269 .GOT10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_10),
61206270 .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_13),
......@@ -6169,11 +6319,14 @@ fn addSymbolRelocAssumeCapacity(
61696319 },
61706320 .abs64 => .@"64",
61716321 .abs32 => .@"32",
6322 .abs16 => unreachable,
6323 .abs8 => unreachable,
61726324 .abs32s => .@"32S",
61736325 .rel64 => .PC64,
61746326 .rel32 => .PC32,
6175 .pltrel64 => break :r .none,
6176 .pltrel32 => break :r .none,
6327 .rel16 => unreachable,
6328 .rel8 => unreachable,
6329 .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none,
61776330 .dtpoff64 => .DTPOFF64,
61786331 .dtpoff32 => .DTPOFF32,
61796332 .tpoff64 => .TPOFF64,
......@@ -6203,14 +6356,20 @@ fn addSymbolRelocAssumeCapacity(
62036356 },
62046357 .abs64 => .@"64",
62056358 .abs32 => .@"32",
6206 .abs32s, .size64, .size32 => unreachable,
6359 .abs32s => unreachable,
6360 .abs16 => unreachable,
6361 .abs8 => unreachable,
62076362 .rel64 => .@"64_PCREL",
62086363 .rel32 => .@"32_PCREL",
6209 .pltrel64, .pltrel32 => break :r .none,
6364 .rel16 => unreachable,
6365 .rel8 => unreachable,
6366 .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none,
62106367 .dtpoff64 => .TLS_DTPREL64,
62116368 .dtpoff32 => .TLS_DTPREL32,
62126369 .tpoff64 => .TLS_TPREL64,
62136370 .tpoff32 => .TLS_TPREL32,
6371 .size64 => unreachable,
6372 .size32 => unreachable,
62146373
62156374 .larch_abs32_lo12 => .PCALA_LO12,
62166375 .larch_rel32_hi20 => .PCALA_HI20,
......@@ -6225,6 +6384,43 @@ fn addSymbolRelocAssumeCapacity(
62256384 .larch_tpoff64_lo20 => .TLS_LE64_LO20,
62266385 .larch_tpoff64_hi12 => .TLS_LE64_HI12,
62276386 } },
6387 .SPARCV9 => .{ .SPARC = switch (@"type") {
6388 .write_rela => unreachable,
6389 .dsorel64, .dsorel32 => {
6390 assert(target.unwrap() == .local);
6391 break :r .none;
6392 },
6393 .abs64 => .@"64",
6394 .abs32 => .@"32",
6395 .abs32s => unreachable,
6396 .abs16 => .@"16",
6397 .abs8 => .@"8",
6398 .rel64 => .DISP64,
6399 .rel32 => .DISP32,
6400 .rel16 => .DISP16,
6401 .rel8 => .DISP8,
6402 .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none,
6403 .dtpoff64 => @panic("TODO: dtpoff64"),
6404 .dtpoff32 => @panic("TODO: dtpoff32"),
6405 .tpoff64 => @panic("TODO: tpoff64"),
6406 .tpoff32 => @panic("TODO: tpoff32"),
6407 .size64 => .SIZE64,
6408 .size32 => .SIZE32,
6409
6410 .larch_abs32_lo12,
6411 .larch_rel32_hi20,
6412 .larch_rel64_lo20,
6413 .larch_rel64_hi12,
6414 .larch_branch_rel18,
6415 .larch_branch_rel23,
6416 .larch_branch_rel28,
6417 .larch_call_rel38,
6418 .larch_tpoff32_lo12,
6419 .larch_tpoff32_hi20,
6420 .larch_tpoff64_lo20,
6421 .larch_tpoff64_hi12,
6422 => unreachable,
6423 } },
62286424 };
62296425
62306426 class: switch (elf.classifySymbolValue(target)) {