| ... | ... | @@ -1132,19 +1132,25 @@ const SymbolReloc = struct { |
| 1132 | 1132 | /// This is only used targeting local symbols so can always be statically resolved. |
| 1133 | 1133 | dsorel32, |
| 1134 | 1134 | |
| 1135 | | abs64, |
| 1135 | abs8, |
| 1136 | abs16, |
| 1136 | 1137 | abs32, |
| 1137 | 1138 | abs32s, |
| 1138 | | rel64, |
| 1139 | abs64, |
| 1140 | rel8, |
| 1141 | rel16, |
| 1139 | 1142 | rel32, |
| 1140 | | pltrel64, |
| 1143 | rel64, |
| 1144 | pltabs32, |
| 1145 | pltabs64, |
| 1141 | 1146 | pltrel32, |
| 1142 | | dtpoff64, |
| 1147 | pltrel64, |
| 1143 | 1148 | dtpoff32, |
| 1144 | | tpoff64, |
| 1149 | dtpoff64, |
| 1145 | 1150 | tpoff32, |
| 1146 | | size64, |
| 1151 | tpoff64, |
| 1147 | 1152 | size32, |
| 1153 | size64, |
| 1148 | 1154 | |
| 1149 | 1155 | larch_abs32_lo12, |
| 1150 | 1156 | larch_rel32_hi20, |
| ... | ... | @@ -1170,8 +1176,18 @@ const SymbolReloc = struct { |
| 1170 | 1176 | fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool { |
| 1171 | 1177 | return switch (elf.identClass()) { |
| 1172 | 1178 | .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 | }, |
| 1175 | 1191 | }; |
| 1176 | 1192 | } |
| 1177 | 1193 | }; |
| ... | ... | @@ -1190,11 +1206,31 @@ const SymbolReloc = struct { |
| 1190 | 1206 | .static => unreachable, |
| 1191 | 1207 | .dynamic => return, // the relocation happens at runtime |
| 1192 | 1208 | .static_relative => { |
| 1193 | | assert(reloc.type.isAbsAddr(elf)); |
| 1194 | 1209 | // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc. |
| 1195 | 1210 | // This is a simplified version of the general relocation handling logic, where we |
| 1196 | 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 | 1234 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value); |
| 1199 | 1235 | return; |
| 1200 | 1236 | }, |
| ... | ... | @@ -1241,6 +1277,13 @@ const SymbolReloc = struct { |
| 1241 | 1277 | @intCast(@as(i64, @bitCast(target_value))), |
| 1242 | 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 | 1287 | .rel64 => std.mem.writeInt( |
| 1245 | 1288 | i64, |
| 1246 | 1289 | dest_slice[0..8], |
| ... | ... | @@ -1253,17 +1296,65 @@ const SymbolReloc = struct { |
| 1253 | 1296 | @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))), |
| 1254 | 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 | 1346 | .pltrel64 => { |
| 1257 | 1347 | const plt_index = switch (reloc.target.unwrap()) { |
| 1258 | 1348 | .local => continue :type .rel64, |
| 1259 | 1349 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64, |
| 1260 | 1350 | }; |
| 1261 | 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 | 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 | 1358 | std.mem.writeInt( |
| 1268 | 1359 | i64, |
| 1269 | 1360 | dest_slice[0..8], |
| ... | ... | @@ -1277,11 +1368,12 @@ const SymbolReloc = struct { |
| 1277 | 1368 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32, |
| 1278 | 1369 | }; |
| 1279 | 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 | 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 | 1377 | std.mem.writeInt( |
| 1286 | 1378 | i32, |
| 1287 | 1379 | dest_slice[0..4], |
| ... | ... | @@ -6110,11 +6202,69 @@ fn addRelocAssumeCapacity( |
| 6110 | 6202 | _, |
| 6111 | 6203 | .NONE, |
| 6112 | 6204 | .COPY, |
| 6205 | .GLOB_DAT, |
| 6113 | 6206 | .JMP_SLOT, |
| 6114 | 6207 | .RELATIVE, |
| 6115 | 6208 | .IRELATIVE, |
| 6116 | 6209 | => std.debug.panic("TODO: error for illegal or unsupported input relocation, {t}", .{@"type".SPARC}), |
| 6117 | 6210 | |
| 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 | 6268 | // Relocations targeting a GOT entry |
| 6119 | 6269 | .GOT10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_10), |
| 6120 | 6270 | .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_13), |
| ... | ... | @@ -6169,11 +6319,14 @@ fn addSymbolRelocAssumeCapacity( |
| 6169 | 6319 | }, |
| 6170 | 6320 | .abs64 => .@"64", |
| 6171 | 6321 | .abs32 => .@"32", |
| 6322 | .abs16 => unreachable, |
| 6323 | .abs8 => unreachable, |
| 6172 | 6324 | .abs32s => .@"32S", |
| 6173 | 6325 | .rel64 => .PC64, |
| 6174 | 6326 | .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, |
| 6177 | 6330 | .dtpoff64 => .DTPOFF64, |
| 6178 | 6331 | .dtpoff32 => .DTPOFF32, |
| 6179 | 6332 | .tpoff64 => .TPOFF64, |
| ... | ... | @@ -6203,14 +6356,20 @@ fn addSymbolRelocAssumeCapacity( |
| 6203 | 6356 | }, |
| 6204 | 6357 | .abs64 => .@"64", |
| 6205 | 6358 | .abs32 => .@"32", |
| 6206 | | .abs32s, .size64, .size32 => unreachable, |
| 6359 | .abs32s => unreachable, |
| 6360 | .abs16 => unreachable, |
| 6361 | .abs8 => unreachable, |
| 6207 | 6362 | .rel64 => .@"64_PCREL", |
| 6208 | 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 | 6367 | .dtpoff64 => .TLS_DTPREL64, |
| 6211 | 6368 | .dtpoff32 => .TLS_DTPREL32, |
| 6212 | 6369 | .tpoff64 => .TLS_TPREL64, |
| 6213 | 6370 | .tpoff32 => .TLS_TPREL32, |
| 6371 | .size64 => unreachable, |
| 6372 | .size32 => unreachable, |
| 6214 | 6373 | |
| 6215 | 6374 | .larch_abs32_lo12 => .PCALA_LO12, |
| 6216 | 6375 | .larch_rel32_hi20 => .PCALA_HI20, |
| ... | ... | @@ -6225,6 +6384,43 @@ fn addSymbolRelocAssumeCapacity( |
| 6225 | 6384 | .larch_tpoff64_lo20 => .TLS_LE64_LO20, |
| 6226 | 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 | }; |
| 6229 | 6425 | |
| 6230 | 6426 | class: switch (elf.classifySymbolValue(target)) { |