| ... | ... | @@ -1210,7 +1210,7 @@ const SymbolReloc = struct { |
| 1210 | 1210 | /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`. |
| 1211 | 1211 | target: Symbol.Id, |
| 1212 | 1212 | /// A signed constant used to compute the relocated value. Precise meaning depends on `@"type"`. |
| 1213 | | addend: i64, |
| 1213 | addend: SymbolReloc.Addend, |
| 1214 | 1214 | /// Specifies how to apply the relocation. |
| 1215 | 1215 | /// |
| 1216 | 1216 | /// When emitting a relocatable, this field is `undefined`. |
| ... | ... | @@ -1251,6 +1251,18 @@ const SymbolReloc = struct { |
| 1251 | 1251 | return shndx; |
| 1252 | 1252 | } |
| 1253 | 1253 | |
| 1254 | const Addend = packed union(u64) { |
| 1255 | normal: i64, |
| 1256 | /// Only valid for `Type.special(.sparc_olo10)`. |
| 1257 | sparc_olo10: packed struct { |
| 1258 | /// The first addend from `r_addend`. |
| 1259 | a: u10, |
| 1260 | /// The second addend from the upper `r_info` type bits. |
| 1261 | o: i24, |
| 1262 | _pad: u30 = 0, |
| 1263 | }, |
| 1264 | }; |
| 1265 | |
| 1254 | 1266 | /// Instead of using the ELF relocation enums, we have our own internal representation for |
| 1255 | 1267 | /// relocation types. This representation is more compact (requiring only 16 bits), and allows |
| 1256 | 1268 | /// sharing a lot of relocation handling between multiple relocs and target architectures. |
| ... | ... | @@ -1504,6 +1516,7 @@ const SymbolReloc = struct { |
| 1504 | 1516 | larch_b26, |
| 1505 | 1517 | larch_call36, |
| 1506 | 1518 | |
| 1519 | sparc_olo10, |
| 1507 | 1520 | sparc_hix22, |
| 1508 | 1521 | sparc_le_hix22, |
| 1509 | 1522 | sparc_wdisp10, |
| ... | ... | @@ -1513,13 +1526,14 @@ const SymbolReloc = struct { |
| 1513 | 1526 | s: Special, |
| 1514 | 1527 | elf: *Elf, |
| 1515 | 1528 | target: Symbol.Id, |
| 1516 | | addend: u64, |
| 1529 | addend: SymbolReloc.Addend, |
| 1517 | 1530 | dest_vaddr: u64, |
| 1518 | 1531 | dest_slice: []u8, |
| 1519 | 1532 | ) error{ RelocationMisaligned, RelocationOverflow }!void { |
| 1533 | const normal_addend: u64 = @bitCast(addend.normal); |
| 1520 | 1534 | switch (s) { |
| 1521 | 1535 | .larch_pcala_hi20 => { |
| 1522 | | const val = target.value(elf) +% addend; |
| 1536 | const val = target.value(elf) +% normal_addend; |
| 1523 | 1537 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| 1524 | 1538 | elf.targetStore(inst, .{ |
| 1525 | 1539 | .b0_4 = elf.targetLoad(inst).b0_4, |
| ... | ... | @@ -1528,7 +1542,7 @@ const SymbolReloc = struct { |
| 1528 | 1542 | }); |
| 1529 | 1543 | }, |
| 1530 | 1544 | .larch_pcala64_lo20 => { |
| 1531 | | const val = target.value(elf) +% addend; |
| 1545 | const val = target.value(elf) +% normal_addend; |
| 1532 | 1546 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| 1533 | 1547 | elf.targetStore(inst, .{ |
| 1534 | 1548 | .b0_4 = elf.targetLoad(inst).b0_4, |
| ... | ... | @@ -1537,7 +1551,7 @@ const SymbolReloc = struct { |
| 1537 | 1551 | }); |
| 1538 | 1552 | }, |
| 1539 | 1553 | .larch_pcala64_hi12 => { |
| 1540 | | const val = target.value(elf) +% addend; |
| 1554 | const val = target.value(elf) +% normal_addend; |
| 1541 | 1555 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); |
| 1542 | 1556 | elf.targetStore(inst, .{ |
| 1543 | 1557 | .b0_9 = elf.targetLoad(inst).b0_9, |
| ... | ... | @@ -1547,7 +1561,7 @@ const SymbolReloc = struct { |
| 1547 | 1561 | }, |
| 1548 | 1562 | .larch_b21, .larch_b26, .larch_call36 => { |
| 1549 | 1563 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); |
| 1550 | | const jump_offset: i64 = @bitCast(target_vaddr +% addend -% dest_vaddr); |
| 1564 | const jump_offset: i64 = @bitCast(target_vaddr +% normal_addend -% dest_vaddr); |
| 1551 | 1565 | if ((jump_offset >> 2) << 2 != jump_offset) { |
| 1552 | 1566 | return error.RelocationMisaligned; |
| 1553 | 1567 | } |
| ... | ... | @@ -1606,13 +1620,26 @@ const SymbolReloc = struct { |
| 1606 | 1620 | } |
| 1607 | 1621 | }, |
| 1608 | 1622 | |
| 1623 | .sparc_olo10 => { |
| 1624 | const addends = addend.sparc_olo10; |
| 1625 | const lo10: i64 = @as(u10, @truncate(target.value(elf) +% addends.a)); |
| 1626 | const simm13 = std.math.cast(i13, lo10 + addends.o) orelse return error.RelocationOverflow; |
| 1627 | const dest_ptr: *align(1) packed struct(u32) { |
| 1628 | simm13: u13, |
| 1629 | b13_31: u19, |
| 1630 | } = @ptrCast(dest_slice); |
| 1631 | elf.targetStore(dest_ptr, .{ |
| 1632 | .simm13 = @bitCast(simm13), |
| 1633 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, |
| 1634 | }); |
| 1635 | }, |
| 1609 | 1636 | .sparc_hix22 => { |
| 1610 | 1637 | const dest_ptr: *align(1) packed struct(u32) { |
| 1611 | 1638 | imm22: u22, |
| 1612 | 1639 | b22_31: u10, |
| 1613 | 1640 | } = @ptrCast(dest_slice); |
| 1614 | 1641 | elf.targetStore(dest_ptr, .{ |
| 1615 | | .imm22 = @truncate(~(target.value(elf) +% addend) >> 10), |
| 1642 | .imm22 = @truncate(~(target.value(elf) +% normal_addend) >> 10), |
| 1616 | 1643 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| 1617 | 1644 | }); |
| 1618 | 1645 | }, |
| ... | ... | @@ -1629,13 +1656,13 @@ const SymbolReloc = struct { |
| 1629 | 1656 | b22_31: u10, |
| 1630 | 1657 | } = @ptrCast(dest_slice); |
| 1631 | 1658 | elf.targetStore(dest_ptr, .{ |
| 1632 | | .imm22 = @truncate(~(target.value(elf) +% addend -% tls_size) >> 10), |
| 1659 | .imm22 = @truncate(~(target.value(elf) +% normal_addend -% tls_size) >> 10), |
| 1633 | 1660 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| 1634 | 1661 | }); |
| 1635 | 1662 | }, |
| 1636 | 1663 | .sparc_wdisp16, .sparc_wdisp10 => { |
| 1637 | 1664 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); |
| 1638 | | const jump_offset: i64 = @bitCast(target_vaddr +% addend -% dest_vaddr); |
| 1665 | const jump_offset: i64 = @bitCast(target_vaddr +% normal_addend -% dest_vaddr); |
| 1639 | 1666 | if ((jump_offset >> 2) << 2 != jump_offset) { |
| 1640 | 1667 | return error.RelocationMisaligned; |
| 1641 | 1668 | } |
| ... | ... | @@ -1719,6 +1746,7 @@ const SymbolReloc = struct { |
| 1719 | 1746 | .larch_b26, |
| 1720 | 1747 | .larch_call36, |
| 1721 | 1748 | |
| 1749 | .sparc_olo10, |
| 1722 | 1750 | .sparc_hix22, |
| 1723 | 1751 | .sparc_wdisp10, |
| 1724 | 1752 | .sparc_wdisp16, |
| ... | ... | @@ -1815,7 +1843,7 @@ const SymbolReloc = struct { |
| 1815 | 1843 | .special => return reloc.type.action.special.applyInner( |
| 1816 | 1844 | elf, |
| 1817 | 1845 | reloc.target, |
| 1818 | | addend, |
| 1846 | reloc.addend, |
| 1819 | 1847 | dest_vaddr, |
| 1820 | 1848 | dest_slice, |
| 1821 | 1849 | ), |
| ... | ... | @@ -8986,7 +9014,7 @@ fn addRelocAssumeCapacity( |
| 8986 | 9014 | .offset = offset, |
| 8987 | 9015 | .type = undefined, |
| 8988 | 9016 | .target = target, |
| 8989 | | .addend = addend, |
| 9017 | .addend = .{ .normal = addend }, |
| 8990 | 9018 | .next = next, |
| 8991 | 9019 | .prev = .none, |
| 8992 | 9020 | .rela_index = rela_index.toOptional(), |
| ... | ... | @@ -9064,7 +9092,8 @@ fn addRelocAssumeCapacity( |
| 9064 | 9092 | _ => return error.UnknownRelocation, |
| 9065 | 9093 | else => return error.UnimplementedRelocation, |
| 9066 | 9094 | }, |
| 9067 | | .SPARCV9 => switch (@"type".SPARC) { |
| 9095 | // For SPARC, only the 8 lower bits represent the type. See the `R_SPARC_OLO10` prong below for more info. |
| 9096 | .SPARCV9 => switch (@as(std.elf.R_SPARC, @fromBackingInt(@as(u8, @truncate(@backingInt(@"type".SPARC)))))) { |
| 9068 | 9097 | .NONE => {}, |
| 9069 | 9098 | _ => return error.UnknownRelocation, |
| 9070 | 9099 | |
| ... | ... | @@ -9086,9 +9115,6 @@ fn addRelocAssumeCapacity( |
| 9086 | 9115 | .PCPLT10, |
| 9087 | 9116 | => return error.UnimplementedRelocation, |
| 9088 | 9117 | |
| 9089 | | // Needs to use the second addend in `ELF64_R_TYPE_DATA(reloc.r_info)` which we currently can't model. |
| 9090 | | .OLO10 => return error.UnimplementedRelocation, |
| 9091 | | |
| 9092 | 9118 | // Does not patch any bytes. Together with `STT_SPARC_REGISTER`, this is used to indicate that an object |
| 9093 | 9119 | // file owns a global register and what value it should be initialized to. I don't think this sees any |
| 9094 | 9120 | // real-world use. |
| ... | ... | @@ -9175,6 +9201,20 @@ fn addRelocAssumeCapacity( |
| 9175 | 9201 | try elf.addSymbolRelocAssumeCapacity(node, offset, callee_sym, addend, .simple(.pltrel, .{ .dest = .@"32[29:0]", .cast = .signed, .shift = .@"2_exact" })); |
| 9176 | 9202 | }, |
| 9177 | 9203 | |
| 9204 | // `R_SPARC_OLO10` packs a secondary addend into the upper 24 bits. Conceptually, this relocation is |
| 9205 | // just `R_SPARC_LO10` (with `r_addend`) + `R_SPARC_13` (with `r_info` addend) applied in sequence. We |
| 9206 | // can neatly fit both into the single `addend` value, to be handled by `SymbolReloc.Special.applyInner`. |
| 9207 | .OLO10 => |t| try elf.addSymbolRelocAssumeCapacityInner( |
| 9208 | node, |
| 9209 | offset, |
| 9210 | target, |
| 9211 | .{ .sparc_olo10 = .{ |
| 9212 | .a = @truncate(@as(u64, @bitCast(addend))), |
| 9213 | .o = @truncate(@as(i32, @bitCast(@backingInt(t) >> 8))), |
| 9214 | } }, |
| 9215 | .special(.sparc_olo10), |
| 9216 | ), |
| 9217 | |
| 9178 | 9218 | // The following relocations are all represented by the ABI as writing to a 13 bit |
| 9179 | 9219 | // field (32[12:0]), but masking out some bits of the value. To simplify our logic |
| 9180 | 9220 | // for applying relocations, we split this action up: we create a relocation writing |
| ... | ... | @@ -9324,6 +9364,16 @@ fn addSymbolRelocAssumeCapacity( |
| 9324 | 9364 | target: Symbol.Id, |
| 9325 | 9365 | addend: i64, |
| 9326 | 9366 | @"type": SymbolReloc.Type, |
| 9367 | ) Error!void { |
| 9368 | return elf.addSymbolRelocAssumeCapacityInner(node, offset, target, .{ .normal = addend }, @"type"); |
| 9369 | } |
| 9370 | fn addSymbolRelocAssumeCapacityInner( |
| 9371 | elf: *Elf, |
| 9372 | node: MappedFile.Node.Index, |
| 9373 | offset: u64, |
| 9374 | target: Symbol.Id, |
| 9375 | addend: SymbolReloc.Addend, |
| 9376 | @"type": SymbolReloc.Type, |
| 9327 | 9377 | ) Error!void { |
| 9328 | 9378 | assert(elf.ehdrType() != .REL); |
| 9329 | 9379 | |
| ... | ... | @@ -9353,6 +9403,7 @@ fn addSymbolRelocAssumeCapacity( |
| 9353 | 9403 | .larch_pcala64_lo20, |
| 9354 | 9404 | .larch_pcala64_hi12, |
| 9355 | 9405 | |
| 9406 | .sparc_olo10, |
| 9356 | 9407 | .sparc_hix22, |
| 9357 | 9408 | => true, |
| 9358 | 9409 | |
| ... | ... | @@ -9447,7 +9498,7 @@ fn addSymbolRelocAssumeCapacity( |
| 9447 | 9498 | .type = dynamic_reloc_type, |
| 9448 | 9499 | .offset = node_vaddr + offset, |
| 9449 | 9500 | .raw_sym_index = target.unwrap().global.dynsymIndex(elf).?, |
| 9450 | | .addend = addend, |
| 9501 | .addend = addend.normal, |
| 9451 | 9502 | }).toOptional(); |
| 9452 | 9503 | }, |
| 9453 | 9504 | } |