@@ -1011,6 +1011,135 @@ void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,
1011
1011
}
1012
1012
}
1013
1013
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
+
1014
1143
// The target location for the relocation is described by RE.SectionID and
1015
1144
// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
1016
1145
// SectionEntry has three members describing its location.
@@ -1076,12 +1205,17 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
1076
1205
case Triple::bpfeb:
1077
1206
resolveBPFRelocation (Section, Offset, Value, Type, Addend);
1078
1207
break ;
1208
+ case Triple::riscv32: // Fall through.
1209
+ case Triple::riscv64:
1210
+ resolveRISCVRelocation (Section, Offset, Value, Type, Addend, SectionID);
1211
+ break ;
1079
1212
default :
1080
1213
llvm_unreachable (" Unsupported CPU type!" );
1081
1214
}
1082
1215
}
1083
1216
1084
- void *RuntimeDyldELF::computePlaceholderAddress (unsigned SectionID, uint64_t Offset) const {
1217
+ void *RuntimeDyldELF::computePlaceholderAddress (unsigned SectionID,
1218
+ uint64_t Offset) const {
1085
1219
return (void *)(Sections[SectionID].getObjAddress () + Offset);
1086
1220
}
1087
1221
@@ -1870,7 +2004,8 @@ RuntimeDyldELF::processRelocationRef(
1870
2004
Value.Addend += support::ulittle32_t::ref (computePlaceholderAddress (SectionID, Offset));
1871
2005
processSimpleRelocation (SectionID, Offset, RelType, Value);
1872
2006
} 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));
1874
2009
processSimpleRelocation (SectionID, Offset, RelType, Value);
1875
2010
} else if (RelType == ELF::R_X86_64_GOTTPOFF) {
1876
2011
processX86_64GOTTPOFFRelocation (SectionID, Offset, Value, Addend);
@@ -1884,9 +2019,23 @@ RuntimeDyldELF::processRelocationRef(
1884
2019
} else {
1885
2020
processSimpleRelocation (SectionID, Offset, RelType, Value);
1886
2021
}
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);
1887
2035
} else {
1888
2036
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));
1890
2039
}
1891
2040
processSimpleRelocation (SectionID, Offset, RelType, Value);
1892
2041
}
0 commit comments