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 {...@@ -1132,19 +1132,25 @@ const SymbolReloc = struct {
1132 /// This is only used targeting local symbols so can always be statically resolved.1132 /// This is only used targeting local symbols so can always be statically resolved.
1133 dsorel32,1133 dsorel32,
11341134
1135 abs64,1135 abs8,
1136 abs16,
1136 abs32,1137 abs32,
1137 abs32s,1138 abs32s,
1138 rel64,1139 abs64,
1140 rel8,
1141 rel16,
1139 rel32,1142 rel32,
1140 pltrel64,1143 rel64,
1144 pltabs32,
1145 pltabs64,
1141 pltrel32,1146 pltrel32,
1142 dtpoff64,1147 pltrel64,
1143 dtpoff32,1148 dtpoff32,
1144 tpoff64,1149 dtpoff64,
1145 tpoff32,1150 tpoff32,
1146 size64,1151 tpoff64,
1147 size32,1152 size32,
1153 size64,
11481154
1149 larch_abs32_lo12,1155 larch_abs32_lo12,
1150 larch_rel32_hi20,1156 larch_rel32_hi20,
...@@ -1170,8 +1176,18 @@ const SymbolReloc = struct {...@@ -1170,8 +1176,18 @@ const SymbolReloc = struct {
1170 fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool {1176 fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool {
1171 return switch (elf.identClass()) {1177 return switch (elf.identClass()) {
1172 .NONE, _ => unreachable,1178 .NONE, _ => unreachable,
1173 .@"32" => t == .abs32,1179 .@"32" => switch (t) {
1174 .@"64" => t == .abs64,1180 .abs32,
1181 .pltabs32,
1182 => true,
1183 else => false,
1184 },
1185 .@"64" => switch (t) {
1186 .abs64,
1187 .pltabs64,
1188 => true,
1189 else => false,
1190 },
1175 };1191 };
1176 }1192 }
1177 };1193 };
...@@ -1190,11 +1206,31 @@ const SymbolReloc = struct {...@@ -1190,11 +1206,31 @@ const SymbolReloc = struct {
1190 .static => unreachable,1206 .static => unreachable,
1191 .dynamic => return, // the relocation happens at runtime1207 .dynamic => return, // the relocation happens at runtime
1192 .static_relative => {1208 .static_relative => {
1193 assert(reloc.type.isAbsAddr(elf));
1194 // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc.1209 // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc.
1195 // This is a simplified version of the general relocation handling logic, where we1210 // This is a simplified version of the general relocation handling logic, where we
1196 // know we're using '.abs64' or '.abs32' (matching the ELF ident class).1211 // 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 };
1198 elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value);1234 elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value);
1199 return;1235 return;
1200 },1236 },
...@@ -1241,6 +1277,13 @@ const SymbolReloc = struct {...@@ -1241,6 +1277,13 @@ const SymbolReloc = struct {
1241 @intCast(@as(i64, @bitCast(target_value))),1277 @intCast(@as(i64, @bitCast(target_value))),
1242 target_endian,1278 target_endian,
1243 ),1279 ),
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),
1244 .rel64 => std.mem.writeInt(1287 .rel64 => std.mem.writeInt(
1245 i64,1288 i64,
1246 dest_slice[0..8],1289 dest_slice[0..8],
...@@ -1253,17 +1296,65 @@ const SymbolReloc = struct {...@@ -1253,17 +1296,65 @@ const SymbolReloc = struct {
1253 @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))),1296 @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))),
1254 target_endian,1297 target_endian,
1255 ),1298 ),
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 },
1256 .pltrel64 => {1346 .pltrel64 => {
1257 const plt_index = switch (reloc.target.unwrap()) {1347 const plt_index = switch (reloc.target.unwrap()) {
1258 .local => continue :type .rel64,1348 .local => continue :type .rel64,
1259 .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64,1349 .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64,
1260 };1350 };
1261 if (elf.pltEntryIsDead(plt_index)) continue :type .rel64;1351 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)) {
1263 else => |machine| @panic(@tagName(machine)),1353 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 },
1265 };1356 };
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;
1267 std.mem.writeInt(1358 std.mem.writeInt(
1268 i64,1359 i64,
1269 dest_slice[0..8],1360 dest_slice[0..8],
...@@ -1277,11 +1368,12 @@ const SymbolReloc = struct {...@@ -1277,11 +1368,12 @@ const SymbolReloc = struct {
1277 .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32,1368 .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32,
1278 };1369 };
1279 if (elf.pltEntryIsDead(plt_index)) continue :type .rel32;1370 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)) {
1281 else => |machine| @panic(@tagName(machine)),1372 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 },
1283 };1375 };
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;
1285 std.mem.writeInt(1377 std.mem.writeInt(
1286 i32,1378 i32,
1287 dest_slice[0..4],1379 dest_slice[0..4],
...@@ -6110,11 +6202,69 @@ fn addRelocAssumeCapacity(...@@ -6110,11 +6202,69 @@ fn addRelocAssumeCapacity(
6110 _,6202 _,
6111 .NONE,6203 .NONE,
6112 .COPY,6204 .COPY,
6205 .GLOB_DAT,
6113 .JMP_SLOT,6206 .JMP_SLOT,
6114 .RELATIVE,6207 .RELATIVE,
6115 .IRELATIVE,6208 .IRELATIVE,
6116 => std.debug.panic("TODO: error for illegal or unsupported input relocation, {t}", .{@"type".SPARC}),6209 => 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
6118 // Relocations targeting a GOT entry6268 // Relocations targeting a GOT entry
6119 .GOT10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_10),6269 .GOT10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_10),
6120 .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_13),6270 .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_13),
...@@ -6169,11 +6319,14 @@ fn addSymbolRelocAssumeCapacity(...@@ -6169,11 +6319,14 @@ fn addSymbolRelocAssumeCapacity(
6169 },6319 },
6170 .abs64 => .@"64",6320 .abs64 => .@"64",
6171 .abs32 => .@"32",6321 .abs32 => .@"32",
6322 .abs16 => unreachable,
6323 .abs8 => unreachable,
6172 .abs32s => .@"32S",6324 .abs32s => .@"32S",
6173 .rel64 => .PC64,6325 .rel64 => .PC64,
6174 .rel32 => .PC32,6326 .rel32 => .PC32,
6175 .pltrel64 => break :r .none,6327 .rel16 => unreachable,
6176 .pltrel32 => break :r .none,6328 .rel8 => unreachable,
6329 .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none,
6177 .dtpoff64 => .DTPOFF64,6330 .dtpoff64 => .DTPOFF64,
6178 .dtpoff32 => .DTPOFF32,6331 .dtpoff32 => .DTPOFF32,
6179 .tpoff64 => .TPOFF64,6332 .tpoff64 => .TPOFF64,
...@@ -6203,14 +6356,20 @@ fn addSymbolRelocAssumeCapacity(...@@ -6203,14 +6356,20 @@ fn addSymbolRelocAssumeCapacity(
6203 },6356 },
6204 .abs64 => .@"64",6357 .abs64 => .@"64",
6205 .abs32 => .@"32",6358 .abs32 => .@"32",
6206 .abs32s, .size64, .size32 => unreachable,6359 .abs32s => unreachable,
6360 .abs16 => unreachable,
6361 .abs8 => unreachable,
6207 .rel64 => .@"64_PCREL",6362 .rel64 => .@"64_PCREL",
6208 .rel32 => .@"32_PCREL",6363 .rel32 => .@"32_PCREL",
6209 .pltrel64, .pltrel32 => break :r .none,6364 .rel16 => unreachable,
6365 .rel8 => unreachable,
6366 .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none,
6210 .dtpoff64 => .TLS_DTPREL64,6367 .dtpoff64 => .TLS_DTPREL64,
6211 .dtpoff32 => .TLS_DTPREL32,6368 .dtpoff32 => .TLS_DTPREL32,
6212 .tpoff64 => .TLS_TPREL64,6369 .tpoff64 => .TLS_TPREL64,
6213 .tpoff32 => .TLS_TPREL32,6370 .tpoff32 => .TLS_TPREL32,
6371 .size64 => unreachable,
6372 .size32 => unreachable,
62146373
6215 .larch_abs32_lo12 => .PCALA_LO12,6374 .larch_abs32_lo12 => .PCALA_LO12,
6216 .larch_rel32_hi20 => .PCALA_HI20,6375 .larch_rel32_hi20 => .PCALA_HI20,
...@@ -6225,6 +6384,43 @@ fn addSymbolRelocAssumeCapacity(...@@ -6225,6 +6384,43 @@ fn addSymbolRelocAssumeCapacity(
6225 .larch_tpoff64_lo20 => .TLS_LE64_LO20,6384 .larch_tpoff64_lo20 => .TLS_LE64_LO20,
6226 .larch_tpoff64_hi12 => .TLS_LE64_HI12,6385 .larch_tpoff64_hi12 => .TLS_LE64_HI12,
6227 } },6386 } },
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 } },
6228 };6424 };
62296425
6230 class: switch (elf.classifySymbolValue(target)) {6426 class: switch (elf.classifySymbolValue(target)) {