| ... | @@ -208,29 +208,24 @@ navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct { | ... | @@ -208,29 +208,24 @@ navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct { |
| 208 | lsi: Symbol.LocalIndex, | 208 | lsi: Symbol.LocalIndex, |
| 209 | /// The start index of the contiguous sequence of symbol relocations in this NAV. | 209 | /// The start index of the contiguous sequence of symbol relocations in this NAV. |
| 210 | first_symbol_reloc: SymbolReloc.Index, | 210 | first_symbol_reloc: SymbolReloc.Index, |
| 211 | /// The start index of the contiguous sequence of GOT relocations in this NAV. | | |
| 212 | first_got_reloc: GotReloc.Index, | | |
| 213 | }), | 211 | }), |
| 214 | uavs: std.array_hash_map.Auto(InternPool.Index, struct { | 212 | uavs: std.array_hash_map.Auto(InternPool.Index, struct { |
| 215 | lsi: Symbol.LocalIndex, | 213 | lsi: Symbol.LocalIndex, |
| 216 | /// The start index of the contiguous sequence of symbol relocations in this UAV. | 214 | /// The start index of the contiguous sequence of symbol relocations in this UAV. |
| 217 | first_symbol_reloc: SymbolReloc.Index, | 215 | first_symbol_reloc: SymbolReloc.Index, |
| 218 | // No `first_got_reloc` field because a UAV never contains GOT relocations. | | |
| 219 | }), | 216 | }), |
| 220 | lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { | 217 | lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { |
| 221 | map: std.array_hash_map.Auto(InternPool.Index, struct { | 218 | map: std.array_hash_map.Auto(InternPool.Index, struct { |
| 222 | lsi: Symbol.LocalIndex, | 219 | lsi: Symbol.LocalIndex, |
| 223 | /// The start index of the contiguous sequence of symbol relocations in this lazy code/data. | 220 | /// The start index of the contiguous sequence of symbol relocations in this lazy code/data. |
| 224 | first_symbol_reloc: SymbolReloc.Index, | 221 | first_symbol_reloc: SymbolReloc.Index, |
| 225 | /// The start index of the contiguous sequence of GOT relocations in this lazy code/data. | | |
| 226 | first_got_reloc: GotReloc.Index, | | |
| 227 | }), | 222 | }), |
| 228 | pending_index: u32, | 223 | pending_index: u32, |
| 229 | }), | 224 | }), |
| 230 | pending_uavs: std.ArrayList(Node.UavMapIndex), | 225 | pending_uavs: std.ArrayList(Node.UavMapIndex), |
| 231 | symbol_relocs: std.ArrayList(SymbolReloc), | 226 | symbol_relocs: std.ArrayList(SymbolReloc), |
| 232 | node_relocs: std.ArrayList(NodeReloc), | 227 | node_relocs: std.ArrayList(NodeReloc), |
| 233 | got_relocs: std.ArrayList(GotReloc), | 228 | got_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), |
| 234 | /// Set of relocations which must be re-applied if the size of the TLS segment changes. | 229 | /// Set of relocations which must be re-applied if the size of the TLS segment changes. |
| 235 | tls_size_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), | 230 | tls_size_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), |
| 236 | /// Index matches the index into `shdrs`. Like `shdrs`, this map excludes `SHN_UNDEF`. | 231 | /// Index matches the index into `shdrs`. Like `shdrs`, this map excludes `SHN_UNDEF`. |
| ... | @@ -388,9 +383,6 @@ const Node = union(enum) { | ... | @@ -388,9 +383,6 @@ const Node = union(enum) { |
| 388 | fn firstSymbolReloc(nmi: NavMapIndex, elf: *const Elf) SymbolReloc.Index { | 383 | fn firstSymbolReloc(nmi: NavMapIndex, elf: *const Elf) SymbolReloc.Index { |
| 389 | return elf.navs.values()[@backingInt(nmi)].first_symbol_reloc; | 384 | return elf.navs.values()[@backingInt(nmi)].first_symbol_reloc; |
| 390 | } | 385 | } |
| 391 | fn firstGotReloc(nmi: NavMapIndex, elf: *const Elf) GotReloc.Index { | | |
| 392 | return elf.navs.values()[@backingInt(nmi)].first_got_reloc; | | |
| 393 | } | | |
| 394 | }; | 386 | }; |
| 395 | | 387 | |
| 396 | pub const UavMapIndex = enum(u32) { | 388 | pub const UavMapIndex = enum(u32) { |
| ... | @@ -407,11 +399,6 @@ const Node = union(enum) { | ... | @@ -407,11 +399,6 @@ const Node = union(enum) { |
| 407 | fn firstSymbolReloc(umi: UavMapIndex, elf: *const Elf) SymbolReloc.Index { | 399 | fn firstSymbolReloc(umi: UavMapIndex, elf: *const Elf) SymbolReloc.Index { |
| 408 | return elf.uavs.values()[@backingInt(umi)].first_symbol_reloc; | 400 | return elf.uavs.values()[@backingInt(umi)].first_symbol_reloc; |
| 409 | } | 401 | } |
| 410 | fn firstGotReloc(umi: UavMapIndex, elf: *const Elf) GotReloc.Index { | | |
| 411 | _ = umi; | | |
| 412 | _ = elf; | | |
| 413 | return .none; | | |
| 414 | } | | |
| 415 | }; | 402 | }; |
| 416 | | 403 | |
| 417 | pub const LazyMapRef = struct { | 404 | pub const LazyMapRef = struct { |
| ... | @@ -437,9 +424,6 @@ const Node = union(enum) { | ... | @@ -437,9 +424,6 @@ const Node = union(enum) { |
| 437 | fn firstSymbolReloc(lmi: @This(), elf: *const Elf) SymbolReloc.Index { | 424 | fn firstSymbolReloc(lmi: @This(), elf: *const Elf) SymbolReloc.Index { |
| 438 | return elf.lazy.getPtrConst(kind).map.values()[@backingInt(lmi)].first_symbol_reloc; | 425 | return elf.lazy.getPtrConst(kind).map.values()[@backingInt(lmi)].first_symbol_reloc; |
| 439 | } | 426 | } |
| 440 | fn firstGotReloc(lmi: @This(), elf: *const Elf) GotReloc.Index { | | |
| 441 | return elf.lazy.getPtrConst(kind).map.values()[@backingInt(lmi)].first_got_reloc; | | |
| 442 | } | | |
| 443 | }; | 427 | }; |
| 444 | } | 428 | } |
| 445 | | 429 | |
| ... | @@ -603,8 +587,6 @@ const InputSection = struct { | ... | @@ -603,8 +587,6 @@ const InputSection = struct { |
| 603 | node: MappedFile.Node.Index, | 587 | node: MappedFile.Node.Index, |
| 604 | /// The start index of the contiguous sequence of symbol relocations in this input section. | 588 | /// The start index of the contiguous sequence of symbol relocations in this input section. |
| 605 | first_symbol_reloc: SymbolReloc.Index, | 589 | first_symbol_reloc: SymbolReloc.Index, |
| 606 | /// The start index of the contiguous sequence of GOT relocations in this input section. | | |
| 607 | first_got_reloc: GotReloc.Index, | | |
| 608 | | 590 | |
| 609 | const Index = enum(u32) { | 591 | const Index = enum(u32) { |
| 610 | _, | 592 | _, |
| ... | @@ -1387,14 +1369,29 @@ const SymbolReloc = struct { | ... | @@ -1387,14 +1369,29 @@ const SymbolReloc = struct { |
| 1387 | node: MappedFile.Node.Index.Optional, | 1369 | node: MappedFile.Node.Index.Optional, |
| 1388 | /// The offset of the relocation inside of `node`. | 1370 | /// The offset of the relocation inside of `node`. |
| 1389 | offset: u64, | 1371 | offset: u64, |
| 1390 | /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`. | 1372 | /// A symbol used to compute the relocated value. Precise meaning depends on `bits.@"type"`. |
| 1391 | target: Symbol.Id, | 1373 | target_symbol: Symbol.Id, |
| 1392 | /// A signed constant used to compute the relocated value. Precise meaning depends on `@"type"`. | 1374 | /// A signed constant used to compute the relocated value. Precise meaning depends on `bits.@"type"`. |
| 1393 | addend: SymbolReloc.Addend, | 1375 | addend: SymbolReloc.Addend, |
| 1394 | /// Specifies how to apply the relocation. | 1376 | bits: packed struct(u32) { |
| 1395 | /// | 1377 | /// Specifies how to apply the relocation. |
| 1396 | /// When emitting a relocatable, this field is `undefined`. | 1378 | /// |
| 1397 | type: SymbolReloc.Type, | 1379 | /// When emitting a relocatable, this field is `undefined`. |
| | 1380 | type: SymbolReloc.Type, |
| | 1381 | |
| | 1382 | result: enum(u3) { |
| | 1383 | ok, |
| | 1384 | overflowed, |
| | 1385 | misaligned, |
| | 1386 | illegal_dynamic_type, |
| | 1387 | illegal_dynamic_section, |
| | 1388 | }, |
| | 1389 | |
| | 1390 | /// ~~mystery bits~~ |
| | 1391 | /// what will MLUGG use them for? |
| | 1392 | /// nobody knows |
| | 1393 | _: u11 = 0, |
| | 1394 | }, |
| 1398 | /// Forms a linked list of all symbol relocations with the same `target`. This list exists so | 1395 | /// Forms a linked list of all symbol relocations with the same `target`. This list exists so |
| 1399 | /// that all relocations targeting a particular symbol can be re-applied if that symbol moves. | 1396 | /// that all relocations targeting a particular symbol can be re-applied if that symbol moves. |
| 1400 | /// Doubly-linked so that relocations can be removed. | 1397 | /// Doubly-linked so that relocations can be removed. |
| ... | @@ -1412,13 +1409,6 @@ const SymbolReloc = struct { | ... | @@ -1412,13 +1409,6 @@ const SymbolReloc = struct { |
| 1412 | /// relocation entry. The entry will be removed if we discover a definition which allows us to | 1409 | /// relocation entry. The entry will be removed if we discover a definition which allows us to |
| 1413 | /// statically resolve the relocation. | 1410 | /// statically resolve the relocation. |
| 1414 | rela_index: Section.RelaIndex.Optional, | 1411 | rela_index: Section.RelaIndex.Optional, |
| 1415 | result: enum(u8) { | | |
| 1416 | ok, | | |
| 1417 | overflowed, | | |
| 1418 | misaligned, | | |
| 1419 | illegal_dynamic_type, | | |
| 1420 | illegal_dynamic_section, | | |
| 1421 | }, | | |
| 1422 | | 1412 | |
| 1423 | /// Determines the section in which this relocation will be placed if it is outstanding. | 1413 | /// Determines the section in which this relocation will be placed if it is outstanding. |
| 1424 | /// | 1414 | /// |
| ... | @@ -1464,7 +1454,7 @@ const SymbolReloc = struct { | ... | @@ -1464,7 +1454,7 @@ const SymbolReloc = struct { |
| 1464 | /// relocations which write multiple sequences of bits or which need to do unusual arithmetic on | 1454 | /// relocations which write multiple sequences of bits or which need to do unusual arithmetic on |
| 1465 | /// a symbol value. The representation is simply a big enum containing all of these exceptional | 1455 | /// a symbol value. The representation is simply a big enum containing all of these exceptional |
| 1466 | /// cases---see `Special`. This representation is in use when `Type.target == .special`. | 1456 | /// cases---see `Special`. This representation is in use when `Type.target == .special`. |
| 1467 | const Type = packed struct(u16) { | 1457 | const Type = packed struct(u18) { |
| 1468 | /// Helper function for constructing a "simple" relocation type. This mainly exists to | 1458 | /// Helper function for constructing a "simple" relocation type. This mainly exists to |
| 1469 | /// improve readability in the relocation lowering logic in `addRelocAssumeCapacity`. | 1459 | /// improve readability in the relocation lowering logic in `addRelocAssumeCapacity`. |
| 1470 | fn simple(target: Target, action: Simple) SymbolReloc.Type { | 1460 | fn simple(target: Target, action: Simple) SymbolReloc.Type { |
| ... | @@ -1493,7 +1483,7 @@ const SymbolReloc = struct { | ... | @@ -1493,7 +1483,7 @@ const SymbolReloc = struct { |
| 1493 | /// Otherwise (for "simple" relocations), `Target` indicates the first step in computing the | 1483 | /// Otherwise (for "simple" relocations), `Target` indicates the first step in computing the |
| 1494 | /// relocation---whether we care about the target symbol's absolute address, its PC-relative | 1484 | /// relocation---whether we care about the target symbol's absolute address, its PC-relative |
| 1495 | /// address, its PLT entry, etc. | 1485 | /// address, its PLT entry, etc. |
| 1496 | const Target = enum(u3) { | 1486 | const Target = enum(u5) { |
| 1497 | /// This is a "special" relocation whose specific type is in the `action.special` field. | 1487 | /// This is a "special" relocation whose specific type is in the `action.special` field. |
| 1498 | special, | 1488 | special, |
| 1499 | | 1489 | |
| ... | @@ -1501,6 +1491,7 @@ const SymbolReloc = struct { | ... | @@ -1501,6 +1491,7 @@ const SymbolReloc = struct { |
| 1501 | abs, | 1491 | abs, |
| 1502 | /// Offset from the relocation itself to the target symbol ("PC-relative"). | 1492 | /// Offset from the relocation itself to the target symbol ("PC-relative"). |
| 1503 | rel, | 1493 | rel, |
| | 1494 | |
| 1504 | /// Address of the target symbol's PLT entry. | 1495 | /// Address of the target symbol's PLT entry. |
| 1505 | /// | 1496 | /// |
| 1506 | /// If the target symbol does not have a PLT entry, equivalent to `.abs`. | 1497 | /// If the target symbol does not have a PLT entry, equivalent to `.abs`. |
| ... | @@ -1509,12 +1500,35 @@ const SymbolReloc = struct { | ... | @@ -1509,12 +1500,35 @@ const SymbolReloc = struct { |
| 1509 | /// | 1500 | /// |
| 1510 | /// If the target symbol does not have a PLT entry, equivalent to `.rel`. | 1501 | /// If the target symbol does not have a PLT entry, equivalent to `.rel`. |
| 1511 | pltrel, | 1502 | pltrel, |
| | 1503 | |
| 1512 | /// Offset of the target TLS symbol from the base of this DSO's own TLS region. | 1504 | /// Offset of the target TLS symbol from the base of this DSO's own TLS region. |
| 1513 | dtpoff, | 1505 | dtpoff, |
| 1514 | /// Offset of the target TLS symbol from the raw thread pointer. | 1506 | /// Offset of the target TLS symbol from the raw thread pointer. |
| 1515 | tpoff, | 1507 | tpoff, |
| | 1508 | |
| 1516 | /// Size of the target symbol. | 1509 | /// Size of the target symbol. |
| 1517 | size, | 1510 | size, |
| | 1511 | |
| | 1512 | /// Address of the GOT entry with key `.{ .symbol = target_symbol }`. |
| | 1513 | gotabs_symbol, |
| | 1514 | /// Offset from the relocation to the GOT entry with key `.{ .symbol = target_symbol }`. |
| | 1515 | gotrel_symbol, |
| | 1516 | /// Offset from the GOT base to the GOT entry with key `.{ .symbol = target_symbol }`. |
| | 1517 | gotoff_symbol, |
| | 1518 | |
| | 1519 | /// Address of the GOT entry with key `.{ .tpoff = target_symbol }`. |
| | 1520 | gotabs_tpoff, |
| | 1521 | /// Offset from the relocation to the GOT entry with key `.{ .tpoff = target_symbol }`. |
| | 1522 | gotrel_tpoff, |
| | 1523 | /// Offset from the GOT base to the GOT entry with key `.{ .tpoff = target_symbol }`. |
| | 1524 | gotoff_tpoff, |
| | 1525 | |
| | 1526 | /// Address of the GOT entry with key `.{ .tlsgd0 = target_symbol }`. |
| | 1527 | gotabs_tlsgd, |
| | 1528 | /// Offset from the relocation to the GOT entry with key `.{ .tlsgd0 = target_symbol }`. |
| | 1529 | gotrel_tlsgd, |
| | 1530 | /// Offset from the GOT base to the GOT entry with key `.{ .tlsgd0 = target_symbol }`. |
| | 1531 | gotoff_tlsgd, |
| 1518 | }; | 1532 | }; |
| 1519 | | 1533 | |
| 1520 | /// For a "simple" relocation, after the initial value is computed according to `Target`, a | 1534 | /// For a "simple" relocation, after the initial value is computed according to `Target`, a |
| ... | @@ -1701,17 +1715,22 @@ const SymbolReloc = struct { | ... | @@ -1701,17 +1715,22 @@ const SymbolReloc = struct { |
| 1701 | larch_b21, | 1715 | larch_b21, |
| 1702 | larch_b26, | 1716 | larch_b26, |
| 1703 | larch_call36, | 1717 | larch_call36, |
| | 1718 | larch_got_pcala_hi20, |
| | 1719 | larch_got_pcala64_lo20, |
| | 1720 | larch_got_pcala64_hi12, |
| 1704 | | 1721 | |
| 1705 | sparc_olo10, | 1722 | sparc_olo10, |
| 1706 | sparc_hix22, | 1723 | sparc_hix22, |
| 1707 | sparc_le_hix22, | 1724 | sparc_le_hix22, |
| 1708 | sparc_wdisp10, | 1725 | sparc_wdisp10, |
| 1709 | sparc_wdisp16, | 1726 | sparc_wdisp16, |
| | 1727 | sparc_got_op_lox10, |
| | 1728 | sparc_got_op_hix22, |
| 1710 | | 1729 | |
| 1711 | fn applyInner( | 1730 | fn applyInner( |
| 1712 | s: Special, | 1731 | s: Special, |
| 1713 | elf: *Elf, | 1732 | elf: *Elf, |
| 1714 | target: Symbol.Id, | 1733 | target_sym: Symbol.Id, |
| 1715 | addend: SymbolReloc.Addend, | 1734 | addend: SymbolReloc.Addend, |
| 1716 | dest_vaddr: u64, | 1735 | dest_vaddr: u64, |
| 1717 | dest_slice: []u8, | 1736 | dest_slice: []u8, |
| ... | @@ -1719,7 +1738,7 @@ const SymbolReloc = struct { | ... | @@ -1719,7 +1738,7 @@ const SymbolReloc = struct { |
| 1719 | const normal_addend: u64 = @bitCast(addend.normal); | 1738 | const normal_addend: u64 = @bitCast(addend.normal); |
| 1720 | switch (s) { | 1739 | switch (s) { |
| 1721 | .larch_pcala_hi20 => { | 1740 | .larch_pcala_hi20 => { |
| 1722 | const val = target.value(elf) +% normal_addend; | 1741 | const val = target_sym.value(elf) +% normal_addend; |
| 1723 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | 1742 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| 1724 | elf.targetStore(inst, .{ | 1743 | elf.targetStore(inst, .{ |
| 1725 | .b0_4 = elf.targetLoad(inst).b0_4, | 1744 | .b0_4 = elf.targetLoad(inst).b0_4, |
| ... | @@ -1728,7 +1747,7 @@ const SymbolReloc = struct { | ... | @@ -1728,7 +1747,7 @@ const SymbolReloc = struct { |
| 1728 | }); | 1747 | }); |
| 1729 | }, | 1748 | }, |
| 1730 | .larch_pcala64_lo20 => { | 1749 | .larch_pcala64_lo20 => { |
| 1731 | const val = target.value(elf) +% normal_addend; | 1750 | const val = target_sym.value(elf) +% normal_addend; |
| 1732 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | 1751 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| 1733 | elf.targetStore(inst, .{ | 1752 | elf.targetStore(inst, .{ |
| 1734 | .b0_4 = elf.targetLoad(inst).b0_4, | 1753 | .b0_4 = elf.targetLoad(inst).b0_4, |
| ... | @@ -1737,7 +1756,7 @@ const SymbolReloc = struct { | ... | @@ -1737,7 +1756,7 @@ const SymbolReloc = struct { |
| 1737 | }); | 1756 | }); |
| 1738 | }, | 1757 | }, |
| 1739 | .larch_pcala64_hi12 => { | 1758 | .larch_pcala64_hi12 => { |
| 1740 | const val = target.value(elf) +% normal_addend; | 1759 | const val = target_sym.value(elf) +% normal_addend; |
| 1741 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); | 1760 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); |
| 1742 | elf.targetStore(inst, .{ | 1761 | elf.targetStore(inst, .{ |
| 1743 | .b0_9 = elf.targetLoad(inst).b0_9, | 1762 | .b0_9 = elf.targetLoad(inst).b0_9, |
| ... | @@ -1746,7 +1765,7 @@ const SymbolReloc = struct { | ... | @@ -1746,7 +1765,7 @@ const SymbolReloc = struct { |
| 1746 | }); | 1765 | }); |
| 1747 | }, | 1766 | }, |
| 1748 | .larch_b21, .larch_b26, .larch_call36 => { | 1767 | .larch_b21, .larch_b26, .larch_call36 => { |
| 1749 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); | 1768 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target_sym) orelse target_sym.value(elf); |
| 1750 | const jump_offset: i64 = @bitCast(target_vaddr +% normal_addend -% dest_vaddr); | 1769 | const jump_offset: i64 = @bitCast(target_vaddr +% normal_addend -% dest_vaddr); |
| 1751 | if ((jump_offset >> 2) << 2 != jump_offset) { | 1770 | if ((jump_offset >> 2) << 2 != jump_offset) { |
| 1752 | return error.RelocationMisaligned; | 1771 | return error.RelocationMisaligned; |
| ... | @@ -1806,9 +1825,43 @@ const SymbolReloc = struct { | ... | @@ -1806,9 +1825,43 @@ const SymbolReloc = struct { |
| 1806 | } | 1825 | } |
| 1807 | }, | 1826 | }, |
| 1808 | | 1827 | |
| | 1828 | .larch_got_pcala_hi20 => { |
| | 1829 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 1830 | const got_offset = elf.got.getIndex(.{ .symbol = target_sym }).? * elf.targetPtrSize(); |
| | 1831 | const val = got_vaddr +% got_offset +% normal_addend; |
| | 1832 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| | 1833 | elf.targetStore(inst, .{ |
| | 1834 | .b0_4 = elf.targetLoad(inst).b0_4, |
| | 1835 | .j20 = link.loongarch.pcalaHi20(val, dest_vaddr), |
| | 1836 | .b25_31 = elf.targetLoad(inst).b25_31, |
| | 1837 | }); |
| | 1838 | }, |
| | 1839 | .larch_got_pcala64_lo20 => { |
| | 1840 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 1841 | const got_offset = elf.got.getIndex(.{ .symbol = target_sym }).? * elf.targetPtrSize(); |
| | 1842 | const val = got_vaddr +% got_offset +% normal_addend; |
| | 1843 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| | 1844 | elf.targetStore(inst, .{ |
| | 1845 | .b0_4 = elf.targetLoad(inst).b0_4, |
| | 1846 | .j20 = link.loongarch.pcala64Lo20(val, dest_vaddr), |
| | 1847 | .b25_31 = elf.targetLoad(inst).b25_31, |
| | 1848 | }); |
| | 1849 | }, |
| | 1850 | .larch_got_pcala64_hi12 => { |
| | 1851 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 1852 | const got_offset = elf.got.getIndex(.{ .symbol = target_sym }).? * elf.targetPtrSize(); |
| | 1853 | const val = got_vaddr +% got_offset +% normal_addend; |
| | 1854 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); |
| | 1855 | elf.targetStore(inst, .{ |
| | 1856 | .b0_9 = elf.targetLoad(inst).b0_9, |
| | 1857 | .k12 = link.loongarch.pcala64Hi12(val, dest_vaddr), |
| | 1858 | .b22_31 = elf.targetLoad(inst).b22_31, |
| | 1859 | }); |
| | 1860 | }, |
| | 1861 | |
| 1809 | .sparc_olo10 => { | 1862 | .sparc_olo10 => { |
| 1810 | const addends = addend.sparc_olo10; | 1863 | const addends = addend.sparc_olo10; |
| 1811 | const lo10: i64 = @as(u10, @truncate(target.value(elf) +% addends.a)); | 1864 | const lo10: i64 = @as(u10, @truncate(target_sym.value(elf) +% addends.a)); |
| 1812 | const simm13 = std.math.cast(i13, lo10 + addends.o) orelse return error.RelocationOverflow; | 1865 | const simm13 = std.math.cast(i13, lo10 + addends.o) orelse return error.RelocationOverflow; |
| 1813 | const dest_ptr: *align(1) packed struct(u32) { | 1866 | const dest_ptr: *align(1) packed struct(u32) { |
| 1814 | simm13: u13, | 1867 | simm13: u13, |
| ... | @@ -1825,7 +1878,7 @@ const SymbolReloc = struct { | ... | @@ -1825,7 +1878,7 @@ const SymbolReloc = struct { |
| 1825 | b22_31: u10, | 1878 | b22_31: u10, |
| 1826 | } = @ptrCast(dest_slice); | 1879 | } = @ptrCast(dest_slice); |
| 1827 | elf.targetStore(dest_ptr, .{ | 1880 | elf.targetStore(dest_ptr, .{ |
| 1828 | .imm22 = @truncate(~(target.value(elf) +% normal_addend) >> 10), | 1881 | .imm22 = @truncate(~(target_sym.value(elf) +% normal_addend) >> 10), |
| 1829 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | 1882 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| 1830 | }); | 1883 | }); |
| 1831 | }, | 1884 | }, |
| ... | @@ -1842,12 +1895,12 @@ const SymbolReloc = struct { | ... | @@ -1842,12 +1895,12 @@ const SymbolReloc = struct { |
| 1842 | b22_31: u10, | 1895 | b22_31: u10, |
| 1843 | } = @ptrCast(dest_slice); | 1896 | } = @ptrCast(dest_slice); |
| 1844 | elf.targetStore(dest_ptr, .{ | 1897 | elf.targetStore(dest_ptr, .{ |
| 1845 | .imm22 = @truncate(~(target.value(elf) +% normal_addend -% tls_size) >> 10), | 1898 | .imm22 = @truncate(~(target_sym.value(elf) +% normal_addend -% tls_size) >> 10), |
| 1846 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | 1899 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| 1847 | }); | 1900 | }); |
| 1848 | }, | 1901 | }, |
| 1849 | .sparc_wdisp16, .sparc_wdisp10 => { | 1902 | .sparc_wdisp16, .sparc_wdisp10 => { |
| 1850 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); | 1903 | const target_vaddr: u64 = elf.pltEntryTargetAddr(target_sym) orelse target_sym.value(elf); |
| 1851 | const jump_offset: i64 = @bitCast(target_vaddr +% normal_addend -% dest_vaddr); | 1904 | const jump_offset: i64 = @bitCast(target_vaddr +% normal_addend -% dest_vaddr); |
| 1852 | if ((jump_offset >> 2) << 2 != jump_offset) { | 1905 | if ((jump_offset >> 2) << 2 != jump_offset) { |
| 1853 | return error.RelocationMisaligned; | 1906 | return error.RelocationMisaligned; |
| ... | @@ -1897,10 +1950,120 @@ const SymbolReloc = struct { | ... | @@ -1897,10 +1950,120 @@ const SymbolReloc = struct { |
| 1897 | else => unreachable, | 1950 | else => unreachable, |
| 1898 | } | 1951 | } |
| 1899 | }, | 1952 | }, |
| | 1953 | |
| | 1954 | .sparc_got_op_lox10 => { |
| | 1955 | const got_offset = elf.got.getIndex(.{ .symbol = target_sym }).? * elf.targetPtrSize(); |
| | 1956 | const dest_ptr: *align(1) packed struct(u32) { |
| | 1957 | imm13: u13, |
| | 1958 | b13_31: u19, |
| | 1959 | } = @ptrCast(dest_slice); |
| | 1960 | elf.targetStore(dest_ptr, .{ |
| | 1961 | .imm13 = @as(u10, @truncate(got_offset)), |
| | 1962 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, |
| | 1963 | }); |
| | 1964 | }, |
| | 1965 | .sparc_got_op_hix22 => { |
| | 1966 | const got_offset = elf.got.getIndex(.{ .symbol = target_sym }).? * elf.targetPtrSize(); |
| | 1967 | const dest_ptr: *align(1) packed struct(u32) { |
| | 1968 | imm22: u22, |
| | 1969 | b22_31: u10, |
| | 1970 | } = @ptrCast(dest_slice); |
| | 1971 | elf.targetStore(dest_ptr, .{ |
| | 1972 | .imm22 = @truncate(got_offset >> 10), |
| | 1973 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| | 1974 | }); |
| | 1975 | }, |
| 1900 | } | 1976 | } |
| 1901 | } | 1977 | } |
| 1902 | }; | 1978 | }; |
| 1903 | | 1979 | |
| | 1980 | fn needsGotEntry(t: SymbolReloc.Type) ?enum { symbol, tpoff, tlsgd } { |
| | 1981 | return switch (t.target) { |
| | 1982 | .abs, |
| | 1983 | .rel, |
| | 1984 | .pltabs, |
| | 1985 | .pltrel, |
| | 1986 | .dtpoff, |
| | 1987 | .tpoff, |
| | 1988 | .size, |
| | 1989 | => null, |
| | 1990 | |
| | 1991 | .gotabs_symbol, .gotrel_symbol, .gotoff_symbol => .symbol, |
| | 1992 | .gotabs_tpoff, .gotrel_tpoff, .gotoff_tpoff => .tpoff, |
| | 1993 | .gotabs_tlsgd, .gotrel_tlsgd, .gotoff_tlsgd => .tlsgd, |
| | 1994 | |
| | 1995 | .special => switch (t.action.special) { |
| | 1996 | .larch_pcala_hi20, |
| | 1997 | .larch_pcala64_lo20, |
| | 1998 | .larch_pcala64_hi12, |
| | 1999 | .larch_b21, |
| | 2000 | .larch_b26, |
| | 2001 | .larch_call36, |
| | 2002 | .sparc_olo10, |
| | 2003 | .sparc_hix22, |
| | 2004 | .sparc_le_hix22, |
| | 2005 | .sparc_wdisp10, |
| | 2006 | .sparc_wdisp16, |
| | 2007 | => null, |
| | 2008 | |
| | 2009 | .larch_got_pcala_hi20, |
| | 2010 | .larch_got_pcala64_lo20, |
| | 2011 | .larch_got_pcala64_hi12, |
| | 2012 | .sparc_got_op_lox10, |
| | 2013 | .sparc_got_op_hix22, |
| | 2014 | => .symbol, |
| | 2015 | }, |
| | 2016 | }; |
| | 2017 | } |
| | 2018 | |
| | 2019 | fn dependsOnGotAddress(t: SymbolReloc.Type) bool { |
| | 2020 | return switch (t.target) { |
| | 2021 | .abs, |
| | 2022 | .rel, |
| | 2023 | .pltabs, |
| | 2024 | .pltrel, |
| | 2025 | .dtpoff, |
| | 2026 | .tpoff, |
| | 2027 | .size, |
| | 2028 | => false, |
| | 2029 | |
| | 2030 | .gotabs_symbol, |
| | 2031 | .gotrel_symbol, |
| | 2032 | .gotabs_tpoff, |
| | 2033 | .gotrel_tpoff, |
| | 2034 | .gotabs_tlsgd, |
| | 2035 | .gotrel_tlsgd, |
| | 2036 | => true, |
| | 2037 | |
| | 2038 | .gotoff_symbol, |
| | 2039 | .gotoff_tpoff, |
| | 2040 | .gotoff_tlsgd, |
| | 2041 | => false, |
| | 2042 | |
| | 2043 | .special => switch (t.action.special) { |
| | 2044 | .larch_pcala_hi20, |
| | 2045 | .larch_pcala64_lo20, |
| | 2046 | .larch_pcala64_hi12, |
| | 2047 | .larch_b21, |
| | 2048 | .larch_b26, |
| | 2049 | .larch_call36, |
| | 2050 | .sparc_olo10, |
| | 2051 | .sparc_hix22, |
| | 2052 | .sparc_le_hix22, |
| | 2053 | .sparc_wdisp10, |
| | 2054 | .sparc_wdisp16, |
| | 2055 | => false, |
| | 2056 | |
| | 2057 | .larch_got_pcala_hi20, |
| | 2058 | .larch_got_pcala64_lo20, |
| | 2059 | .larch_got_pcala64_hi12, |
| | 2060 | .sparc_got_op_lox10, |
| | 2061 | .sparc_got_op_hix22, |
| | 2062 | => true, |
| | 2063 | }, |
| | 2064 | }; |
| | 2065 | } |
| | 2066 | |
| 1904 | fn dependsOnTlsSize(t: SymbolReloc.Type, elf: *const Elf) bool { | 2067 | fn dependsOnTlsSize(t: SymbolReloc.Type, elf: *const Elf) bool { |
| 1905 | return switch (elf.targetTlsVariant()) { | 2068 | return switch (elf.targetTlsVariant()) { |
| 1906 | // In TLS variant I, the executable's TLS block starts at a fixed offset from the | 2069 | // In TLS variant I, the executable's TLS block starts at a fixed offset from the |
| ... | @@ -1917,6 +2080,15 @@ const SymbolReloc = struct { | ... | @@ -1917,6 +2080,15 @@ const SymbolReloc = struct { |
| 1917 | .pltrel, | 2080 | .pltrel, |
| 1918 | .dtpoff, | 2081 | .dtpoff, |
| 1919 | .size, | 2082 | .size, |
| | 2083 | .gotabs_symbol, |
| | 2084 | .gotrel_symbol, |
| | 2085 | .gotoff_symbol, |
| | 2086 | .gotabs_tpoff, |
| | 2087 | .gotrel_tpoff, |
| | 2088 | .gotoff_tpoff, |
| | 2089 | .gotabs_tlsgd, |
| | 2090 | .gotrel_tlsgd, |
| | 2091 | .gotoff_tlsgd, |
| 1920 | => false, | 2092 | => false, |
| 1921 | | 2093 | |
| 1922 | .tpoff => true, | 2094 | .tpoff => true, |
| ... | @@ -1931,11 +2103,16 @@ const SymbolReloc = struct { | ... | @@ -1931,11 +2103,16 @@ const SymbolReloc = struct { |
| 1931 | .larch_b21, | 2103 | .larch_b21, |
| 1932 | .larch_b26, | 2104 | .larch_b26, |
| 1933 | .larch_call36, | 2105 | .larch_call36, |
| | 2106 | .larch_got_pcala_hi20, |
| | 2107 | .larch_got_pcala64_lo20, |
| | 2108 | .larch_got_pcala64_hi12, |
| 1934 | | 2109 | |
| 1935 | .sparc_olo10, | 2110 | .sparc_olo10, |
| 1936 | .sparc_hix22, | 2111 | .sparc_hix22, |
| 1937 | .sparc_wdisp10, | 2112 | .sparc_wdisp10, |
| 1938 | .sparc_wdisp16, | 2113 | .sparc_wdisp16, |
| | 2114 | .sparc_got_op_lox10, |
| | 2115 | .sparc_got_op_hix22, |
| 1939 | => false, | 2116 | => false, |
| 1940 | }, | 2117 | }, |
| 1941 | }, | 2118 | }, |
| ... | @@ -1954,7 +2131,7 @@ const SymbolReloc = struct { | ... | @@ -1954,7 +2131,7 @@ const SymbolReloc = struct { |
| 1954 | | 2131 | |
| 1955 | fn apply(reloc: *SymbolReloc, elf: *Elf) void { | 2132 | fn apply(reloc: *SymbolReloc, elf: *Elf) void { |
| 1956 | const node = reloc.node.unwrap() orelse return; // deleted | 2133 | const node = reloc.node.unwrap() orelse return; // deleted |
| 1957 | if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) { | 2134 | if (node.hasMoved(&elf.mf) or reloc.target_symbol.hasMoved(elf)) { |
| 1958 | // There's no point applying the relocation now, because it will be re-applied by | 2135 | // There's no point applying the relocation now, because it will be re-applied by |
| 1959 | // `flushMoved` at some point anyway. | 2136 | // `flushMoved` at some point anyway. |
| 1960 | return; | 2137 | return; |
| ... | @@ -1966,7 +2143,7 @@ const SymbolReloc = struct { | ... | @@ -1966,7 +2143,7 @@ const SymbolReloc = struct { |
| 1966 | reloc.relaSection(elf).relaSetOffset(elf, rela_index, reloc_addr); | 2143 | reloc.relaSection(elf).relaSetOffset(elf, rela_index, reloc_addr); |
| 1967 | return; | 2144 | return; |
| 1968 | } | 2145 | } |
| 1969 | switch (reloc.result) { | 2146 | switch (reloc.bits.result) { |
| 1970 | .ok => {}, | 2147 | .ok => {}, |
| 1971 | .overflowed => elf.overflowed_reloc_count -= 1, | 2148 | .overflowed => elf.overflowed_reloc_count -= 1, |
| 1972 | .misaligned => elf.misaligned_reloc_count -= 1, | 2149 | .misaligned => elf.misaligned_reloc_count -= 1, |
| ... | @@ -1977,14 +2154,14 @@ const SymbolReloc = struct { | ... | @@ -1977,14 +2154,14 @@ const SymbolReloc = struct { |
| 1977 | } | 2154 | } |
| 1978 | if (reloc.applyInner(elf)) { | 2155 | if (reloc.applyInner(elf)) { |
| 1979 | @branchHint(.likely); | 2156 | @branchHint(.likely); |
| 1980 | reloc.result = .ok; | 2157 | reloc.bits.result = .ok; |
| 1981 | } else |err| switch (err) { | 2158 | } else |err| switch (err) { |
| 1982 | error.RelocationOverflow => { | 2159 | error.RelocationOverflow => { |
| 1983 | reloc.result = .overflowed; | 2160 | reloc.bits.result = .overflowed; |
| 1984 | elf.overflowed_reloc_count += 1; | 2161 | elf.overflowed_reloc_count += 1; |
| 1985 | }, | 2162 | }, |
| 1986 | error.RelocationMisaligned => { | 2163 | error.RelocationMisaligned => { |
| 1987 | reloc.result = .misaligned; | 2164 | reloc.bits.result = .misaligned; |
| 1988 | elf.misaligned_reloc_count += 1; | 2165 | elf.misaligned_reloc_count += 1; |
| 1989 | }, | 2166 | }, |
| 1990 | } | 2167 | } |
| ... | @@ -1995,21 +2172,21 @@ const SymbolReloc = struct { | ... | @@ -1995,21 +2172,21 @@ const SymbolReloc = struct { |
| 1995 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; | 2172 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| 1996 | | 2173 | |
| 1997 | const addend: u64 = @bitCast(reloc.addend); | 2174 | const addend: u64 = @bitCast(reloc.addend); |
| 1998 | const target_val: u64 = type: switch (reloc.type.target) { | 2175 | const target_val: u64 = type: switch (reloc.bits.type.target) { |
| 1999 | .abs => reloc.target.value(elf) +% addend, | 2176 | .abs => reloc.target_symbol.value(elf) +% addend, |
| 2000 | .rel => reloc.target.value(elf) +% addend -% dest_vaddr, | 2177 | .rel => reloc.target_symbol.value(elf) +% addend -% dest_vaddr, |
| 2001 | .pltabs => { | 2178 | .pltabs => { |
| 2002 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .abs; | 2179 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target_symbol) orelse continue :type .abs; |
| 2003 | break :type plt_entry_addr +% addend; | 2180 | break :type plt_entry_addr +% addend; |
| 2004 | }, | 2181 | }, |
| 2005 | .pltrel => { | 2182 | .pltrel => { |
| 2006 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .rel; | 2183 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target_symbol) orelse continue :type .rel; |
| 2007 | break :type plt_entry_addr +% addend -% dest_vaddr; | 2184 | break :type plt_entry_addr +% addend -% dest_vaddr; |
| 2008 | }, | 2185 | }, |
| 2009 | .dtpoff => reloc.target.value(elf) +% addend, | 2186 | .dtpoff => reloc.target_symbol.value(elf) +% addend, |
| 2010 | .tpoff => switch (elf.targetTlsVariant()) { | 2187 | .tpoff => switch (elf.targetTlsVariant()) { |
| 2011 | .I_original => |tls| tls.tcb_size +% reloc.target.value(elf) +% addend, | 2188 | .I_original => |tls| tls.tcb_size +% reloc.target_symbol.value(elf) +% addend, |
| 2012 | .I_modified => |tls| 0 -% tls.tp_off +% reloc.target.value(elf) +% addend, | 2189 | .I_modified => |tls| 0 -% tls.tp_off +% reloc.target_symbol.value(elf) +% addend, |
| 2013 | .II => { | 2190 | .II => { |
| 2014 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; | 2191 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; |
| 2015 | const tls_size: u64 = switch (elf.phdrSlice()) { | 2192 | const tls_size: u64 = switch (elf.phdrSlice()) { |
| ... | @@ -2018,13 +2195,57 @@ const SymbolReloc = struct { | ... | @@ -2018,13 +2195,57 @@ const SymbolReloc = struct { |
| 2018 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); | 2195 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); |
| 2019 | }, | 2196 | }, |
| 2020 | }; | 2197 | }; |
| 2021 | break :type reloc.target.value(elf) +% addend -% tls_size; | 2198 | break :type reloc.target_symbol.value(elf) +% addend -% tls_size; |
| 2022 | }, | 2199 | }, |
| 2023 | }, | 2200 | }, |
| 2024 | .size => reloc.target.size(elf), | 2201 | .size => reloc.target_symbol.size(elf), |
| 2025 | .special => return reloc.type.action.special.applyInner( | 2202 | |
| | 2203 | .gotabs_symbol => { |
| | 2204 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2205 | const got_offset = elf.got.getIndex(.{ .symbol = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2206 | break :type (got_vaddr + got_offset) +% addend; |
| | 2207 | }, |
| | 2208 | .gotrel_symbol => { |
| | 2209 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2210 | const got_offset = elf.got.getIndex(.{ .symbol = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2211 | break :type (got_vaddr + got_offset) +% addend -% dest_vaddr; |
| | 2212 | }, |
| | 2213 | .gotoff_symbol => { |
| | 2214 | const got_offset = elf.got.getIndex(.{ .symbol = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2215 | break :type got_offset +% addend; |
| | 2216 | }, |
| | 2217 | .gotabs_tpoff => { |
| | 2218 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2219 | const got_offset = elf.got.getIndex(.{ .tpoff = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2220 | break :type (got_vaddr + got_offset) +% addend; |
| | 2221 | }, |
| | 2222 | .gotrel_tpoff => { |
| | 2223 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2224 | const got_offset = elf.got.getIndex(.{ .tpoff = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2225 | break :type (got_vaddr + got_offset) +% addend -% dest_vaddr; |
| | 2226 | }, |
| | 2227 | .gotoff_tpoff => { |
| | 2228 | const got_offset = elf.got.getIndex(.{ .tpoff = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2229 | break :type got_offset +% addend; |
| | 2230 | }, |
| | 2231 | .gotabs_tlsgd => { |
| | 2232 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2233 | const got_offset = elf.got.getIndex(.{ .tlsgd0 = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2234 | break :type (got_vaddr + got_offset) +% addend; |
| | 2235 | }, |
| | 2236 | .gotrel_tlsgd => { |
| | 2237 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2238 | const got_offset = elf.got.getIndex(.{ .tlsgd0 = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2239 | break :type (got_vaddr + got_offset) +% addend -% dest_vaddr; |
| | 2240 | }, |
| | 2241 | .gotoff_tlsgd => { |
| | 2242 | const got_offset = elf.got.getIndex(.{ .tlsgd0 = reloc.target_symbol }).? * elf.targetPtrSize(); |
| | 2243 | break :type got_offset +% addend; |
| | 2244 | }, |
| | 2245 | |
| | 2246 | .special => return reloc.bits.type.action.special.applyInner( |
| 2026 | elf, | 2247 | elf, |
| 2027 | reloc.target, | 2248 | reloc.target_symbol, |
| 2028 | reloc.addend, | 2249 | reloc.addend, |
| 2029 | dest_vaddr, | 2250 | dest_vaddr, |
| 2030 | dest_slice, | 2251 | dest_slice, |
| ... | @@ -2033,7 +2254,7 @@ const SymbolReloc = struct { | ... | @@ -2033,7 +2254,7 @@ const SymbolReloc = struct { |
| 2033 | | 2254 | |
| 2034 | // Check for the `R_*_RELATIVE` case now, because it is possible only when no shift or cast | 2255 | // Check for the `R_*_RELATIVE` case now, because it is possible only when no shift or cast |
| 2035 | // is required, meaning we can handle it now and return early. | 2256 | // is required, meaning we can handle it now and return early. |
| 2036 | if (reloc.rela_index.unwrap()) |rela_index| switch (elf.classifySymbolValue(reloc.target)) { | 2257 | if (reloc.rela_index.unwrap()) |rela_index| switch (elf.classifySymbolValue(reloc.target_symbol)) { |
| 2037 | .static => unreachable, | 2258 | .static => unreachable, |
| 2038 | .dynamic => { | 2259 | .dynamic => { |
| 2039 | // The relocation happens at runtime; we just need to update its offset. | 2260 | // The relocation happens at runtime; we just need to update its offset. |
| ... | @@ -2046,31 +2267,34 @@ const SymbolReloc = struct { | ... | @@ -2046,31 +2267,34 @@ const SymbolReloc = struct { |
| 2046 | // destination slice, we actually want to write it to the runtime relocation entry. | 2267 | // destination slice, we actually want to write it to the runtime relocation entry. |
| 2047 | switch (elf.identClass()) { | 2268 | switch (elf.identClass()) { |
| 2048 | .NONE, _ => unreachable, | 2269 | .NONE, _ => unreachable, |
| 2049 | .@"32" => assert(reloc.type.action.simple.dest == .@"32"), | 2270 | .@"32" => assert(reloc.bits.type.action.simple.dest == .@"32"), |
| 2050 | .@"64" => assert(reloc.type.action.simple.dest == .@"64"), | 2271 | .@"64" => assert(reloc.bits.type.action.simple.dest == .@"64"), |
| 2051 | } | 2272 | } |
| 2052 | assert(reloc.type.action.simple.cast == .unsigned); | 2273 | assert(reloc.bits.type.action.simple.cast == .unsigned); |
| 2053 | assert(reloc.type.action.simple.shift == .@"0"); | 2274 | assert(reloc.bits.type.action.simple.shift == .@"0"); |
| 2054 | elf.shndx.rela_dyn.relaSetOffset(elf, rela_index, dest_vaddr); | 2275 | elf.shndx.rela_dyn.relaSetOffset(elf, rela_index, dest_vaddr); |
| 2055 | elf.shndx.rela_dyn.relaSetAddend(elf, rela_index, target_val); | 2276 | elf.shndx.rela_dyn.relaSetAddend(elf, rela_index, target_val); |
| 2056 | return; | 2277 | return; |
| 2057 | }, | 2278 | }, |
| 2058 | }; | 2279 | }; |
| 2059 | | 2280 | |
| 2060 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | 2281 | try reloc.bits.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); |
| 2061 | } | 2282 | } |
| 2062 | | 2283 | |
| 2063 | fn delete(reloc: *SymbolReloc, elf: *Elf, index: SymbolReloc.Index) void { | 2284 | fn delete(reloc: *SymbolReloc, elf: *Elf, index: SymbolReloc.Index) void { |
| 2064 | assert(index.get(elf) == reloc); | 2285 | assert(index.get(elf) == reloc); |
| 2065 | | 2286 | |
| 2066 | reloc.deleteOutputRel(elf); | 2287 | reloc.deleteOutputRel(elf); |
| 2067 | if (reloc.type.dependsOnTlsSize(elf)) { | 2288 | if (reloc.bits.type.dependsOnTlsSize(elf)) { |
| 2068 | assert(elf.tls_size_symbol_relocs.swapRemove(index)); | 2289 | assert(elf.tls_size_symbol_relocs.swapRemove(index)); |
| 2069 | } | 2290 | } |
| | 2291 | if (reloc.bits.type.dependsOnGotAddress()) { |
| | 2292 | assert(elf.got_relocs.swapRemove(index)); |
| | 2293 | } |
| 2070 | | 2294 | |
| 2071 | switch (reloc.prev) { | 2295 | switch (reloc.prev) { |
| 2072 | .none => { | 2296 | .none => { |
| 2073 | const first_target_reloc = &reloc.target.index(elf).ptr(elf).first_target_reloc; | 2297 | const first_target_reloc = &reloc.target_symbol.index(elf).ptr(elf).first_target_reloc; |
| 2074 | assert(first_target_reloc.* == index); | 2298 | assert(first_target_reloc.* == index); |
| 2075 | first_target_reloc.* = reloc.next; | 2299 | first_target_reloc.* = reloc.next; |
| 2076 | }, | 2300 | }, |
| ... | @@ -2080,7 +2304,7 @@ const SymbolReloc = struct { | ... | @@ -2080,7 +2304,7 @@ const SymbolReloc = struct { |
| 2080 | .none => {}, | 2304 | .none => {}, |
| 2081 | else => |next| next.get(elf).prev = reloc.prev, | 2305 | else => |next| next.get(elf).prev = reloc.prev, |
| 2082 | } | 2306 | } |
| 2083 | switch (reloc.result) { | 2307 | switch (reloc.bits.result) { |
| 2084 | .ok => {}, | 2308 | .ok => {}, |
| 2085 | .overflowed => elf.overflowed_reloc_count -= 1, | 2309 | .overflowed => elf.overflowed_reloc_count -= 1, |
| 2086 | .misaligned => elf.misaligned_reloc_count -= 1, | 2310 | .misaligned => elf.misaligned_reloc_count -= 1, |
| ... | @@ -2113,25 +2337,25 @@ const SymbolReloc = struct { | ... | @@ -2113,25 +2337,25 @@ const SymbolReloc = struct { |
| 2113 | const reloc_node = reloc.node.unwrap().?; // deleted | 2337 | const reloc_node = reloc.node.unwrap().?; // deleted |
| 2114 | | 2338 | |
| 2115 | // Delete any current output relocation or error. | 2339 | // Delete any current output relocation or error. |
| 2116 | switch (reloc.result) { | 2340 | switch (reloc.bits.result) { |
| 2117 | .ok, .overflowed, .misaligned => { | 2341 | .ok, .overflowed, .misaligned => { |
| 2118 | reloc.deleteOutputRel(elf); | 2342 | reloc.deleteOutputRel(elf); |
| 2119 | }, | 2343 | }, |
| 2120 | .illegal_dynamic_type => { | 2344 | .illegal_dynamic_type => { |
| 2121 | elf.illegal_dynamic_type_reloc_count -= 1; | 2345 | elf.illegal_dynamic_type_reloc_count -= 1; |
| 2122 | reloc.result = .ok; | 2346 | reloc.bits.result = .ok; |
| 2123 | }, | 2347 | }, |
| 2124 | .illegal_dynamic_section => { | 2348 | .illegal_dynamic_section => { |
| 2125 | elf.illegal_dynamic_section_reloc_count -= 1; | 2349 | elf.illegal_dynamic_section_reloc_count -= 1; |
| 2126 | reloc.result = .ok; | 2350 | reloc.bits.result = .ok; |
| 2127 | }, | 2351 | }, |
| 2128 | } | 2352 | } |
| 2129 | | 2353 | |
| 2130 | assert(reloc.rela_index == .none); | 2354 | assert(reloc.rela_index == .none); |
| 2131 | | 2355 | |
| 2132 | const symbol_class = elf.classifySymbolValue(reloc.target); | 2356 | const symbol_class = elf.classifySymbolValue(reloc.target_symbol); |
| 2133 | | 2357 | |
| 2134 | switch (reloc.target.unwrap()) { | 2358 | switch (reloc.target_symbol.unwrap()) { |
| 2135 | .local => {}, | 2359 | .local => {}, |
| 2136 | .global => |gsi| switch (symbol_class) { | 2360 | .global => |gsi| switch (symbol_class) { |
| 2137 | .static => gsi.ptr(elf).status.any_static_target_relocs = true, | 2361 | .static => gsi.ptr(elf).status.any_static_target_relocs = true, |
| ... | @@ -2152,25 +2376,36 @@ const SymbolReloc = struct { | ... | @@ -2152,25 +2376,36 @@ const SymbolReloc = struct { |
| 2152 | } = switch (symbol_class) { | 2376 | } = switch (symbol_class) { |
| 2153 | .static => return, | 2377 | .static => return, |
| 2154 | | 2378 | |
| 2155 | .static_relative => switch (reloc.type.target) { | 2379 | .static_relative => switch (reloc.bits.type.target) { |
| 2156 | // We need a runtime relocation if the relocation depends on our load address, which | 2380 | // We need a runtime relocation if the relocation depends on our load address, which |
| 2157 | // is the case iff the relocation resolves to the absolute value of a symbol. Relocs | 2381 | // is the case iff the relocation resolves to the absolute value of a symbol. Relocs |
| 2158 | // which are PC-relative, or which resolve to something other than a symbol address | 2382 | // which are PC-relative, or which resolve to something other than a symbol address |
| 2159 | // (e.g. a symbol's size), are fine. | 2383 | // (e.g. a symbol's size), are fine. |
| 2160 | | 2384 | |
| 2161 | .pltrel, | 2385 | .pltrel, |
| | 2386 | .gotrel_symbol, |
| | 2387 | .gotoff_symbol, |
| | 2388 | .gotrel_tpoff, |
| | 2389 | .gotoff_tpoff, |
| | 2390 | .gotrel_tlsgd, |
| | 2391 | .gotoff_tlsgd, |
| 2162 | .rel, | 2392 | .rel, |
| 2163 | .size, | 2393 | .size, |
| 2164 | .dtpoff, | 2394 | .dtpoff, |
| 2165 | .tpoff, | 2395 | .tpoff, |
| 2166 | => return, | 2396 | => return, |
| 2167 | | 2397 | |
| 2168 | .abs, .pltabs => switch (reloc.type.action.simple.dest.isAddr(elf)) { | 2398 | .abs, |
| | 2399 | .pltabs, |
| | 2400 | .gotabs_symbol, |
| | 2401 | .gotabs_tpoff, |
| | 2402 | .gotabs_tlsgd, |
| | 2403 | => switch (reloc.bits.type.action.simple.dest.isAddr(elf)) { |
| 2169 | true => .relative, | 2404 | true => .relative, |
| 2170 | false => .illegal, | 2405 | false => .illegal, |
| 2171 | }, | 2406 | }, |
| 2172 | | 2407 | |
| 2173 | .special => switch (reloc.type.action.special) { | 2408 | .special => switch (reloc.bits.type.action.special) { |
| 2174 | .larch_pcala_hi20, | 2409 | .larch_pcala_hi20, |
| 2175 | .larch_pcala64_lo20, | 2410 | .larch_pcala64_lo20, |
| 2176 | .larch_pcala64_hi12, | 2411 | .larch_pcala64_hi12, |
| ... | @@ -2180,6 +2415,11 @@ const SymbolReloc = struct { | ... | @@ -2180,6 +2415,11 @@ const SymbolReloc = struct { |
| 2180 | .sparc_wdisp10, | 2415 | .sparc_wdisp10, |
| 2181 | .sparc_wdisp16, | 2416 | .sparc_wdisp16, |
| 2182 | .sparc_le_hix22, | 2417 | .sparc_le_hix22, |
| | 2418 | .larch_got_pcala_hi20, |
| | 2419 | .larch_got_pcala64_lo20, |
| | 2420 | .larch_got_pcala64_hi12, |
| | 2421 | .sparc_got_op_lox10, |
| | 2422 | .sparc_got_op_hix22, |
| 2183 | => return, | 2423 | => return, |
| 2184 | | 2424 | |
| 2185 | .sparc_olo10, | 2425 | .sparc_olo10, |
| ... | @@ -2188,44 +2428,60 @@ const SymbolReloc = struct { | ... | @@ -2188,44 +2428,60 @@ const SymbolReloc = struct { |
| 2188 | }, | 2428 | }, |
| 2189 | }, | 2429 | }, |
| 2190 | | 2430 | |
| 2191 | .dynamic => switch (reloc.type.target) { | 2431 | .dynamic => switch (reloc.bits.type.target) { |
| 2192 | // PLT relocations targeting dynamic symbols actually target that symbol's PLT | 2432 | // PLT/GOT relocations targeting dynamic symbols actually target that symbol's PLT |
| 2193 | // entry, so we should emit an `R_*_RELATIVE` relocation instead. | 2433 | // or GOT entry, so we should emit an `R_*_RELATIVE` relocation instead. |
| 2194 | .pltabs => switch (reloc.type.action.simple.dest.isAddr(elf)) { | 2434 | .pltabs, |
| | 2435 | .gotabs_symbol, |
| | 2436 | .gotabs_tpoff, |
| | 2437 | .gotabs_tlsgd, |
| | 2438 | => switch (reloc.bits.type.action.simple.dest.isAddr(elf)) { |
| 2195 | true => .relative, | 2439 | true => .relative, |
| 2196 | false => .illegal, | 2440 | false => .illegal, |
| 2197 | }, | 2441 | }, |
| 2198 | // ...although PC-relative PLT relocations don't even need that that! | 2442 | // ...although PC-relative PLT/GOT relocations don't even need that that! |
| 2199 | .pltrel => return, | 2443 | .pltrel, |
| | 2444 | .gotrel_symbol, |
| | 2445 | .gotoff_symbol, |
| | 2446 | .gotrel_tpoff, |
| | 2447 | .gotoff_tpoff, |
| | 2448 | .gotrel_tlsgd, |
| | 2449 | .gotoff_tlsgd, |
| | 2450 | => return, |
| 2200 | // PC-relative relocations are not valid dynamic relocations. | 2451 | // PC-relative relocations are not valid dynamic relocations. |
| 2201 | .rel => .illegal, | 2452 | .rel => .illegal, |
| 2202 | // On the few targets supporting size relocations, they are valid at runtime. | 2453 | // On the few targets supporting size relocations, they are valid at runtime. |
| 2203 | .size => switch (reloc.type.action.simple.dest) { | 2454 | .size => switch (reloc.bits.type.action.simple.dest) { |
| 2204 | .@"32" => .size32, | 2455 | .@"32" => .size32, |
| 2205 | .@"64" => .size64, | 2456 | .@"64" => .size64, |
| 2206 | else => .illegal, | 2457 | else => .illegal, |
| 2207 | }, | 2458 | }, |
| 2208 | // Absolute addresses and TLS offsets can be lowered at runtime provided they | 2459 | // Absolute addresses and TLS offsets can be lowered at runtime provided they |
| 2209 | // are address-sized. | 2460 | // are address-sized. |
| 2210 | .dtpoff => switch (reloc.type.action.simple.dest.isAddr(elf)) { | 2461 | .dtpoff => switch (reloc.bits.type.action.simple.dest.isAddr(elf)) { |
| 2211 | true => .dtp_off, | 2462 | true => .dtp_off, |
| 2212 | false => .illegal, | 2463 | false => .illegal, |
| 2213 | }, | 2464 | }, |
| 2214 | .tpoff => switch (reloc.type.action.simple.dest.isAddr(elf)) { | 2465 | .tpoff => switch (reloc.bits.type.action.simple.dest.isAddr(elf)) { |
| 2215 | true => .tp_off, | 2466 | true => .tp_off, |
| 2216 | false => .illegal, | 2467 | false => .illegal, |
| 2217 | }, | 2468 | }, |
| 2218 | .abs => switch (reloc.type.action.simple.dest.isAddr(elf)) { | 2469 | .abs => switch (reloc.bits.type.action.simple.dest.isAddr(elf)) { |
| 2219 | true => .abs_addr, | 2470 | true => .abs_addr, |
| 2220 | false => .illegal, | 2471 | false => .illegal, |
| 2221 | }, | 2472 | }, |
| 2222 | | 2473 | |
| 2223 | .special => switch (reloc.type.action.special) { | 2474 | .special => switch (reloc.bits.type.action.special) { |
| 2224 | .larch_b21, | 2475 | .larch_b21, |
| 2225 | .larch_b26, | 2476 | .larch_b26, |
| 2226 | .larch_call36, | 2477 | .larch_call36, |
| 2227 | .sparc_wdisp10, | 2478 | .sparc_wdisp10, |
| 2228 | .sparc_wdisp16, | 2479 | .sparc_wdisp16, |
| | 2480 | .larch_got_pcala_hi20, |
| | 2481 | .larch_got_pcala64_lo20, |
| | 2482 | .larch_got_pcala64_hi12, |
| | 2483 | .sparc_got_op_lox10, |
| | 2484 | .sparc_got_op_hix22, |
| 2229 | => return, | 2485 | => return, |
| 2230 | | 2486 | |
| 2231 | .larch_pcala_hi20, | 2487 | .larch_pcala_hi20, |
| ... | @@ -2255,7 +2511,7 @@ const SymbolReloc = struct { | ... | @@ -2255,7 +2511,7 @@ const SymbolReloc = struct { |
| 2255 | .abs_addr, | 2511 | .abs_addr, |
| 2256 | .dtp_off, | 2512 | .dtp_off, |
| 2257 | .tp_off, | 2513 | .tp_off, |
| 2258 | => switch (reloc.target.unwrap()) { | 2514 | => switch (reloc.target_symbol.unwrap()) { |
| 2259 | .local => true, | 2515 | .local => true, |
| 2260 | .global => |gsi| gsi.resolveAlias(elf).defined(elf), | 2516 | .global => |gsi| gsi.resolveAlias(elf).defined(elf), |
| 2261 | }, | 2517 | }, |
| ... | @@ -2267,7 +2523,7 @@ const SymbolReloc = struct { | ... | @@ -2267,7 +2523,7 @@ const SymbolReloc = struct { |
| 2267 | }; | 2523 | }; |
| 2268 | if (!allow) { | 2524 | if (!allow) { |
| 2269 | // ...but in this case we actually do need to trigger an error. | 2525 | // ...but in this case we actually do need to trigger an error. |
| 2270 | reloc.result = .illegal_dynamic_section; | 2526 | reloc.bits.result = .illegal_dynamic_section; |
| 2271 | elf.illegal_dynamic_section_reloc_count += 1; | 2527 | elf.illegal_dynamic_section_reloc_count += 1; |
| 2272 | } | 2528 | } |
| 2273 | return; | 2529 | return; |
| ... | @@ -2278,7 +2534,7 @@ const SymbolReloc = struct { | ... | @@ -2278,7 +2534,7 @@ const SymbolReloc = struct { |
| 2278 | | 2534 | |
| 2279 | const rel_type: MachineRelocType = rel: switch (want_dynamic_reloc) { | 2535 | const rel_type: MachineRelocType = rel: switch (want_dynamic_reloc) { |
| 2280 | .illegal => { | 2536 | .illegal => { |
| 2281 | reloc.result = .illegal_dynamic_type; | 2537 | reloc.bits.result = .illegal_dynamic_type; |
| 2282 | elf.illegal_dynamic_type_reloc_count += 1; | 2538 | elf.illegal_dynamic_type_reloc_count += 1; |
| 2283 | return; | 2539 | return; |
| 2284 | }, | 2540 | }, |
| ... | @@ -2292,7 +2548,7 @@ const SymbolReloc = struct { | ... | @@ -2292,7 +2548,7 @@ const SymbolReloc = struct { |
| 2292 | const target_dynsym: u32 = switch (want_dynamic_reloc) { | 2548 | const target_dynsym: u32 = switch (want_dynamic_reloc) { |
| 2293 | .illegal => unreachable, // handled above | 2549 | .illegal => unreachable, // handled above |
| 2294 | .relative => 0, | 2550 | .relative => 0, |
| 2295 | else => reloc.target.unwrap().global.dynsymIndex(elf).?, | 2551 | else => reloc.target_symbol.unwrap().global.dynsymIndex(elf).?, |
| 2296 | }; | 2552 | }; |
| 2297 | | 2553 | |
| 2298 | try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, 1); | 2554 | try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, 1); |
| ... | @@ -2435,227 +2691,20 @@ const GotKey = union(enum) { | ... | @@ -2435,227 +2691,20 @@ const GotKey = union(enum) { |
| 2435 | /// Value is the signed offset of the given symbol from the TLS pointer. | 2691 | /// Value is the signed offset of the given symbol from the TLS pointer. |
| 2436 | tpoff: Symbol.Id, | 2692 | tpoff: Symbol.Id, |
| 2437 | | 2693 | |
| 2438 | /// Value is the TLS module ID of the DSO we are creating. | 2694 | /// Value is the TLS module ID for the given STT_TLS symbol. Alternatively, it may be set to |
| 2439 | /// | 2695 | /// `Symbol.Id.null` to resolve to the TLS module ID of this module (for TLSLD relocations). |
| 2440 | /// Used for the first of the two GOT entries generated by a TLSLD relocation. | | |
| 2441 | tlsld0, | | |
| 2442 | /// Value is always 0. | | |
| 2443 | /// | 2696 | /// |
| 2444 | /// Used for the second of the two GOT entries generated by a TLSLD relocation. | 2697 | /// Alternative |
| 2445 | tlsld1, | | |
| 2446 | | | |
| 2447 | /// Value is the TLS module ID for the given STT_TLS symbol. | | |
| 2448 | /// | 2698 | /// |
| 2449 | /// Used for the first of the two GOT entries generated by a TLSGD relocation. | 2699 | /// Used for the first of the two GOT entries generated by a TLSGD relocation. |
| 2450 | tlsgd0: Symbol.Id, | 2700 | tlsgd0: Symbol.Id, |
| 2451 | /// Value is the offset of the given STT_TLS symbol from the base of the per-module TLS area. | 2701 | /// Value is the offset of the given STT_TLS symbol from the base of the per-module TLS area. |
| | 2702 | /// Alternatively, it may be set to `Symbol.Id.null` to resolve to 0 (for TLSLD relocations). |
| 2452 | /// | 2703 | /// |
| 2453 | /// Used for the second of the two GOT entries generated by a TLSGD relocation. | 2704 | /// Used for the second of the two GOT entries generated by a TLSGD relocation. |
| 2454 | tlsgd1: Symbol.Id, | 2705 | tlsgd1: Symbol.Id, |
| 2455 | }; | 2706 | }; |
| 2456 | | 2707 | |
| 2457 | /// A relocation targeting a particular GOT entry. | | |
| 2458 | const GotReloc = struct { | | |
| 2459 | /// The node containing this relocation. Possible values are: | | |
| 2460 | /// * An input section | | |
| 2461 | /// * A section | | |
| 2462 | /// * A NAV, UAV, or lazy code/data | | |
| 2463 | /// * `.none`, if this relocation was deleted (in which case it should be ignored) | | |
| 2464 | node: MappedFile.Node.Index.Optional, | | |
| 2465 | /// The offset of the relocation inside of `node`. | | |
| 2466 | offset: u64, | | |
| 2467 | target: GotKey, | | |
| 2468 | addend: i64, | | |
| 2469 | type: GotReloc.Type, | | |
| 2470 | result: enum(u8) { ok, overflowed, misaligned }, | | |
| 2471 | | | |
| 2472 | /// `GotReloc.Type` has the same structure as `SymbolReloc.Type`, just with different `Target` | | |
| 2473 | /// and `Special` enums---consult doc comments on `SymbolReloc.Type` for an overview. | | |
| 2474 | const Type = packed struct(u16) { | | |
| 2475 | fn simple(target: Target, action: Simple) GotReloc.Type { | | |
| 2476 | assert(target != .special); | | |
| 2477 | return .{ .target = target, .action = .{ .simple = action } }; | | |
| 2478 | } | | |
| 2479 | | | |
| 2480 | fn special(s: Special) GotReloc.Type { | | |
| 2481 | return .{ .target = .special, .action = .{ .special = s } }; | | |
| 2482 | } | | |
| 2483 | | | |
| 2484 | target: Target, | | |
| 2485 | action: packed union { | | |
| 2486 | simple: Simple, | | |
| 2487 | special: Special, | | |
| 2488 | }, | | |
| 2489 | | | |
| 2490 | /// Like `SymbolReloc.Target`, but for GOT relocations. There are fewer tags because there | | |
| 2491 | /// are fewer different kinds of GOT relocation. | | |
| 2492 | const Target = enum(u3) { | | |
| 2493 | /// This is a "special" relocation whose specific type is in the `action.special` field. | | |
| 2494 | special, | | |
| 2495 | | | |
| 2496 | /// Absolute address of the GOT entry. | | |
| 2497 | abs, | | |
| 2498 | /// Offset from the relocation itself to the GOT entry ("PC-relative"). | | |
| 2499 | rel, | | |
| 2500 | /// Offset from the base of the GOT to the GOT entry. | | |
| 2501 | offset, | | |
| 2502 | }; | | |
| 2503 | | | |
| 2504 | const Simple = SymbolReloc.Type.Simple; | | |
| 2505 | | | |
| 2506 | /// Like `SymbolReloc.Special`, but for GOT relocations. | | |
| 2507 | const Special = enum(u13) { | | |
| 2508 | larch_pcala_hi20, | | |
| 2509 | larch_pcala64_lo20, | | |
| 2510 | larch_pcala64_hi12, | | |
| 2511 | | | |
| 2512 | sparc_op_lox10, | | |
| 2513 | sparc_op_hix22, | | |
| 2514 | | | |
| 2515 | fn applyInner( | | |
| 2516 | s: Special, | | |
| 2517 | elf: *Elf, | | |
| 2518 | got_vaddr: u64, | | |
| 2519 | got_offset: u64, | | |
| 2520 | addend: u64, | | |
| 2521 | dest_vaddr: u64, | | |
| 2522 | dest_slice: []u8, | | |
| 2523 | ) error{ RelocationMisaligned, RelocationOverflow }!void { | | |
| 2524 | switch (s) { | | |
| 2525 | .larch_pcala_hi20 => { | | |
| 2526 | const val = got_vaddr +% got_offset +% addend; | | |
| 2527 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | | |
| 2528 | elf.targetStore(inst, .{ | | |
| 2529 | .b0_4 = elf.targetLoad(inst).b0_4, | | |
| 2530 | .j20 = link.loongarch.pcalaHi20(val, dest_vaddr), | | |
| 2531 | .b25_31 = elf.targetLoad(inst).b25_31, | | |
| 2532 | }); | | |
| 2533 | }, | | |
| 2534 | .larch_pcala64_lo20 => { | | |
| 2535 | const val = got_vaddr +% got_offset +% addend; | | |
| 2536 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | | |
| 2537 | elf.targetStore(inst, .{ | | |
| 2538 | .b0_4 = elf.targetLoad(inst).b0_4, | | |
| 2539 | .j20 = link.loongarch.pcala64Lo20(val, dest_vaddr), | | |
| 2540 | .b25_31 = elf.targetLoad(inst).b25_31, | | |
| 2541 | }); | | |
| 2542 | }, | | |
| 2543 | .larch_pcala64_hi12 => { | | |
| 2544 | const val = got_vaddr +% got_offset +% addend; | | |
| 2545 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); | | |
| 2546 | elf.targetStore(inst, .{ | | |
| 2547 | .b0_9 = elf.targetLoad(inst).b0_9, | | |
| 2548 | .k12 = link.loongarch.pcala64Hi12(val, dest_vaddr), | | |
| 2549 | .b22_31 = elf.targetLoad(inst).b22_31, | | |
| 2550 | }); | | |
| 2551 | }, | | |
| 2552 | .sparc_op_lox10 => { | | |
| 2553 | const dest_ptr: *align(1) packed struct(u32) { | | |
| 2554 | imm13: u13, | | |
| 2555 | b13_31: u19, | | |
| 2556 | } = @ptrCast(dest_slice); | | |
| 2557 | elf.targetStore(dest_ptr, .{ | | |
| 2558 | .imm13 = @as(u10, @truncate(got_offset)), | | |
| 2559 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, | | |
| 2560 | }); | | |
| 2561 | }, | | |
| 2562 | .sparc_op_hix22 => { | | |
| 2563 | const dest_ptr: *align(1) packed struct(u32) { | | |
| 2564 | imm22: u22, | | |
| 2565 | b22_31: u10, | | |
| 2566 | } = @ptrCast(dest_slice); | | |
| 2567 | elf.targetStore(dest_ptr, .{ | | |
| 2568 | .imm22 = @truncate(got_offset >> 10), | | |
| 2569 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | | |
| 2570 | }); | | |
| 2571 | }, | | |
| 2572 | } | | |
| 2573 | } | | |
| 2574 | }; | | |
| 2575 | }; | | |
| 2576 | | | |
| 2577 | const Index = enum(u32) { | | |
| 2578 | none = std.math.maxInt(u32), | | |
| 2579 | _, | | |
| 2580 | | | |
| 2581 | fn get(index: GotReloc.Index, elf: *Elf) *GotReloc { | | |
| 2582 | return &elf.got_relocs.items[@backingInt(index)]; | | |
| 2583 | } | | |
| 2584 | }; | | |
| 2585 | | | |
| 2586 | fn apply(reloc: *GotReloc, elf: *Elf) void { | | |
| 2587 | assert(elf.ehdrType() != .REL); | | |
| 2588 | const node = reloc.node.unwrap() orelse return; // deleted | | |
| 2589 | if (node.hasMoved(&elf.mf) or elf.shndx.got.node(elf).hasMoved(&elf.mf)) { | | |
| 2590 | // There's no point applying the relocation now, because it will be re-applied by | | |
| 2591 | // `flushMoved` at some point anyway. | | |
| 2592 | return; | | |
| 2593 | } | | |
| 2594 | switch (reloc.result) { | | |
| 2595 | .ok => {}, | | |
| 2596 | .overflowed => elf.overflowed_reloc_count -= 1, | | |
| 2597 | .misaligned => elf.misaligned_reloc_count -= 1, | | |
| 2598 | } | | |
| 2599 | if (reloc.applyInner(elf)) { | | |
| 2600 | @branchHint(.likely); | | |
| 2601 | reloc.result = .ok; | | |
| 2602 | } else |err| switch (err) { | | |
| 2603 | error.RelocationOverflow => { | | |
| 2604 | reloc.result = .overflowed; | | |
| 2605 | elf.overflowed_reloc_count += 1; | | |
| 2606 | }, | | |
| 2607 | error.RelocationMisaligned => { | | |
| 2608 | reloc.result = .misaligned; | | |
| 2609 | elf.misaligned_reloc_count += 1; | | |
| 2610 | }, | | |
| 2611 | } | | |
| 2612 | } | | |
| 2613 | fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { | | |
| 2614 | const node = reloc.node.unwrap().?; | | |
| 2615 | const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset; | | |
| 2616 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; | | |
| 2617 | | | |
| 2618 | const got_vaddr = elf.shndx.got.vaddr(elf); | | |
| 2619 | const got_index: u64 = elf.got.getIndex(reloc.target).?; | | |
| 2620 | const got_offset: u64 = switch (elf.identClass()) { | | |
| 2621 | .NONE, _ => unreachable, | | |
| 2622 | inline else => |class| @sizeOf(class.ElfN().Addr) * got_index, | | |
| 2623 | }; | | |
| 2624 | const addend: u64 = @bitCast(reloc.addend); | | |
| 2625 | | | |
| 2626 | const target_val: u64 = switch (reloc.type.target) { | | |
| 2627 | .abs => got_vaddr +% got_offset +% addend, | | |
| 2628 | .rel => got_vaddr +% got_offset +% addend -% dest_vaddr, | | |
| 2629 | .offset => got_offset +% addend, | | |
| 2630 | .special => return reloc.type.action.special.applyInner( | | |
| 2631 | elf, | | |
| 2632 | got_vaddr, | | |
| 2633 | got_offset, | | |
| 2634 | addend, | | |
| 2635 | dest_vaddr, | | |
| 2636 | dest_slice, | | |
| 2637 | ), | | |
| 2638 | }; | | |
| 2639 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | | |
| 2640 | } | | |
| 2641 | | | |
| 2642 | fn delete(reloc: *GotReloc, elf: *Elf) void { | | |
| 2643 | switch (reloc.result) { | | |
| 2644 | .ok => {}, | | |
| 2645 | .overflowed => elf.overflowed_reloc_count -= 1, | | |
| 2646 | .misaligned => elf.misaligned_reloc_count -= 1, | | |
| 2647 | } | | |
| 2648 | reloc.* = .{ | | |
| 2649 | .node = .none, | | |
| 2650 | .offset = undefined, | | |
| 2651 | .target = undefined, | | |
| 2652 | .addend = undefined, | | |
| 2653 | .type = undefined, | | |
| 2654 | .result = undefined, | | |
| 2655 | }; | | |
| 2656 | } | | |
| 2657 | }; | | |
| 2658 | | | |
| 2659 | /// Records all global symbols defined in any DSO we depend on. For each symbol, its name, version, | 2708 | /// Records all global symbols defined in any DSO we depend on. For each symbol, its name, version, |
| 2660 | /// type, size, and alignment are all stored, as well as the soname of the DSO defining it. If one | 2709 | /// type, size, and alignment are all stored, as well as the soname of the DSO defining it. If one |
| 2661 | /// of these symbols ends up being referenced by the ELF module we are producing, we need this | 2710 | /// of these symbols ends up being referenced by the ELF module we are producing, we need this |
| ... | @@ -3000,6 +3049,8 @@ const AddLocalSymbolOptions = struct { | ... | @@ -3000,6 +3049,8 @@ const AddLocalSymbolOptions = struct { |
| 3000 | fn addLocalSymbol(elf: *Elf, opts: AddLocalSymbolOptions) Error!Symbol.LocalIndex { | 3049 | fn addLocalSymbol(elf: *Elf, opts: AddLocalSymbolOptions) Error!Symbol.LocalIndex { |
| 3001 | const gpa = elf.base.comp.gpa; | 3050 | const gpa = elf.base.comp.gpa; |
| 3002 | | 3051 | |
| | 3052 | assert(opts.shndx != .UNDEF); |
| | 3053 | |
| 3003 | try elf.symtab.ensureUnusedCapacity(gpa, 1); | 3054 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| 3004 | try elf.changed_symtab_index.ensureUnusedCapacity(gpa, 1); | 3055 | try elf.changed_symtab_index.ensureUnusedCapacity(gpa, 1); |
| 3005 | try Section.Index.symtab.node(elf).ensureMinimumSize(gpa, &elf.mf, switch (elf.shdrPtr(.symtab)) { | 3056 | try Section.Index.symtab.node(elf).ensureMinimumSize(gpa, &elf.mf, switch (elf.shdrPtr(.symtab)) { |
| ... | @@ -4293,7 +4344,7 @@ const Symbol = struct { | ... | @@ -4293,7 +4344,7 @@ const Symbol = struct { |
| 4293 | var ri = sym_id.index(elf).ptr(elf).first_target_reloc; | 4344 | var ri = sym_id.index(elf).ptr(elf).first_target_reloc; |
| 4294 | while (ri != .none) { | 4345 | while (ri != .none) { |
| 4295 | const reloc = ri.get(elf); | 4346 | const reloc = ri.get(elf); |
| 4296 | assert(reloc.target == sym_id); | 4347 | assert(reloc.target_symbol == sym_id); |
| 4297 | try reloc.updateDynamicReloc(elf); | 4348 | try reloc.updateDynamicReloc(elf); |
| 4298 | ri = reloc.next; | 4349 | ri = reloc.next; |
| 4299 | } | 4350 | } |
| ... | @@ -4470,7 +4521,7 @@ const Symbol = struct { | ... | @@ -4470,7 +4521,7 @@ const Symbol = struct { |
| 4470 | var ri = sym_id.index(elf).ptr(elf).first_target_reloc; | 4521 | var ri = sym_id.index(elf).ptr(elf).first_target_reloc; |
| 4471 | while (ri != .none) { | 4522 | while (ri != .none) { |
| 4472 | const reloc = ri.get(elf); | 4523 | const reloc = ri.get(elf); |
| 4473 | assert(reloc.target == sym_id); | 4524 | assert(reloc.target_symbol == sym_id); |
| 4474 | reloc.apply(elf); | 4525 | reloc.apply(elf); |
| 4475 | ri = reloc.next; | 4526 | ri = reloc.next; |
| 4476 | } | 4527 | } |
| ... | @@ -4563,7 +4614,7 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum { | ... | @@ -4563,7 +4614,7 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum { |
| 4563 | | 4614 | |
| 4564 | const shndx: Section.Index = switch (resolved_sym.unwrap()) { | 4615 | const shndx: Section.Index = switch (resolved_sym.unwrap()) { |
| 4565 | .local => shndx: { | 4616 | .local => shndx: { |
| 4566 | assert(symtab_shndx != .UNDEF); | 4617 | assert(sym == Symbol.Id.null or symtab_shndx != .UNDEF); |
| 4567 | assert(visibility == .DEFAULT); | 4618 | assert(visibility == .DEFAULT); |
| 4568 | break :shndx symtab_shndx; | 4619 | break :shndx symtab_shndx; |
| 4569 | }, | 4620 | }, |
| ... | @@ -4683,7 +4734,6 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol | ... | @@ -4683,7 +4734,6 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol |
| 4683 | .shndx = shndx, | 4734 | .shndx = shndx, |
| 4684 | }), | 4735 | }), |
| 4685 | .first_symbol_reloc = .none, | 4736 | .first_symbol_reloc = .none, |
| 4686 | .first_got_reloc = .none, | | |
| 4687 | }; | 4737 | }; |
| 4688 | elf.base.comp.link_prog_node.increaseEstimatedTotalItems(1); | 4738 | elf.base.comp.link_prog_node.increaseEstimatedTotalItems(1); |
| 4689 | } | 4739 | } |
| ... | @@ -6787,7 +6837,6 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -6787,7 +6837,6 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 6787 | skip_symbol_relocs: MappedFile.Node.Index.Optional = .none, | 6837 | skip_symbol_relocs: MappedFile.Node.Index.Optional = .none, |
| 6788 | first_node_reloc: ?*NodeReloc.Index = null, | 6838 | first_node_reloc: ?*NodeReloc.Index = null, |
| 6789 | skip_node_relocs: MappedFile.Node.Index.Optional = .none, | 6839 | skip_node_relocs: MappedFile.Node.Index.Optional = .none, |
| 6790 | first_got_reloc: ?*GotReloc.Index = null, | | |
| 6791 | } = switch (elf.getNode(ni)) { | 6840 | } = switch (elf.getNode(ni)) { |
| 6792 | .deleted, | 6841 | .deleted, |
| 6793 | .archive, | 6842 | .archive, |
| ... | @@ -6814,18 +6863,15 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -6814,18 +6863,15 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 6814 | => unreachable, // cannot contain relocs (.plt, .dynamic, and .eh_frame_hdr unsupported) | 6863 | => unreachable, // cannot contain relocs (.plt, .dynamic, and .eh_frame_hdr unsupported) |
| 6815 | .input_section => |isi| .{ | 6864 | .input_section => |isi| .{ |
| 6816 | .first_symbol_reloc = &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, | 6865 | .first_symbol_reloc = &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, |
| 6817 | .first_got_reloc = &elf.input_sections.items[@backingInt(isi)].first_got_reloc, | | |
| 6818 | }, | 6866 | }, |
| 6819 | .nav => |nmi| .{ | 6867 | .nav => |nmi| .{ |
| 6820 | .first_symbol_reloc = &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc, | 6868 | .first_symbol_reloc = &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc, |
| 6821 | .first_got_reloc = &elf.navs.values()[@backingInt(nmi)].first_got_reloc, | | |
| 6822 | }, | 6869 | }, |
| 6823 | .uav => |umi| .{ | 6870 | .uav => |umi| .{ |
| 6824 | .first_symbol_reloc = &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc, | 6871 | .first_symbol_reloc = &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc, |
| 6825 | }, | 6872 | }, |
| 6826 | inline .lazy_code, .lazy_const_data => |lmi| .{ | 6873 | inline .lazy_code, .lazy_const_data => |lmi| .{ |
| 6827 | .first_symbol_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc, | 6874 | .first_symbol_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc, |
| 6828 | .first_got_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc, | | |
| 6829 | }, | 6875 | }, |
| 6830 | .unit_debug_info_header => |ui| .{ | 6876 | .unit_debug_info_header => |ui| .{ |
| 6831 | .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_node_reloc, | 6877 | .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_node_reloc, |
| ... | @@ -6893,19 +6939,6 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -6893,19 +6939,6 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 6893 | } | 6939 | } |
| 6894 | ptr.* = @fromBackingInt(@intCast(elf.node_relocs.items.len)); | 6940 | ptr.* = @fromBackingInt(@intCast(elf.node_relocs.items.len)); |
| 6895 | } | 6941 | } |
| 6896 | | | |
| 6897 | if (opts.first_got_reloc) |ptr| { | | |
| 6898 | if (ptr.* != .none) { | | |
| 6899 | for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| { | | |
| 6900 | if (reloc.node != ni.toOptional()) { | | |
| 6901 | if (reloc.node == .none) continue; | | |
| 6902 | break; | | |
| 6903 | } | | |
| 6904 | reloc.delete(elf); | | |
| 6905 | } | | |
| 6906 | } | | |
| 6907 | ptr.* = @fromBackingInt(@intCast(elf.got_relocs.items.len)); | | |
| 6908 | } | | |
| 6909 | } | 6942 | } |
| 6910 | | 6943 | |
| 6911 | /// Given that `node` has moved, updates all relocations in `node` as needed. In relocatables, this | 6944 | /// Given that `node` has moved, updates all relocations in `node` as needed. In relocatables, this |
| ... | @@ -6918,7 +6951,6 @@ fn flushMovedNodeRelocs( | ... | @@ -6918,7 +6951,6 @@ fn flushMovedNodeRelocs( |
| 6918 | skip_symbol_relocs: MappedFile.Node.Index.Optional = .none, | 6951 | skip_symbol_relocs: MappedFile.Node.Index.Optional = .none, |
| 6919 | first_node_reloc: NodeReloc.Index = .none, | 6952 | first_node_reloc: NodeReloc.Index = .none, |
| 6920 | skip_node_relocs: MappedFile.Node.Index.Optional = .none, | 6953 | skip_node_relocs: MappedFile.Node.Index.Optional = .none, |
| 6921 | first_got_reloc: GotReloc.Index = .none, | | |
| 6922 | }, | 6954 | }, |
| 6923 | ) void { | 6955 | ) void { |
| 6924 | if (opts.first_symbol_reloc != .none) { | 6956 | if (opts.first_symbol_reloc != .none) { |
| ... | @@ -6942,16 +6974,6 @@ fn flushMovedNodeRelocs( | ... | @@ -6942,16 +6974,6 @@ fn flushMovedNodeRelocs( |
| 6942 | reloc.apply(elf); | 6974 | reloc.apply(elf); |
| 6943 | } | 6975 | } |
| 6944 | } | 6976 | } |
| 6945 | | | |
| 6946 | if (opts.first_got_reloc != .none) { | | |
| 6947 | for (elf.got_relocs.items[@backingInt(opts.first_got_reloc)..]) |*reloc| { | | |
| 6948 | if (reloc.node != node.toOptional()) { | | |
| 6949 | if (reloc.node == .none) continue; | | |
| 6950 | break; | | |
| 6951 | } | | |
| 6952 | reloc.apply(elf); | | |
| 6953 | } | | |
| 6954 | } | | |
| 6955 | } | 6977 | } |
| 6956 | | 6978 | |
| 6957 | fn identClass(elf: *const Elf) std.elf.CLASS { | 6979 | fn identClass(elf: *const Elf) std.elf.CLASS { |
| ... | @@ -7496,7 +7518,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node | ... | @@ -7496,7 +7518,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 7496 | .shndx = shndx, | 7518 | .shndx = shndx, |
| 7497 | }), | 7519 | }), |
| 7498 | .first_symbol_reloc = .none, | 7520 | .first_symbol_reloc = .none, |
| 7499 | .first_got_reloc = .none, | | |
| 7500 | }; | 7521 | }; |
| 7501 | } | 7522 | } |
| 7502 | return nmi; | 7523 | return nmi; |
| ... | @@ -8064,7 +8085,6 @@ fn loadObject( | ... | @@ -8064,7 +8085,6 @@ fn loadObject( |
| 8064 | .vaddr = 0, | 8085 | .vaddr = 0, |
| 8065 | .node = ni, | 8086 | .node = ni, |
| 8066 | .first_symbol_reloc = .none, | 8087 | .first_symbol_reloc = .none, |
| 8067 | .first_got_reloc = .none, | | |
| 8068 | }; | 8088 | }; |
| 8069 | elf.input_prog_node.increaseEstimatedTotalItems(1); | 8089 | elf.input_prog_node.increaseEstimatedTotalItems(1); |
| 8070 | } | 8090 | } |
| ... | @@ -9422,7 +9442,6 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -9422,7 +9442,6 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 9422 | const gpa = elf.base.comp.gpa; | 9442 | const gpa = elf.base.comp.gpa; |
| 9423 | try elf.symbol_relocs.ensureUnusedCapacity(gpa, len); | 9443 | try elf.symbol_relocs.ensureUnusedCapacity(gpa, len); |
| 9424 | try elf.node_relocs.ensureUnusedCapacity(gpa, len); | 9444 | try elf.node_relocs.ensureUnusedCapacity(gpa, len); |
| 9425 | try elf.got_relocs.ensureUnusedCapacity(gpa, len); | | |
| 9426 | const class = elf.identClass(); | 9445 | const class = elf.identClass(); |
| 9427 | switch (elf.ehdrType()) { | 9446 | switch (elf.ehdrType()) { |
| 9428 | .REL => { | 9447 | .REL => { |
| ... | @@ -9460,7 +9479,6 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -9460,7 +9479,6 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 9460 | try shndx.get(elf).rela.shndx.relaEnsureAdditionalCapacity(elf, len); | 9479 | try shndx.get(elf).rela.shndx.relaEnsureAdditionalCapacity(elf, len); |
| 9461 | }, | 9480 | }, |
| 9462 | .EXEC, .DYN => { | 9481 | .EXEC, .DYN => { |
| 9463 | try elf.tls_size_symbol_relocs.ensureUnusedCapacity(gpa, len); | | |
| 9464 | const new_got_entries = len * 2; // at worst, every reloc is a new TLSGD | 9482 | const new_got_entries = len * 2; // at worst, every reloc is a new TLSGD |
| 9465 | try elf.got.ensureUnusedCapacity(gpa, new_got_entries); | 9483 | try elf.got.ensureUnusedCapacity(gpa, new_got_entries); |
| 9466 | const need_got_size = switch (class) { | 9484 | const need_got_size = switch (class) { |
| ... | @@ -9506,13 +9524,12 @@ fn addRelocAssumeCapacity( | ... | @@ -9506,13 +9524,12 @@ fn addRelocAssumeCapacity( |
| 9506 | elf.symbol_relocs.appendAssumeCapacity(.{ | 9524 | elf.symbol_relocs.appendAssumeCapacity(.{ |
| 9507 | .node = node.toOptional(), | 9525 | .node = node.toOptional(), |
| 9508 | .offset = offset, | 9526 | .offset = offset, |
| 9509 | .type = undefined, | 9527 | .bits = undefined, |
| 9510 | .target = target, | 9528 | .target_symbol = target, |
| 9511 | .addend = .{ .normal = addend }, | 9529 | .addend = .{ .normal = addend }, |
| 9512 | .next = next, | 9530 | .next = next, |
| 9513 | .prev = .none, | 9531 | .prev = .none, |
| 9514 | .rela_index = rela_index.toOptional(), | 9532 | .rela_index = rela_index.toOptional(), |
| 9515 | .result = .ok, | | |
| 9516 | }); | 9533 | }); |
| 9517 | ri.get(elf).apply(elf); | 9534 | ri.get(elf).apply(elf); |
| 9518 | }, | 9535 | }, |
| ... | @@ -9567,14 +9584,14 @@ fn addRelocAssumeCapacity( | ... | @@ -9567,14 +9584,14 @@ fn addRelocAssumeCapacity( |
| 9567 | .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32[24:5]", .cast = .trunc, .shift = .@"32" })), | 9584 | .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32[24:5]", .cast = .trunc, .shift = .@"32" })), |
| 9568 | .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32[21:10]", .cast = .unsigned, .shift = .@"52" })), | 9585 | .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32[21:10]", .cast = .unsigned, .shift = .@"52" })), |
| 9569 | | 9586 | |
| 9570 | .GOT_PC_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.abs, .{ .dest = .@"32[21:10]", .cast = .trunc, .shift = .@"0" })), | 9587 | .GOT_PC_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotabs_symbol, .{ .dest = .@"32[21:10]", .cast = .trunc, .shift = .@"0" })), |
| 9571 | .GOT_PC_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .special(.larch_pcala_hi20)), | 9588 | .GOT_PC_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.larch_got_pcala_hi20)), |
| 9572 | .GOT64_PC_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .special(.larch_pcala64_lo20)), | 9589 | .GOT64_PC_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.larch_got_pcala64_lo20)), |
| 9573 | .GOT64_PC_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .special(.larch_pcala64_hi12)), | 9590 | .GOT64_PC_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.larch_got_pcala64_hi12)), |
| 9574 | .GOT_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.abs, .{ .dest = .@"32[21:10]", .cast = .trunc, .shift = .@"0" })), | 9591 | .GOT_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotabs_symbol, .{ .dest = .@"32[21:10]", .cast = .trunc, .shift = .@"0" })), |
| 9575 | .GOT_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.abs, .{ .dest = .@"32[24:5]", .cast = .trunc, .shift = .@"12" })), | 9592 | .GOT_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotabs_symbol, .{ .dest = .@"32[24:5]", .cast = .trunc, .shift = .@"12" })), |
| 9576 | .GOT64_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.abs, .{ .dest = .@"32[24:5]", .cast = .trunc, .shift = .@"32" })), | 9593 | .GOT64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotabs_symbol, .{ .dest = .@"32[24:5]", .cast = .trunc, .shift = .@"32" })), |
| 9577 | .GOT64_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.abs, .{ .dest = .@"32[21:10]", .cast = .unsigned, .shift = .@"52" })), | 9594 | .GOT64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotabs_symbol, .{ .dest = .@"32[21:10]", .cast = .unsigned, .shift = .@"52" })), |
| 9578 | // zig fmt: on | 9595 | // zig fmt: on |
| 9579 | }, | 9596 | }, |
| 9580 | .PPC64 => switch (@"type".PPC64) { | 9597 | .PPC64 => switch (@"type".PPC64) { |
| ... | @@ -9678,13 +9695,13 @@ fn addRelocAssumeCapacity( | ... | @@ -9678,13 +9695,13 @@ fn addRelocAssumeCapacity( |
| 9678 | .TLS_DTPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), | 9695 | .TLS_DTPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), |
| 9679 | .TLS_DTPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), | 9696 | .TLS_DTPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), |
| 9680 | | 9697 | |
| 9681 | .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"32[12:0]", .cast = .unsigned, .shift = .@"0" })), | 9698 | .GOT13 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_symbol, .{ .dest = .@"32[12:0]", .cast = .unsigned, .shift = .@"0" })), |
| 9682 | .GOT22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), | 9699 | .GOT22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_symbol, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), |
| 9683 | .GOTDATA_OP_LOX10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .special(.sparc_op_lox10)), | 9700 | .GOTDATA_OP_LOX10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_got_op_lox10)), |
| 9684 | .GOTDATA_OP_HIX22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .special(.sparc_op_hix22)), | 9701 | .GOTDATA_OP_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_got_op_hix22)), |
| 9685 | .TLS_GD_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .tlsgd0 = target }, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), | 9702 | .TLS_GD_HI22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_tlsgd, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), |
| 9686 | .TLS_LDM_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), | 9703 | .TLS_LDM_HI22 => try elf.addSymbolRelocAssumeCapacity(node, offset, .null, addend, .simple(.gotoff_tlsgd, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), |
| 9687 | .TLS_IE_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .tpoff = target }, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), | 9704 | .TLS_IE_HI22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_tpoff, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), |
| 9688 | // zig fmt: on | 9705 | // zig fmt: on |
| 9689 | | 9706 | |
| 9690 | .TLS_GD_CALL, .TLS_LDM_CALL => { | 9707 | .TLS_GD_CALL, .TLS_LDM_CALL => { |
| ... | @@ -9750,19 +9767,19 @@ fn addRelocAssumeCapacity( | ... | @@ -9750,19 +9767,19 @@ fn addRelocAssumeCapacity( |
| 9750 | }, | 9767 | }, |
| 9751 | .GOT10 => { | 9768 | .GOT10 => { |
| 9752 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); | 9769 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); |
| 9753 | elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); | 9770 | try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_symbol, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); |
| 9754 | }, | 9771 | }, |
| 9755 | .TLS_GD_LO10 => { | 9772 | .TLS_GD_LO10 => { |
| 9756 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); | 9773 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); |
| 9757 | elf.addGotRelocAssumeCapacity(node, offset, .{ .tlsgd0 = target }, addend, .simple(.offset, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); | 9774 | try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_tlsgd, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); |
| 9758 | }, | 9775 | }, |
| 9759 | .TLS_LDM_LO10 => { | 9776 | .TLS_LDM_LO10 => { |
| 9760 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); | 9777 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); |
| 9761 | elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .simple(.offset, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); | 9778 | try elf.addSymbolRelocAssumeCapacity(node, offset, .null, addend, .simple(.gotoff_tlsgd, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); |
| 9762 | }, | 9779 | }, |
| 9763 | .TLS_IE_LO10 => { | 9780 | .TLS_IE_LO10 => { |
| 9764 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); | 9781 | try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); |
| 9765 | elf.addGotRelocAssumeCapacity(node, offset, .{ .tpoff = target }, addend, .simple(.offset, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); | 9782 | try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_tpoff, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); |
| 9766 | }, | 9783 | }, |
| 9767 | }, | 9784 | }, |
| 9768 | .X86_64 => rel_type: switch (@"type".X86_64) { | 9785 | .X86_64 => rel_type: switch (@"type".X86_64) { |
| ... | @@ -9790,12 +9807,7 @@ fn addRelocAssumeCapacity( | ... | @@ -9790,12 +9807,7 @@ fn addRelocAssumeCapacity( |
| 9790 | .GOTOFF64 => return error.UnimplementedRelocation, // offset of symbol from GOT base | 9807 | .GOTOFF64 => return error.UnimplementedRelocation, // offset of symbol from GOT base |
| 9791 | .PLTOFF64 => return error.UnimplementedRelocation, // offset of PLT entry from GOT base (yes, I know, the name is stupid) | 9808 | .PLTOFF64 => return error.UnimplementedRelocation, // offset of PLT entry from GOT base (yes, I know, the name is stupid) |
| 9792 | | 9809 | |
| 9793 | // TODO: figure out how to do relaxations. Perhaps we want to remove a `GotReloc` | 9810 | // TODO: figure out how to do relaxations |
| 9794 | // and replace it with a `SymbolReloc` when a relaxation becomes possible, but we'd | | |
| 9795 | // need to bear in mind whether incremental updates might make a relaxation | | |
| 9796 | // impossible again or something like that. Relaxations seem kind of hostile to | | |
| 9797 | // incremental compilation, so perhaps we just only support them in non-incremental | | |
| 9798 | // compilations and just apply them in flush or something. | | |
| 9799 | | 9811 | |
| 9800 | // Relaxable versions of other relocations. Since we don't yet implement relaxation, | 9812 | // Relaxable versions of other relocations. Since we don't yet implement relaxation, |
| 9801 | // just use the handling for the non-relaxable versions. | 9813 | // just use the handling for the non-relaxable versions. |
| ... | @@ -9831,13 +9843,13 @@ fn addRelocAssumeCapacity( | ... | @@ -9831,13 +9843,13 @@ fn addRelocAssumeCapacity( |
| 9831 | .TPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), | 9843 | .TPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), |
| 9832 | .TPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"64", .cast = .signed, .shift = .@"0" })), | 9844 | .TPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"64", .cast = .signed, .shift = .@"0" })), |
| 9833 | | 9845 | |
| 9834 | .GOT32 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), | 9846 | .GOT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_symbol, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), |
| 9835 | .GOT64 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), | 9847 | .GOT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotoff_symbol, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), |
| 9836 | .GOTPCREL => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.rel, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), | 9848 | .GOTPCREL => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotrel_symbol, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), |
| 9837 | .GOTPCREL64 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.rel, .{ .dest = .@"64", .cast = .signed, .shift = .@"0" })), | 9849 | .GOTPCREL64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotrel_symbol, .{ .dest = .@"64", .cast = .signed, .shift = .@"0" })), |
| 9838 | .TLSGD => elf.addGotRelocAssumeCapacity(node, offset, .{ .tlsgd0 = target }, addend, .simple(.rel, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), | 9850 | .TLSGD => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotrel_tlsgd, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), |
| 9839 | .TLSLD => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .simple(.rel, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), | 9851 | .TLSLD => try elf.addSymbolRelocAssumeCapacity(node, offset, .null, addend, .simple(.gotrel_tlsgd, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), |
| 9840 | .GOTTPOFF => elf.addGotRelocAssumeCapacity(node, offset, .{ .tpoff = target }, addend, .simple(.rel, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), | 9852 | .GOTTPOFF => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.gotrel_tpoff, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), |
| 9841 | // zig fmt: on | 9853 | // zig fmt: on |
| 9842 | | 9854 | |
| 9843 | .GOTPC64 => { | 9855 | .GOTPC64 => { |
| ... | @@ -9872,6 +9884,8 @@ fn addSymbolRelocAssumeCapacityInner( | ... | @@ -9872,6 +9884,8 @@ fn addSymbolRelocAssumeCapacityInner( |
| 9872 | ) Error!void { | 9884 | ) Error!void { |
| 9873 | assert(elf.ehdrType() != .REL); | 9885 | assert(elf.ehdrType() != .REL); |
| 9874 | | 9886 | |
| | 9887 | const gpa = elf.base.comp.gpa; |
| | 9888 | |
| 9875 | request_static_target: { | 9889 | request_static_target: { |
| 9876 | if (elf.shndx.dynamic == .UNDEF) break :request_static_target; | 9890 | if (elf.shndx.dynamic == .UNDEF) break :request_static_target; |
| 9877 | const gsi: Symbol.Global.Index = switch (target.unwrap()) { | 9891 | const gsi: Symbol.Global.Index = switch (target.unwrap()) { |
| ... | @@ -9894,6 +9908,15 @@ fn addSymbolRelocAssumeCapacityInner( | ... | @@ -9894,6 +9908,15 @@ fn addSymbolRelocAssumeCapacityInner( |
| 9894 | .dtpoff, | 9908 | .dtpoff, |
| 9895 | .tpoff, | 9909 | .tpoff, |
| 9896 | .size, | 9910 | .size, |
| | 9911 | .gotabs_symbol, |
| | 9912 | .gotrel_symbol, |
| | 9913 | .gotoff_symbol, |
| | 9914 | .gotabs_tpoff, |
| | 9915 | .gotrel_tpoff, |
| | 9916 | .gotoff_tpoff, |
| | 9917 | .gotabs_tlsgd, |
| | 9918 | .gotrel_tlsgd, |
| | 9919 | .gotoff_tlsgd, |
| 9897 | => false, | 9920 | => false, |
| 9898 | | 9921 | |
| 9899 | .special => switch (@"type".action.special) { | 9922 | .special => switch (@"type".action.special) { |
| ... | @@ -9908,10 +9931,15 @@ fn addSymbolRelocAssumeCapacityInner( | ... | @@ -9908,10 +9931,15 @@ fn addSymbolRelocAssumeCapacityInner( |
| 9908 | .larch_b21, | 9931 | .larch_b21, |
| 9909 | .larch_b26, | 9932 | .larch_b26, |
| 9910 | .larch_call36, | 9933 | .larch_call36, |
| | 9934 | .larch_got_pcala_hi20, |
| | 9935 | .larch_got_pcala64_lo20, |
| | 9936 | .larch_got_pcala64_hi12, |
| 9911 | | 9937 | |
| 9912 | .sparc_le_hix22, | 9938 | .sparc_le_hix22, |
| 9913 | .sparc_wdisp10, | 9939 | .sparc_wdisp10, |
| 9914 | .sparc_wdisp16, | 9940 | .sparc_wdisp16, |
| | 9941 | .sparc_got_op_lox10, |
| | 9942 | .sparc_got_op_hix22, |
| 9915 | => false, | 9943 | => false, |
| 9916 | }, | 9944 | }, |
| 9917 | }; | 9945 | }; |
| ... | @@ -9923,6 +9951,42 @@ fn addSymbolRelocAssumeCapacityInner( | ... | @@ -9923,6 +9951,42 @@ fn addSymbolRelocAssumeCapacityInner( |
| 9923 | } | 9951 | } |
| 9924 | } | 9952 | } |
| 9925 | | 9953 | |
| | 9954 | if (@"type".needsGotEntry()) |got_kind| { |
| | 9955 | const new_index: usize, const new_len: u32 = switch (got_kind) { |
| | 9956 | .symbol => new: { |
| | 9957 | const gop = try elf.got.getOrPut(gpa, .{ .symbol = target }); |
| | 9958 | if (gop.found_existing) break :new .{ 0, 0 }; |
| | 9959 | gop.value_ptr.* = .none; |
| | 9960 | break :new .{ gop.index, 1 }; |
| | 9961 | }, |
| | 9962 | .tpoff => new: { |
| | 9963 | const gop = try elf.got.getOrPut(gpa, .{ .tpoff = target }); |
| | 9964 | if (gop.found_existing) break :new .{ 0, 0 }; |
| | 9965 | gop.value_ptr.* = .none; |
| | 9966 | break :new .{ gop.index, 1 }; |
| | 9967 | }, |
| | 9968 | .tlsgd => new: { |
| | 9969 | try elf.got.ensureUnusedCapacity(gpa, 2); |
| | 9970 | const gop = elf.got.getOrPutAssumeCapacity(.{ .tlsgd0 = target }); |
| | 9971 | if (gop.found_existing) break :new .{ 0, 0 }; |
| | 9972 | gop.value_ptr.* = .none; |
| | 9973 | elf.got.putAssumeCapacityNoClobber(.{ .tlsgd1 = target }, .none); |
| | 9974 | break :new .{ gop.index, 1 }; |
| | 9975 | }, |
| | 9976 | }; |
| | 9977 | |
| | 9978 | switch (elf.shdrPtr(elf.shndx.got)) { |
| | 9979 | inline else => |got_shdr, class| { |
| | 9980 | const new_size = elf.targetLoad(&got_shdr.size) + new_len * @sizeOf(class.ElfN().Addr); |
| | 9981 | elf.targetStore(&got_shdr.size, new_size); |
| | 9982 | try elf.shndx.got.node(elf).ensureMinimumSize(gpa, &elf.mf, new_size); |
| | 9983 | }, |
| | 9984 | } |
| | 9985 | for (new_index..new_index + new_len) |got_index| { |
| | 9986 | elf.updateGotEntry(got_index); |
| | 9987 | } |
| | 9988 | } |
| | 9989 | |
| 9926 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 9990 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 9927 | const first_target_reloc = &target.index(elf).ptr(elf).first_target_reloc; | 9991 | const first_target_reloc = &target.index(elf).ptr(elf).first_target_reloc; |
| 9928 | const next = first_target_reloc.*; | 9992 | const next = first_target_reloc.*; |
| ... | @@ -9931,16 +9995,21 @@ fn addSymbolRelocAssumeCapacityInner( | ... | @@ -9931,16 +9995,21 @@ fn addSymbolRelocAssumeCapacityInner( |
| 9931 | elf.symbol_relocs.appendAssumeCapacity(.{ | 9995 | elf.symbol_relocs.appendAssumeCapacity(.{ |
| 9932 | .node = node.toOptional(), | 9996 | .node = node.toOptional(), |
| 9933 | .offset = offset, | 9997 | .offset = offset, |
| 9934 | .target = target, | 9998 | .target_symbol = target, |
| 9935 | .addend = addend, | 9999 | .addend = addend, |
| 9936 | .type = @"type", | 10000 | .bits = .{ |
| | 10001 | .type = @"type", |
| | 10002 | .result = .ok, |
| | 10003 | }, |
| 9937 | .next = next, | 10004 | .next = next, |
| 9938 | .prev = .none, | 10005 | .prev = .none, |
| 9939 | .rela_index = .none, | 10006 | .rela_index = .none, |
| 9940 | .result = .ok, | | |
| 9941 | }); | 10007 | }); |
| 9942 | if (@"type".dependsOnTlsSize(elf)) { | 10008 | if (@"type".dependsOnTlsSize(elf)) { |
| 9943 | elf.tls_size_symbol_relocs.putAssumeCapacityNoClobber(ri, {}); | 10009 | try elf.tls_size_symbol_relocs.putNoClobber(gpa, ri, {}); |
| | 10010 | } |
| | 10011 | if (@"type".dependsOnGotAddress()) { |
| | 10012 | try elf.got_relocs.put(gpa, ri, {}); |
| 9944 | } | 10013 | } |
| 9945 | try ri.get(elf).updateDynamicReloc(elf); | 10014 | try ri.get(elf).updateDynamicReloc(elf); |
| 9946 | | 10015 | |
| ... | @@ -10046,95 +10115,6 @@ fn addNodeRelocAssumeCapacity( | ... | @@ -10046,95 +10115,6 @@ fn addNodeRelocAssumeCapacity( |
| 10046 | }, | 10115 | }, |
| 10047 | } | 10116 | } |
| 10048 | } | 10117 | } |
| 10049 | fn addGotRelocAssumeCapacity( | | |
| 10050 | elf: *Elf, | | |
| 10051 | node: MappedFile.Node.Index, | | |
| 10052 | offset: u64, | | |
| 10053 | target: GotKey, | | |
| 10054 | addend: i64, | | |
| 10055 | @"type": GotReloc.Type, | | |
| 10056 | ) void { | | |
| 10057 | assert(elf.ehdrType() != .REL); | | |
| 10058 | switch (elf.getNode(node)) { | | |
| 10059 | .deleted, | | |
| 10060 | .archive, | | |
| 10061 | .archive_header, | | |
| 10062 | .archive_input_member, | | |
| 10063 | .archive_elf_member_header, | | |
| 10064 | .elf, | | |
| 10065 | .ehdr, | | |
| 10066 | .shdr, | | |
| 10067 | .segment, | | |
| 10068 | .copied_global, | | |
| 10069 | .debug_shared, | | |
| 10070 | .debug_addr, | | |
| 10071 | .eh_frame_footer, | | |
| 10072 | .debug_str_offsets, | | |
| 10073 | .unit_padding, | | |
| 10074 | .unit_frame, | | |
| 10075 | .unit_frame_cie, | | |
| 10076 | .unit_debug_info, | | |
| 10077 | .unit_debug_info_header, | | |
| 10078 | .unit_debug_info_footer, | | |
| 10079 | .unit_debug_line, | | |
| 10080 | .unit_debug_line_header, | | |
| 10081 | .unit_debug_rnglists, | | |
| 10082 | .const_debug_info, | | |
| 10083 | .global_debug_info, | | |
| 10084 | .func_frame_fde, | | |
| 10085 | .func_debug_info, | | |
| 10086 | .func_debug_line, | | |
| 10087 | .decl_debug_info, | | |
| 10088 | => unreachable, // cannot contain relocs, | | |
| 10089 | .section, | | |
| 10090 | .section_manual_size, | | |
| 10091 | .uav, | | |
| 10092 | => unreachable, // cannot contain GOT relocs | | |
| 10093 | .input_section, | | |
| 10094 | .nav, | | |
| 10095 | .lazy_code, | | |
| 10096 | .lazy_const_data, | | |
| 10097 | => {}, | | |
| 10098 | } | | |
| 10099 | | | |
| 10100 | const gop = elf.got.getOrPutAssumeCapacity(target); | | |
| 10101 | if (!gop.found_existing) { | | |
| 10102 | gop.value_ptr.* = .none; | | |
| 10103 | const maybe_next_key: ?GotKey = switch (target) { | | |
| 10104 | .reserved => null, | | |
| 10105 | .tpoff => null, | | |
| 10106 | .symbol => null, | | |
| 10107 | .tlsld0 => .tlsld1, | | |
| 10108 | .tlsgd0 => |sym| .{ .tlsgd1 = sym }, | | |
| 10109 | .tlsld1 => unreachable, | | |
| 10110 | .tlsgd1 => unreachable, | | |
| 10111 | }; | | |
| 10112 | switch (elf.shdrPtr(elf.shndx.got)) { | | |
| 10113 | inline else => |got_shdr, class| { | | |
| 10114 | const Addr = class.ElfN().Addr; | | |
| 10115 | const old_size = elf.targetLoad(&got_shdr.size); | | |
| 10116 | const new_entry_count = @as(u32, 1) + @intFromBool(maybe_next_key != null); | | |
| 10117 | elf.targetStore(&got_shdr.size, @intCast(old_size + @sizeOf(Addr) * new_entry_count)); | | |
| 10118 | }, | | |
| 10119 | } | | |
| 10120 | if (maybe_next_key) |next_key| { | | |
| 10121 | elf.got.putAssumeCapacityNoClobber(next_key, .none); | | |
| 10122 | elf.updateGotEntry(gop.index); | | |
| 10123 | elf.updateGotEntry(gop.index + 1); | | |
| 10124 | } else { | | |
| 10125 | elf.updateGotEntry(gop.index); | | |
| 10126 | } | | |
| 10127 | } | | |
| 10128 | | | |
| 10129 | elf.got_relocs.appendAssumeCapacity(.{ | | |
| 10130 | .node = .wrap(node), | | |
| 10131 | .offset = offset, | | |
| 10132 | .target = target, | | |
| 10133 | .addend = addend, | | |
| 10134 | .type = @"type", | | |
| 10135 | .result = .ok, | | |
| 10136 | }); | | |
| 10137 | } | | |
| 10138 | fn updateGotEntry(elf: *Elf, got_index: usize) void { | 10118 | fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 10139 | assert(elf.ehdrType() != .REL); | 10119 | assert(elf.ehdrType() != .REL); |
| 10140 | const entry_value: union(enum) { | 10120 | const entry_value: union(enum) { |
| ... | @@ -10193,15 +10173,6 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { | ... | @@ -10193,15 +10173,6 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 10193 | .addend = 0, | 10173 | .addend = 0, |
| 10194 | } }, | 10174 | } }, |
| 10195 | }, | 10175 | }, |
| 10196 | .tlsgd1 => |sym| switch (elf.classifySymbolValue(sym)) { | | |
| 10197 | .static => .{ .unsigned = sym.value(elf) }, | | |
| 10198 | .static_relative => unreachable, // TLS variables should be in TLS sections, which do not return `.static_relative` | | |
| 10199 | .dynamic => .{ .reloc = .{ | | |
| 10200 | .type = .dtpOff(elf), | | |
| 10201 | .dynsym_index = sym.unwrap().global.dynsymIndex(elf).?, | | |
| 10202 | .addend = 0, | | |
| 10203 | } }, | | |
| 10204 | }, | | |
| 10205 | .tlsgd0 => |sym| switch (elf.base.comp.config.link_mode) { | 10176 | .tlsgd0 => |sym| switch (elf.base.comp.config.link_mode) { |
| 10206 | .static => val: { | 10177 | .static => val: { |
| 10207 | assert(elf.base.comp.config.output_mode == .Exe); // static libraries don't have GOTs | 10178 | assert(elf.base.comp.config.output_mode == .Exe); // static libraries don't have GOTs |
| ... | @@ -10209,25 +10180,28 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { | ... | @@ -10209,25 +10180,28 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 10209 | }, | 10180 | }, |
| 10210 | .dynamic => .{ .reloc = .{ | 10181 | .dynamic => .{ .reloc = .{ |
| 10211 | .type = .dtpMod(elf), | 10182 | .type = .dtpMod(elf), |
| 10212 | .dynsym_index = switch (elf.classifySymbolValue(sym)) { | 10183 | .dynsym_index = switch (sym) { |
| 10213 | .static, .static_relative => 0, | 10184 | .null => 0, |
| 10214 | .dynamic => sym.unwrap().global.dynsymIndex(elf).?, | 10185 | else => switch (elf.classifySymbolValue(sym)) { |
| | 10186 | .static, .static_relative => 0, |
| | 10187 | .dynamic => sym.unwrap().global.dynsymIndex(elf).?, |
| | 10188 | }, |
| 10215 | }, | 10189 | }, |
| 10216 | .addend = 0, | 10190 | .addend = 0, |
| 10217 | } }, | 10191 | } }, |
| 10218 | }, | 10192 | }, |
| 10219 | .tlsld0 => switch (elf.base.comp.config.link_mode) { | 10193 | .tlsgd1 => |sym| switch (sym) { |
| 10220 | .static => val: { | 10194 | .null => .{ .unsigned = 0 }, |
| 10221 | assert(elf.base.comp.config.output_mode == .Exe); // static libraries don't have GOTs | 10195 | else => switch (elf.classifySymbolValue(sym)) { |
| 10222 | break :val .{ .unsigned = 1 }; // TLS module ID for executable | 10196 | .static => .{ .unsigned = sym.value(elf) }, |
| | 10197 | .static_relative => unreachable, // TLS variables should be in TLS sections, which do not return `.static_relative` |
| | 10198 | .dynamic => .{ .reloc = .{ |
| | 10199 | .type = .dtpOff(elf), |
| | 10200 | .dynsym_index = sym.unwrap().global.dynsymIndex(elf).?, |
| | 10201 | .addend = 0, |
| | 10202 | } }, |
| 10223 | }, | 10203 | }, |
| 10224 | .dynamic => .{ .reloc = .{ | | |
| 10225 | .type = .dtpMod(elf), | | |
| 10226 | .dynsym_index = 0, | | |
| 10227 | .addend = 0, | | |
| 10228 | } }, | | |
| 10229 | }, | 10204 | }, |
| 10230 | .tlsld1 => .{ .unsigned = 0 }, | | |
| 10231 | }; | 10205 | }; |
| 10232 | | 10206 | |
| 10233 | // First, write to the GOT itself. If we're planning to use a relocation, we'll just write zeroes. | 10207 | // First, write to the GOT itself. If we're planning to use a relocation, we'll just write zeroes. |
| ... | @@ -10994,7 +10968,7 @@ pub fn idle(elf: *Elf) link.Error!bool { | ... | @@ -10994,7 +10968,7 @@ pub fn idle(elf: *Elf) link.Error!bool { |
| 10994 | var ri = symtab_index.ptr(elf).first_target_reloc; | 10968 | var ri = symtab_index.ptr(elf).first_target_reloc; |
| 10995 | while (ri != .none) { | 10969 | while (ri != .none) { |
| 10996 | const reloc = ri.get(elf); | 10970 | const reloc = ri.get(elf); |
| 10997 | assert(reloc.target == sym_id); | 10971 | assert(reloc.target_symbol == sym_id); |
| 10998 | // In relocatables, every symbol relocation has an output relocation. | 10972 | // In relocatables, every symbol relocation has an output relocation. |
| 10999 | const rela_index = reloc.rela_index.unwrap().?; | 10973 | const rela_index = reloc.rela_index.unwrap().?; |
| 11000 | reloc.relaSection(elf).relaUpdateSym(elf, rela_index, @backingInt(symtab_index)); | 10974 | reloc.relaSection(elf).relaUpdateSym(elf, rela_index, @backingInt(symtab_index)); |
| ... | @@ -11024,7 +10998,7 @@ pub fn idle(elf: *Elf) link.Error!bool { | ... | @@ -11024,7 +10998,7 @@ pub fn idle(elf: *Elf) link.Error!bool { |
| 11024 | var ri = symtab_index.ptr(elf).first_target_reloc; | 10998 | var ri = symtab_index.ptr(elf).first_target_reloc; |
| 11025 | while (ri != .none) { | 10999 | while (ri != .none) { |
| 11026 | const reloc = ri.get(elf); | 11000 | const reloc = ri.get(elf); |
| 11027 | assert(reloc.target == sym_id); | 11001 | assert(reloc.target_symbol == sym_id); |
| 11028 | // There may or may not be a runtime relocation for this symbol reloc. | 11002 | // There may or may not be a runtime relocation for this symbol reloc. |
| 11029 | if (reloc.rela_index.unwrap()) |rela_index| { | 11003 | if (reloc.rela_index.unwrap()) |rela_index| { |
| 11030 | elf.shndx.rela_dyn.relaUpdateSym(elf, rela_index, dynsym_index); | 11004 | elf.shndx.rela_dyn.relaUpdateSym(elf, rela_index, dynsym_index); |
| ... | @@ -11615,8 +11589,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -11615,8 +11589,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 11615 | const rela_index = opt_rela_index.unwrap() orelse continue; | 11589 | const rela_index = opt_rela_index.unwrap() orelse continue; |
| 11616 | rela_dyn_shndx.relaAdjustOffset(elf, rela_index, old_addr, addr); | 11590 | rela_dyn_shndx.relaAdjustOffset(elf, rela_index, old_addr, addr); |
| 11617 | } | 11591 | } |
| 11618 | for (elf.got_relocs.items) |*reloc| { | 11592 | for (elf.got_relocs.keys()) |ri| { |
| 11619 | reloc.apply(elf); | 11593 | ri.get(elf).apply(elf); |
| 11620 | } | 11594 | } |
| 11621 | } else if (shndx == elf.shndx.plt) { | 11595 | } else if (shndx == elf.shndx.plt) { |
| 11622 | elf.flushMovedNodeRelocs(ni, .{ | 11596 | elf.flushMovedNodeRelocs(ni, .{ |
| ... | @@ -11683,7 +11657,6 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -11683,7 +11657,6 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 11683 | | 11657 | |
| 11684 | elf.flushMovedNodeRelocs(ni, .{ | 11658 | elf.flushMovedNodeRelocs(ni, .{ |
| 11685 | .first_symbol_reloc = isi.ptrConst(elf).first_symbol_reloc, | 11659 | .first_symbol_reloc = isi.ptrConst(elf).first_symbol_reloc, |
| 11686 | .first_got_reloc = isi.ptrConst(elf).first_got_reloc, | | |
| 11687 | }); | 11660 | }); |
| 11688 | }, | 11661 | }, |
| 11689 | .copied_global => |global_name| { | 11662 | .copied_global => |global_name| { |
| ... | @@ -11714,7 +11687,6 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -11714,7 +11687,6 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 11714 | .none, | 11687 | .none, |
| 11715 | .uav, .lazy_code, .lazy_const_data => .none, | 11688 | .uav, .lazy_code, .lazy_const_data => .none, |
| 11716 | }, | 11689 | }, |
| 11717 | .first_got_reloc = mi.firstGotReloc(elf), | | |
| 11718 | }); | 11690 | }); |
| 11719 | }, | 11691 | }, |
| 11720 | .debug_shared => |ss| { | 11692 | .debug_shared => |ss| { |
| ... | @@ -12200,8 +12172,6 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -12200,8 +12172,6 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 12200 | switch (got_key) { | 12172 | switch (got_key) { |
| 12201 | .reserved, | 12173 | .reserved, |
| 12202 | .symbol, | 12174 | .symbol, |
| 12203 | .tlsld0, | | |
| 12204 | .tlsld1, | | |
| 12205 | .tlsgd0, | 12175 | .tlsgd0, |
| 12206 | .tlsgd1, | 12176 | .tlsgd1, |
| 12207 | => { | 12177 | => { |