@@ -1011,6 +1011,135 @@ void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,
10111011 }
10121012}
10131013
1014+ static void applyUTypeImmRISCV (uint8_t *InstrAddr, uint32_t Imm) {
1015+ uint32_t UpperImm = (Imm + 0x800 ) & 0xfffff000 ;
1016+ auto Instr = support::ulittle32_t::ref (InstrAddr);
1017+ Instr = (Instr & 0xfff ) | UpperImm;
1018+ }
1019+
1020+ static void applyITypeImmRISCV (uint8_t *InstrAddr, uint32_t Imm) {
1021+ uint32_t LowerImm = Imm & 0xfff ;
1022+ auto Instr = support::ulittle32_t::ref (InstrAddr);
1023+ Instr = (Instr & 0xfffff ) | (LowerImm << 20 );
1024+ }
1025+
1026+ void RuntimeDyldELF::resolveRISCVRelocation (const SectionEntry &Section,
1027+ uint64_t Offset, uint64_t Value,
1028+ uint32_t Type, int64_t Addend,
1029+ SID SectionID) {
1030+ switch (Type) {
1031+ default : {
1032+ std::string Err = " Unimplemented reloc type: " + std::to_string (Type);
1033+ llvm::report_fatal_error (Err.c_str ());
1034+ }
1035+ // 32-bit PC-relative function call, macros call, tail (PIC)
1036+ // Write first 20 bits of 32 bit value to the auipc instruction
1037+ // Last 12 bits to the jalr instruction
1038+ case ELF::R_RISCV_CALL:
1039+ case ELF::R_RISCV_CALL_PLT: {
1040+ uint64_t P = Section.getLoadAddressWithOffset (Offset);
1041+ uint64_t PCOffset = Value + Addend - P;
1042+ applyUTypeImmRISCV (Section.getAddressWithOffset (Offset), PCOffset);
1043+ applyITypeImmRISCV (Section.getAddressWithOffset (Offset + 4 ), PCOffset);
1044+ break ;
1045+ }
1046+ // High 20 bits of 32-bit absolute address, %hi(symbol)
1047+ case ELF::R_RISCV_HI20: {
1048+ uint64_t PCOffset = Value + Addend;
1049+ applyUTypeImmRISCV (Section.getAddressWithOffset (Offset), PCOffset);
1050+ break ;
1051+ }
1052+ // Low 12 bits of 32-bit absolute address, %lo(symbol)
1053+ case ELF::R_RISCV_LO12_I: {
1054+ uint64_t PCOffset = Value + Addend;
1055+ applyITypeImmRISCV (Section.getAddressWithOffset (Offset), PCOffset);
1056+ break ;
1057+ }
1058+ // High 20 bits of 32-bit PC-relative reference, %pcrel_hi(symbol)
1059+ case ELF::R_RISCV_GOT_HI20:
1060+ case ELF::R_RISCV_PCREL_HI20: {
1061+ uint64_t P = Section.getLoadAddressWithOffset (Offset);
1062+ uint64_t PCOffset = Value + Addend - P;
1063+ applyUTypeImmRISCV (Section.getAddressWithOffset (Offset), PCOffset);
1064+ break ;
1065+ }
1066+
1067+ // label:
1068+ // auipc a0, %pcrel_hi(symbol) // R_RISCV_PCREL_HI20
1069+ // addi a0, a0, %pcrel_lo(label) // R_RISCV_PCREL_LO12_I
1070+ //
1071+ // The low 12 bits of relative address between pc and symbol.
1072+ // The symbol is related to the high part instruction which is marked by
1073+ // label.
1074+ case ELF::R_RISCV_PCREL_LO12_I: {
1075+ for (auto &&PendingReloc : PendingRelocs) {
1076+ const RelocationValueRef &MatchingValue = PendingReloc.first ;
1077+ RelocationEntry &Reloc = PendingReloc.second ;
1078+ uint64_t HIRelocPC =
1079+ getSectionLoadAddress (Reloc.SectionID ) + Reloc.Offset ;
1080+ if (Value + Addend == HIRelocPC) {
1081+ uint64_t Symbol = getSectionLoadAddress (MatchingValue.SectionID ) +
1082+ MatchingValue.Addend ;
1083+ auto PCOffset = Symbol - HIRelocPC;
1084+ applyITypeImmRISCV (Section.getAddressWithOffset (Offset), PCOffset);
1085+ return ;
1086+ }
1087+ }
1088+
1089+ llvm::report_fatal_error (
1090+ " R_RISCV_PCREL_LO12_I without matching R_RISCV_PCREL_HI20" );
1091+ }
1092+ case ELF::R_RISCV_32_PCREL: {
1093+ uint64_t FinalAddress = Section.getLoadAddressWithOffset (Offset);
1094+ int64_t RealOffset = Value + Addend - FinalAddress;
1095+ int32_t TruncOffset = Lo_32 (RealOffset);
1096+ support::ulittle32_t::ref (Section.getAddressWithOffset (Offset)) =
1097+ TruncOffset;
1098+ break ;
1099+ }
1100+ case ELF::R_RISCV_32: {
1101+ auto Ref = support::ulittle32_t::ref (Section.getAddressWithOffset (Offset));
1102+ Ref = Value + Addend;
1103+ break ;
1104+ }
1105+ case ELF::R_RISCV_64: {
1106+ auto Ref = support::ulittle64_t::ref (Section.getAddressWithOffset (Offset));
1107+ Ref = Value + Addend;
1108+ break ;
1109+ }
1110+ case ELF::R_RISCV_ADD16: {
1111+ auto Ref = support::ulittle16_t::ref (Section.getAddressWithOffset (Offset));
1112+ Ref = Ref + Value + Addend;
1113+ break ;
1114+ }
1115+ case ELF::R_RISCV_ADD32: {
1116+ auto Ref = support::ulittle32_t::ref (Section.getAddressWithOffset (Offset));
1117+ Ref = Ref + Value + Addend;
1118+ break ;
1119+ }
1120+ case ELF::R_RISCV_ADD64: {
1121+ auto Ref = support::ulittle64_t::ref (Section.getAddressWithOffset (Offset));
1122+ Ref = Ref + Value + Addend;
1123+ break ;
1124+ }
1125+ case ELF::R_RISCV_SUB16: {
1126+ auto Ref = support::ulittle16_t::ref (Section.getAddressWithOffset (Offset));
1127+ Ref = Ref - Value - Addend;
1128+ break ;
1129+ }
1130+ case ELF::R_RISCV_SUB32: {
1131+ auto Ref = support::ulittle32_t::ref (Section.getAddressWithOffset (Offset));
1132+ Ref = Ref - Value - Addend;
1133+ break ;
1134+ }
1135+ case ELF::R_RISCV_SUB64: {
1136+ auto Ref = support::ulittle64_t::ref (Section.getAddressWithOffset (Offset));
1137+ Ref = Ref - Value - Addend;
1138+ break ;
1139+ }
1140+ }
1141+ }
1142+
10141143// The target location for the relocation is described by RE.SectionID and
10151144// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
10161145// SectionEntry has three members describing its location.
@@ -1076,12 +1205,17 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
10761205 case Triple::bpfeb:
10771206 resolveBPFRelocation (Section, Offset, Value, Type, Addend);
10781207 break ;
1208+ case Triple::riscv32: // Fall through.
1209+ case Triple::riscv64:
1210+ resolveRISCVRelocation (Section, Offset, Value, Type, Addend, SectionID);
1211+ break ;
10791212 default :
10801213 llvm_unreachable (" Unsupported CPU type!" );
10811214 }
10821215}
10831216
1084- void *RuntimeDyldELF::computePlaceholderAddress (unsigned SectionID, uint64_t Offset) const {
1217+ void *RuntimeDyldELF::computePlaceholderAddress (unsigned SectionID,
1218+ uint64_t Offset) const {
10851219 return (void *)(Sections[SectionID].getObjAddress () + Offset);
10861220}
10871221
@@ -1870,7 +2004,8 @@ RuntimeDyldELF::processRelocationRef(
18702004 Value.Addend += support::ulittle32_t::ref (computePlaceholderAddress (SectionID, Offset));
18712005 processSimpleRelocation (SectionID, Offset, RelType, Value);
18722006 } else if (RelType == ELF::R_X86_64_PC64) {
1873- Value.Addend += support::ulittle64_t::ref (computePlaceholderAddress (SectionID, Offset));
2007+ Value.Addend += support::ulittle64_t::ref (
2008+ computePlaceholderAddress (SectionID, Offset));
18742009 processSimpleRelocation (SectionID, Offset, RelType, Value);
18752010 } else if (RelType == ELF::R_X86_64_GOTTPOFF) {
18762011 processX86_64GOTTPOFFRelocation (SectionID, Offset, Value, Addend);
@@ -1884,9 +2019,23 @@ RuntimeDyldELF::processRelocationRef(
18842019 } else {
18852020 processSimpleRelocation (SectionID, Offset, RelType, Value);
18862021 }
2022+ } else if (Arch == Triple::riscv32 || Arch == Triple::riscv64) {
2023+ // *_LO12 relocation receive information about a symbol from the
2024+ // corresponding *_HI20 relocation, so we have to collect this information
2025+ // before resolving
2026+ if (RelType == ELF::R_RISCV_GOT_HI20 ||
2027+ RelType == ELF::R_RISCV_PCREL_HI20 ||
2028+ RelType == ELF::R_RISCV_TPREL_HI20 ||
2029+ RelType == ELF::R_RISCV_TLS_GD_HI20 ||
2030+ RelType == ELF::R_RISCV_TLS_GOT_HI20) {
2031+ RelocationEntry RE (SectionID, Offset, RelType, Addend);
2032+ PendingRelocs.push_back ({Value, RE});
2033+ }
2034+ processSimpleRelocation (SectionID, Offset, RelType, Value);
18872035 } else {
18882036 if (Arch == Triple::x86) {
1889- Value.Addend += support::ulittle32_t::ref (computePlaceholderAddress (SectionID, Offset));
2037+ Value.Addend += support::ulittle32_t::ref (
2038+ computePlaceholderAddress (SectionID, Offset));
18902039 }
18912040 processSimpleRelocation (SectionID, Offset, RelType, Value);
18922041 }
0 commit comments