@@ -738,6 +738,32 @@ static inline uint32_t extractBits(uint64_t Val, uint32_t Hi, uint32_t Lo) {
738
738
return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1 )) - 1 ))) >> Lo;
739
739
}
740
740
741
+ // Calculate the adjusted page delta between dest and PC. The code is copied
742
+ // from lld and see comments there for more details.
743
+ static uint64_t getLoongArchPageDelta (uint64_t dest, uint64_t pc,
744
+ uint32_t type) {
745
+ uint64_t pcalau12i_pc;
746
+ switch (type) {
747
+ case ELF::R_LARCH_PCALA64_LO20:
748
+ case ELF::R_LARCH_GOT64_PC_LO20:
749
+ pcalau12i_pc = pc - 8 ;
750
+ break ;
751
+ case ELF::R_LARCH_PCALA64_HI12:
752
+ case ELF::R_LARCH_GOT64_PC_HI12:
753
+ pcalau12i_pc = pc - 12 ;
754
+ break ;
755
+ default :
756
+ pcalau12i_pc = pc;
757
+ break ;
758
+ }
759
+ uint64_t result = (dest & ~0xfffULL ) - (pcalau12i_pc & ~0xfffULL );
760
+ if (dest & 0x800 )
761
+ result += 0x1000 - 0x1'0000'0000 ;
762
+ if (result & 0x8000'0000 )
763
+ result += 0x1'0000'0000 ;
764
+ return result;
765
+ }
766
+
741
767
void RuntimeDyldELF::resolveLoongArch64Relocation (const SectionEntry &Section,
742
768
uint64_t Offset,
743
769
uint64_t Value, uint32_t Type,
@@ -789,10 +815,7 @@ void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section,
789
815
case ELF::R_LARCH_GOT_PC_HI20:
790
816
case ELF::R_LARCH_PCALA_HI20: {
791
817
uint64_t Target = Value + Addend;
792
- uint64_t TargetPage =
793
- (Target + (Target & 0x800 )) & ~static_cast <uint64_t >(0xfff );
794
- uint64_t PCPage = FinalAddress & ~static_cast <uint64_t >(0xfff );
795
- int64_t PageDelta = TargetPage - PCPage;
818
+ int64_t PageDelta = getLoongArchPageDelta (Target, FinalAddress, Type);
796
819
auto Instr = support::ulittle32_t::ref (TargetPtr);
797
820
uint32_t Imm31_12 = extractBits (PageDelta, /* Hi=*/ 31 , /* Lo=*/ 12 ) << 5 ;
798
821
Instr = (Instr & 0xfe00001f ) | Imm31_12;
@@ -806,6 +829,24 @@ void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section,
806
829
Instr = (Instr & 0xffc003ff ) | Imm11_0;
807
830
break ;
808
831
}
832
+ case ELF::R_LARCH_GOT64_PC_LO20:
833
+ case ELF::R_LARCH_PCALA64_LO20: {
834
+ uint64_t Target = Value + Addend;
835
+ int64_t PageDelta = getLoongArchPageDelta (Target, FinalAddress, Type);
836
+ auto Instr = support::ulittle32_t::ref (TargetPtr);
837
+ uint32_t Imm51_32 = extractBits (PageDelta, /* Hi=*/ 51 , /* Lo=*/ 32 ) << 5 ;
838
+ Instr = (Instr & 0xfe00001f ) | Imm51_32;
839
+ break ;
840
+ }
841
+ case ELF::R_LARCH_GOT64_PC_HI12:
842
+ case ELF::R_LARCH_PCALA64_HI12: {
843
+ uint64_t Target = Value + Addend;
844
+ int64_t PageDelta = getLoongArchPageDelta (Target, FinalAddress, Type);
845
+ auto Instr = support::ulittle32_t::ref (TargetPtr);
846
+ uint32_t Imm63_52 = extractBits (PageDelta, /* Hi=*/ 63 , /* Lo=*/ 52 ) << 10 ;
847
+ Instr = (Instr & 0xffc003ff ) | Imm63_52;
848
+ break ;
849
+ }
809
850
case ELF::R_LARCH_ABS_HI20: {
810
851
uint64_t Target = Value + Addend;
811
852
auto Instr = support::ulittle32_t::ref (TargetPtr);
@@ -1758,7 +1799,9 @@ RuntimeDyldELF::processRelocationRef(
1758
1799
MemMgr.allowStubAllocation ()) {
1759
1800
resolveLoongArch64Branch (SectionID, Value, RelI, Stubs);
1760
1801
} else if (RelType == ELF::R_LARCH_GOT_PC_HI20 ||
1761
- RelType == ELF::R_LARCH_GOT_PC_LO12) {
1802
+ RelType == ELF::R_LARCH_GOT_PC_LO12 ||
1803
+ RelType == ELF::R_LARCH_GOT64_PC_HI12 ||
1804
+ RelType == ELF::R_LARCH_GOT64_PC_LO20) {
1762
1805
uint64_t GOTOffset = findOrAllocGOTEntry (Value, ELF::R_LARCH_64);
1763
1806
resolveGOTOffsetRelocation (SectionID, Offset, GOTOffset + Addend,
1764
1807
RelType);
@@ -2936,7 +2979,9 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
2936
2979
2937
2980
if (Arch == Triple::loongarch64)
2938
2981
return RelTy == ELF::R_LARCH_GOT_PC_HI20 ||
2939
- RelTy == ELF::R_LARCH_GOT_PC_LO12;
2982
+ RelTy == ELF::R_LARCH_GOT_PC_LO12 ||
2983
+ RelTy == ELF::R_LARCH_GOT64_PC_HI12 ||
2984
+ RelTy == ELF::R_LARCH_GOT64_PC_LO20;
2940
2985
2941
2986
if (Arch == Triple::x86_64)
2942
2987
return RelTy == ELF::R_X86_64_GOTPCREL ||
0 commit comments