1 //===------- ELF_riscv.cpp -JIT linker implementation for ELF/riscv -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // ELF/riscv jit-link implementation.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
14 #include "EHFrameSupportImpl.h"
15 #include "ELFLinkGraphBuilder.h"
16 #include "JITLinkGeneric.h"
17 #include "PerGraphGOTAndPLTStubsBuilder.h"
18 #include "llvm/BinaryFormat/ELF.h"
19 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
20 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
21 #include "llvm/ExecutionEngine/JITLink/riscv.h"
22 #include "llvm/Object/ELF.h"
23 #include "llvm/Object/ELFObjectFile.h"
24 #include "llvm/Support/Endian.h"
25
26 #define DEBUG_TYPE "jitlink"
27 using namespace llvm;
28 using namespace llvm::jitlink;
29 using namespace llvm::jitlink::riscv;
30
31 namespace {
32
33 class PerGraphGOTAndPLTStubsBuilder_ELF_riscv
34 : public PerGraphGOTAndPLTStubsBuilder<
35 PerGraphGOTAndPLTStubsBuilder_ELF_riscv> {
36 public:
37 static constexpr size_t StubEntrySize = 16;
38 static const uint8_t NullGOTEntryContent[8];
39 static const uint8_t RV64StubContent[StubEntrySize];
40 static const uint8_t RV32StubContent[StubEntrySize];
41
42 using PerGraphGOTAndPLTStubsBuilder<
43 PerGraphGOTAndPLTStubsBuilder_ELF_riscv>::PerGraphGOTAndPLTStubsBuilder;
44
isRV64() const45 bool isRV64() const { return G.getPointerSize() == 8; }
46
isGOTEdgeToFix(Edge & E) const47 bool isGOTEdgeToFix(Edge &E) const { return E.getKind() == R_RISCV_GOT_HI20; }
48
createGOTEntry(Symbol & Target)49 Symbol &createGOTEntry(Symbol &Target) {
50 Block &GOTBlock =
51 G.createContentBlock(getGOTSection(), getGOTEntryBlockContent(),
52 orc::ExecutorAddr(), G.getPointerSize(), 0);
53 GOTBlock.addEdge(isRV64() ? R_RISCV_64 : R_RISCV_32, 0, Target, 0);
54 return G.addAnonymousSymbol(GOTBlock, 0, G.getPointerSize(), false, false);
55 }
56
createPLTStub(Symbol & Target)57 Symbol &createPLTStub(Symbol &Target) {
58 Block &StubContentBlock = G.createContentBlock(
59 getStubsSection(), getStubBlockContent(), orc::ExecutorAddr(), 4, 0);
60 auto &GOTEntrySymbol = getGOTEntry(Target);
61 StubContentBlock.addEdge(R_RISCV_CALL, 0, GOTEntrySymbol, 0);
62 return G.addAnonymousSymbol(StubContentBlock, 0, StubEntrySize, true,
63 false);
64 }
65
fixGOTEdge(Edge & E,Symbol & GOTEntry)66 void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
67 // Replace the relocation pair (R_RISCV_GOT_HI20, R_RISCV_PCREL_LO12)
68 // with (R_RISCV_PCREL_HI20, R_RISCV_PCREL_LO12)
69 // Therefore, here just change the R_RISCV_GOT_HI20 to R_RISCV_PCREL_HI20
70 E.setKind(R_RISCV_PCREL_HI20);
71 E.setTarget(GOTEntry);
72 }
73
fixPLTEdge(Edge & E,Symbol & PLTStubs)74 void fixPLTEdge(Edge &E, Symbol &PLTStubs) {
75 assert((E.getKind() == R_RISCV_CALL || E.getKind() == R_RISCV_CALL_PLT ||
76 E.getKind() == CallRelaxable) &&
77 "Not a PLT edge?");
78 E.setKind(R_RISCV_CALL);
79 E.setTarget(PLTStubs);
80 }
81
isExternalBranchEdge(Edge & E) const82 bool isExternalBranchEdge(Edge &E) const {
83 return (E.getKind() == R_RISCV_CALL || E.getKind() == R_RISCV_CALL_PLT ||
84 E.getKind() == CallRelaxable) &&
85 !E.getTarget().isDefined();
86 }
87
88 private:
getGOTSection() const89 Section &getGOTSection() const {
90 if (!GOTSection)
91 GOTSection = &G.createSection("$__GOT", orc::MemProt::Read);
92 return *GOTSection;
93 }
94
getStubsSection() const95 Section &getStubsSection() const {
96 if (!StubsSection)
97 StubsSection =
98 &G.createSection("$__STUBS", orc::MemProt::Read | orc::MemProt::Exec);
99 return *StubsSection;
100 }
101
getGOTEntryBlockContent()102 ArrayRef<char> getGOTEntryBlockContent() {
103 return {reinterpret_cast<const char *>(NullGOTEntryContent),
104 G.getPointerSize()};
105 }
106
getStubBlockContent()107 ArrayRef<char> getStubBlockContent() {
108 auto StubContent = isRV64() ? RV64StubContent : RV32StubContent;
109 return {reinterpret_cast<const char *>(StubContent), StubEntrySize};
110 }
111
112 mutable Section *GOTSection = nullptr;
113 mutable Section *StubsSection = nullptr;
114 };
115
116 const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_riscv::NullGOTEntryContent[8] =
117 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
118
119 const uint8_t
120 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::RV64StubContent[StubEntrySize] = {
121 0x17, 0x0e, 0x00, 0x00, // auipc t3, literal
122 0x03, 0x3e, 0x0e, 0x00, // ld t3, literal(t3)
123 0x67, 0x00, 0x0e, 0x00, // jr t3
124 0x13, 0x00, 0x00, 0x00}; // nop
125
126 const uint8_t
127 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::RV32StubContent[StubEntrySize] = {
128 0x17, 0x0e, 0x00, 0x00, // auipc t3, literal
129 0x03, 0x2e, 0x0e, 0x00, // lw t3, literal(t3)
130 0x67, 0x00, 0x0e, 0x00, // jr t3
131 0x13, 0x00, 0x00, 0x00}; // nop
132 } // namespace
133 namespace llvm {
134 namespace jitlink {
135
getRISCVPCRelHi20(const Edge & E)136 static Expected<const Edge &> getRISCVPCRelHi20(const Edge &E) {
137 using namespace riscv;
138 assert((E.getKind() == R_RISCV_PCREL_LO12_I ||
139 E.getKind() == R_RISCV_PCREL_LO12_S) &&
140 "Can only have high relocation for R_RISCV_PCREL_LO12_I or "
141 "R_RISCV_PCREL_LO12_S");
142
143 const Symbol &Sym = E.getTarget();
144 const Block &B = Sym.getBlock();
145 orc::ExecutorAddrDiff Offset = Sym.getOffset();
146
147 struct Comp {
148 bool operator()(const Edge &Lhs, orc::ExecutorAddrDiff Offset) {
149 return Lhs.getOffset() < Offset;
150 }
151 bool operator()(orc::ExecutorAddrDiff Offset, const Edge &Rhs) {
152 return Offset < Rhs.getOffset();
153 }
154 };
155
156 auto Bound =
157 std::equal_range(B.edges().begin(), B.edges().end(), Offset, Comp{});
158
159 for (auto It = Bound.first; It != Bound.second; ++It) {
160 if (It->getKind() == R_RISCV_PCREL_HI20)
161 return *It;
162 }
163
164 return make_error<JITLinkError>(
165 "No HI20 PCREL relocation type be found for LO12 PCREL relocation type");
166 }
167
extractBits(uint32_t Num,unsigned Low,unsigned Size)168 static uint32_t extractBits(uint32_t Num, unsigned Low, unsigned Size) {
169 return (Num & (((1ULL << Size) - 1) << Low)) >> Low;
170 }
171
isAlignmentCorrect(uint64_t Value,int N)172 static inline bool isAlignmentCorrect(uint64_t Value, int N) {
173 return (Value & (N - 1)) ? false : true;
174 }
175
176 // Requires 0 < N <= 64.
isInRangeForImm(int64_t Value,int N)177 static inline bool isInRangeForImm(int64_t Value, int N) {
178 return Value == llvm::SignExtend64(Value, N);
179 }
180
181 class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
182 friend class JITLinker<ELFJITLinker_riscv>;
183
184 public:
ELFJITLinker_riscv(std::unique_ptr<JITLinkContext> Ctx,std::unique_ptr<LinkGraph> G,PassConfiguration PassConfig)185 ELFJITLinker_riscv(std::unique_ptr<JITLinkContext> Ctx,
186 std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
187 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
188
189 private:
applyFixup(LinkGraph & G,Block & B,const Edge & E) const190 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
191 using namespace riscv;
192 using namespace llvm::support;
193
194 char *BlockWorkingMem = B.getAlreadyMutableContent().data();
195 char *FixupPtr = BlockWorkingMem + E.getOffset();
196 orc::ExecutorAddr FixupAddress = B.getAddress() + E.getOffset();
197 switch (E.getKind()) {
198 case R_RISCV_32: {
199 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
200 *(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
201 break;
202 }
203 case R_RISCV_64: {
204 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
205 *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
206 break;
207 }
208 case R_RISCV_BRANCH: {
209 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
210 if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 12)))
211 return makeTargetOutOfRangeError(G, B, E);
212 if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2)))
213 return makeAlignmentError(FixupAddress, Value, 2, E);
214 uint32_t Imm12 = extractBits(Value, 12, 1) << 31;
215 uint32_t Imm10_5 = extractBits(Value, 5, 6) << 25;
216 uint32_t Imm4_1 = extractBits(Value, 1, 4) << 8;
217 uint32_t Imm11 = extractBits(Value, 11, 1) << 7;
218 uint32_t RawInstr = *(little32_t *)FixupPtr;
219 *(little32_t *)FixupPtr =
220 (RawInstr & 0x1FFF07F) | Imm12 | Imm10_5 | Imm4_1 | Imm11;
221 break;
222 }
223 case R_RISCV_JAL: {
224 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
225 if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 20)))
226 return makeTargetOutOfRangeError(G, B, E);
227 if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2)))
228 return makeAlignmentError(FixupAddress, Value, 2, E);
229 uint32_t Imm20 = extractBits(Value, 20, 1) << 31;
230 uint32_t Imm10_1 = extractBits(Value, 1, 10) << 21;
231 uint32_t Imm11 = extractBits(Value, 11, 1) << 20;
232 uint32_t Imm19_12 = extractBits(Value, 12, 8) << 12;
233 uint32_t RawInstr = *(little32_t *)FixupPtr;
234 *(little32_t *)FixupPtr =
235 (RawInstr & 0xFFF) | Imm20 | Imm10_1 | Imm11 | Imm19_12;
236 break;
237 }
238 case CallRelaxable:
239 // Treat as R_RISCV_CALL when the relaxation pass did not run
240 case R_RISCV_CALL_PLT:
241 case R_RISCV_CALL: {
242 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
243 int64_t Hi = Value + 0x800;
244 if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32)))
245 return makeTargetOutOfRangeError(G, B, E);
246 int32_t Lo = Value & 0xFFF;
247 uint32_t RawInstrAuipc = *(little32_t *)FixupPtr;
248 uint32_t RawInstrJalr = *(little32_t *)(FixupPtr + 4);
249 *(little32_t *)FixupPtr =
250 RawInstrAuipc | (static_cast<uint32_t>(Hi & 0xFFFFF000));
251 *(little32_t *)(FixupPtr + 4) =
252 RawInstrJalr | (static_cast<uint32_t>(Lo) << 20);
253 break;
254 }
255 // The relocations R_RISCV_CALL_PLT and R_RISCV_GOT_HI20 are handled by
256 // PerGraphGOTAndPLTStubsBuilder_ELF_riscv and are transformed into
257 // R_RISCV_CALL and R_RISCV_PCREL_HI20.
258 case R_RISCV_PCREL_HI20: {
259 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
260 int64_t Hi = Value + 0x800;
261 if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32)))
262 return makeTargetOutOfRangeError(G, B, E);
263 uint32_t RawInstr = *(little32_t *)FixupPtr;
264 *(little32_t *)FixupPtr =
265 (RawInstr & 0xFFF) | (static_cast<uint32_t>(Hi & 0xFFFFF000));
266 break;
267 }
268 case R_RISCV_PCREL_LO12_I: {
269 // FIXME: We assume that R_RISCV_PCREL_HI20 is present in object code and
270 // pairs with current relocation R_RISCV_PCREL_LO12_I. So here may need a
271 // check.
272 auto RelHI20 = getRISCVPCRelHi20(E);
273 if (!RelHI20)
274 return RelHI20.takeError();
275 int64_t Value = RelHI20->getTarget().getAddress() +
276 RelHI20->getAddend() - E.getTarget().getAddress();
277 int64_t Lo = Value & 0xFFF;
278 uint32_t RawInstr = *(little32_t *)FixupPtr;
279 *(little32_t *)FixupPtr =
280 (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);
281 break;
282 }
283 case R_RISCV_PCREL_LO12_S: {
284 // FIXME: We assume that R_RISCV_PCREL_HI20 is present in object code and
285 // pairs with current relocation R_RISCV_PCREL_LO12_S. So here may need a
286 // check.
287 auto RelHI20 = getRISCVPCRelHi20(E);
288 if (!RelHI20)
289 return RelHI20.takeError();
290 int64_t Value = RelHI20->getTarget().getAddress() +
291 RelHI20->getAddend() - E.getTarget().getAddress();
292 int64_t Lo = Value & 0xFFF;
293 uint32_t Imm11_5 = extractBits(Lo, 5, 7) << 25;
294 uint32_t Imm4_0 = extractBits(Lo, 0, 5) << 7;
295 uint32_t RawInstr = *(little32_t *)FixupPtr;
296
297 *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
298 break;
299 }
300 case R_RISCV_HI20: {
301 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
302 int64_t Hi = Value + 0x800;
303 if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32)))
304 return makeTargetOutOfRangeError(G, B, E);
305 uint32_t RawInstr = *(little32_t *)FixupPtr;
306 *(little32_t *)FixupPtr =
307 (RawInstr & 0xFFF) | (static_cast<uint32_t>(Hi & 0xFFFFF000));
308 break;
309 }
310 case R_RISCV_LO12_I: {
311 // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs
312 // with current relocation R_RISCV_LO12_I. So here may need a check.
313 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
314 int32_t Lo = Value & 0xFFF;
315 uint32_t RawInstr = *(little32_t *)FixupPtr;
316 *(little32_t *)FixupPtr =
317 (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);
318 break;
319 }
320 case R_RISCV_LO12_S: {
321 // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs
322 // with current relocation R_RISCV_LO12_S. So here may need a check.
323 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
324 int64_t Lo = Value & 0xFFF;
325 uint32_t Imm11_5 = extractBits(Lo, 5, 7) << 25;
326 uint32_t Imm4_0 = extractBits(Lo, 0, 5) << 7;
327 uint32_t RawInstr = *(little32_t *)FixupPtr;
328 *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm11_5 | Imm4_0;
329 break;
330 }
331 case R_RISCV_ADD8: {
332 int64_t Value =
333 (E.getTarget().getAddress() +
334 *(reinterpret_cast<const uint8_t *>(FixupPtr)) + E.getAddend())
335 .getValue();
336 *FixupPtr = static_cast<uint8_t>(Value);
337 break;
338 }
339 case R_RISCV_ADD16: {
340 int64_t Value = (E.getTarget().getAddress() +
341 support::endian::read16le(FixupPtr) + E.getAddend())
342 .getValue();
343 *(little16_t *)FixupPtr = static_cast<uint16_t>(Value);
344 break;
345 }
346 case R_RISCV_ADD32: {
347 int64_t Value = (E.getTarget().getAddress() +
348 support::endian::read32le(FixupPtr) + E.getAddend())
349 .getValue();
350 *(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
351 break;
352 }
353 case R_RISCV_ADD64: {
354 int64_t Value = (E.getTarget().getAddress() +
355 support::endian::read64le(FixupPtr) + E.getAddend())
356 .getValue();
357 *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
358 break;
359 }
360 case R_RISCV_SUB8: {
361 int64_t Value = *(reinterpret_cast<const uint8_t *>(FixupPtr)) -
362 E.getTarget().getAddress().getValue() - E.getAddend();
363 *FixupPtr = static_cast<uint8_t>(Value);
364 break;
365 }
366 case R_RISCV_SUB16: {
367 int64_t Value = support::endian::read16le(FixupPtr) -
368 E.getTarget().getAddress().getValue() - E.getAddend();
369 *(little16_t *)FixupPtr = static_cast<uint32_t>(Value);
370 break;
371 }
372 case R_RISCV_SUB32: {
373 int64_t Value = support::endian::read32le(FixupPtr) -
374 E.getTarget().getAddress().getValue() - E.getAddend();
375 *(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
376 break;
377 }
378 case R_RISCV_SUB64: {
379 int64_t Value = support::endian::read64le(FixupPtr) -
380 E.getTarget().getAddress().getValue() - E.getAddend();
381 *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
382 break;
383 }
384 case R_RISCV_RVC_BRANCH: {
385 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
386 if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 8)))
387 return makeTargetOutOfRangeError(G, B, E);
388 if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2)))
389 return makeAlignmentError(FixupAddress, Value, 2, E);
390 uint16_t Imm8 = extractBits(Value, 8, 1) << 12;
391 uint16_t Imm4_3 = extractBits(Value, 3, 2) << 10;
392 uint16_t Imm7_6 = extractBits(Value, 6, 2) << 5;
393 uint16_t Imm2_1 = extractBits(Value, 1, 2) << 3;
394 uint16_t Imm5 = extractBits(Value, 5, 1) << 2;
395 uint16_t RawInstr = *(little16_t *)FixupPtr;
396 *(little16_t *)FixupPtr =
397 (RawInstr & 0xE383) | Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;
398 break;
399 }
400 case R_RISCV_RVC_JUMP: {
401 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
402 if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 11)))
403 return makeTargetOutOfRangeError(G, B, E);
404 if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2)))
405 return makeAlignmentError(FixupAddress, Value, 2, E);
406 uint16_t Imm11 = extractBits(Value, 11, 1) << 12;
407 uint16_t Imm4 = extractBits(Value, 4, 1) << 11;
408 uint16_t Imm9_8 = extractBits(Value, 8, 2) << 9;
409 uint16_t Imm10 = extractBits(Value, 10, 1) << 8;
410 uint16_t Imm6 = extractBits(Value, 6, 1) << 7;
411 uint16_t Imm7 = extractBits(Value, 7, 1) << 6;
412 uint16_t Imm3_1 = extractBits(Value, 1, 3) << 3;
413 uint16_t Imm5 = extractBits(Value, 5, 1) << 2;
414 uint16_t RawInstr = *(little16_t *)FixupPtr;
415 *(little16_t *)FixupPtr = (RawInstr & 0xE003) | Imm11 | Imm4 | Imm9_8 |
416 Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;
417 break;
418 }
419 case R_RISCV_SUB6: {
420 int64_t Value = *(reinterpret_cast<const uint8_t *>(FixupPtr)) & 0x3f;
421 Value -= E.getTarget().getAddress().getValue() - E.getAddend();
422 *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<uint8_t>(Value) & 0x3f);
423 break;
424 }
425 case R_RISCV_SET6: {
426 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
427 uint32_t RawData = *(little32_t *)FixupPtr;
428 int64_t Word6 = Value & 0x3f;
429 *(little32_t *)FixupPtr = (RawData & 0xffffffc0) | Word6;
430 break;
431 }
432 case R_RISCV_SET8: {
433 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
434 uint32_t RawData = *(little32_t *)FixupPtr;
435 int64_t Word8 = Value & 0xff;
436 *(little32_t *)FixupPtr = (RawData & 0xffffff00) | Word8;
437 break;
438 }
439 case R_RISCV_SET16: {
440 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
441 uint32_t RawData = *(little32_t *)FixupPtr;
442 int64_t Word16 = Value & 0xffff;
443 *(little32_t *)FixupPtr = (RawData & 0xffff0000) | Word16;
444 break;
445 }
446 case R_RISCV_SET32: {
447 int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
448 int64_t Word32 = Value & 0xffffffff;
449 *(little32_t *)FixupPtr = Word32;
450 break;
451 }
452 case R_RISCV_32_PCREL: {
453 int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
454 int64_t Word32 = Value & 0xffffffff;
455 *(little32_t *)FixupPtr = Word32;
456 break;
457 }
458 case AlignRelaxable:
459 // Ignore when the relaxation pass did not run
460 break;
461 case NegDelta32: {
462 int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
463 if (LLVM_UNLIKELY(!isInRangeForImm(Value, 32)))
464 return makeTargetOutOfRangeError(G, B, E);
465 *(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
466 break;
467 }
468 }
469 return Error::success();
470 }
471 };
472
473 namespace {
474
475 struct SymbolAnchor {
476 uint64_t Offset;
477 Symbol *Sym;
478 bool End; // true for the anchor of getOffset() + getSize()
479 };
480
481 struct BlockRelaxAux {
482 // This records symbol start and end offsets which will be adjusted according
483 // to the nearest RelocDeltas element.
484 SmallVector<SymbolAnchor, 0> Anchors;
485 // All edges that either 1) are R_RISCV_ALIGN or 2) have a R_RISCV_RELAX edge
486 // at the same offset.
487 SmallVector<Edge *, 0> RelaxEdges;
488 // For RelaxEdges[I], the actual offset is RelaxEdges[I]->getOffset() - (I ?
489 // RelocDeltas[I - 1] : 0).
490 SmallVector<uint32_t, 0> RelocDeltas;
491 // For RelaxEdges[I], the actual type is EdgeKinds[I].
492 SmallVector<Edge::Kind, 0> EdgeKinds;
493 // List of rewritten instructions. Contains one raw encoded instruction per
494 // element in EdgeKinds that isn't Invalid or R_RISCV_ALIGN.
495 SmallVector<uint32_t, 0> Writes;
496 };
497
498 struct RelaxConfig {
499 bool IsRV32;
500 bool HasRVC;
501 };
502
503 struct RelaxAux {
504 RelaxConfig Config;
505 DenseMap<Block *, BlockRelaxAux> Blocks;
506 };
507
508 } // namespace
509
shouldRelax(const Section & S)510 static bool shouldRelax(const Section &S) {
511 return (S.getMemProt() & orc::MemProt::Exec) != orc::MemProt::None;
512 }
513
isRelaxable(const Edge & E)514 static bool isRelaxable(const Edge &E) {
515 switch (E.getKind()) {
516 default:
517 return false;
518 case CallRelaxable:
519 case AlignRelaxable:
520 return true;
521 }
522 }
523
initRelaxAux(LinkGraph & G)524 static RelaxAux initRelaxAux(LinkGraph &G) {
525 RelaxAux Aux;
526 Aux.Config.IsRV32 = G.getTargetTriple().isRISCV32();
527 const auto &Features = G.getFeatures().getFeatures();
528 Aux.Config.HasRVC = llvm::is_contained(Features, "+c");
529
530 for (auto &S : G.sections()) {
531 if (!shouldRelax(S))
532 continue;
533 for (auto *B : S.blocks()) {
534 auto BlockEmplaceResult = Aux.Blocks.try_emplace(B);
535 assert(BlockEmplaceResult.second && "Block encountered twice");
536 auto &BlockAux = BlockEmplaceResult.first->second;
537
538 for (auto &E : B->edges())
539 if (isRelaxable(E))
540 BlockAux.RelaxEdges.push_back(&E);
541
542 if (BlockAux.RelaxEdges.empty()) {
543 Aux.Blocks.erase(BlockEmplaceResult.first);
544 continue;
545 }
546
547 const auto NumEdges = BlockAux.RelaxEdges.size();
548 BlockAux.RelocDeltas.resize(NumEdges, 0);
549 BlockAux.EdgeKinds.resize_for_overwrite(NumEdges);
550
551 // Store anchors (offset and offset+size) for symbols.
552 for (auto *Sym : S.symbols()) {
553 if (!Sym->isDefined() || &Sym->getBlock() != B)
554 continue;
555
556 BlockAux.Anchors.push_back({Sym->getOffset(), Sym, false});
557 BlockAux.Anchors.push_back(
558 {Sym->getOffset() + Sym->getSize(), Sym, true});
559 }
560 }
561 }
562
563 // Sort anchors by offset so that we can find the closest relocation
564 // efficiently. For a zero size symbol, ensure that its start anchor precedes
565 // its end anchor. For two symbols with anchors at the same offset, their
566 // order does not matter.
567 for (auto &BlockAuxIter : Aux.Blocks) {
568 llvm::sort(BlockAuxIter.second.Anchors, [](auto &A, auto &B) {
569 return std::make_pair(A.Offset, A.End) < std::make_pair(B.Offset, B.End);
570 });
571 }
572
573 return Aux;
574 }
575
relaxAlign(orc::ExecutorAddr Loc,const Edge & E,uint32_t & Remove,Edge::Kind & NewEdgeKind)576 static void relaxAlign(orc::ExecutorAddr Loc, const Edge &E, uint32_t &Remove,
577 Edge::Kind &NewEdgeKind) {
578 // E points to the start of the padding bytes.
579 // E + Addend points to the instruction to be aligned by removing padding.
580 // Alignment is the smallest power of 2 strictly greater than Addend.
581 const auto Align = NextPowerOf2(E.getAddend());
582 const auto DestLoc = alignTo(Loc.getValue(), Align);
583 const auto SrcLoc = Loc.getValue() + E.getAddend();
584 Remove = SrcLoc - DestLoc;
585 assert(static_cast<int32_t>(Remove) >= 0 &&
586 "R_RISCV_ALIGN needs expanding the content");
587 NewEdgeKind = AlignRelaxable;
588 }
589
relaxCall(const Block & B,BlockRelaxAux & Aux,const RelaxConfig & Config,orc::ExecutorAddr Loc,const Edge & E,uint32_t & Remove,Edge::Kind & NewEdgeKind)590 static void relaxCall(const Block &B, BlockRelaxAux &Aux,
591 const RelaxConfig &Config, orc::ExecutorAddr Loc,
592 const Edge &E, uint32_t &Remove,
593 Edge::Kind &NewEdgeKind) {
594 const auto JALR =
595 support::endian::read32le(B.getContent().data() + E.getOffset() + 4);
596 const auto RD = extractBits(JALR, 7, 5);
597 const auto Dest = E.getTarget().getAddress() + E.getAddend();
598 const auto Displace = Dest - Loc;
599
600 if (Config.HasRVC && isInt<12>(Displace) && RD == 0) {
601 NewEdgeKind = R_RISCV_RVC_JUMP;
602 Aux.Writes.push_back(0xa001); // c.j
603 Remove = 6;
604 } else if (Config.HasRVC && Config.IsRV32 && isInt<12>(Displace) && RD == 1) {
605 NewEdgeKind = R_RISCV_RVC_JUMP;
606 Aux.Writes.push_back(0x2001); // c.jal
607 Remove = 6;
608 } else if (isInt<21>(Displace)) {
609 NewEdgeKind = R_RISCV_JAL;
610 Aux.Writes.push_back(0x6f | RD << 7); // jal
611 Remove = 4;
612 } else {
613 // Not relaxable
614 NewEdgeKind = R_RISCV_CALL_PLT;
615 Remove = 0;
616 }
617 }
618
relaxBlock(LinkGraph & G,Block & Block,BlockRelaxAux & Aux,const RelaxConfig & Config)619 static bool relaxBlock(LinkGraph &G, Block &Block, BlockRelaxAux &Aux,
620 const RelaxConfig &Config) {
621 const auto BlockAddr = Block.getAddress();
622 bool Changed = false;
623 ArrayRef<SymbolAnchor> SA = ArrayRef(Aux.Anchors);
624 uint32_t Delta = 0;
625
626 Aux.EdgeKinds.assign(Aux.EdgeKinds.size(), Edge::Invalid);
627 Aux.Writes.clear();
628
629 for (auto [I, E] : llvm::enumerate(Aux.RelaxEdges)) {
630 const auto Loc = BlockAddr + E->getOffset() - Delta;
631 auto &Cur = Aux.RelocDeltas[I];
632 uint32_t Remove = 0;
633 switch (E->getKind()) {
634 case AlignRelaxable:
635 relaxAlign(Loc, *E, Remove, Aux.EdgeKinds[I]);
636 break;
637 case CallRelaxable:
638 relaxCall(Block, Aux, Config, Loc, *E, Remove, Aux.EdgeKinds[I]);
639 break;
640 default:
641 llvm_unreachable("Unexpected relaxable edge kind");
642 }
643
644 // For all anchors whose offsets are <= E->getOffset(), they are preceded by
645 // the previous relocation whose RelocDeltas value equals Delta.
646 // Decrease their offset and update their size.
647 for (; SA.size() && SA[0].Offset <= E->getOffset(); SA = SA.slice(1)) {
648 if (SA[0].End)
649 SA[0].Sym->setSize(SA[0].Offset - Delta - SA[0].Sym->getOffset());
650 else
651 SA[0].Sym->setOffset(SA[0].Offset - Delta);
652 }
653
654 Delta += Remove;
655 if (Delta != Cur) {
656 Cur = Delta;
657 Changed = true;
658 }
659 }
660
661 for (const SymbolAnchor &A : SA) {
662 if (A.End)
663 A.Sym->setSize(A.Offset - Delta - A.Sym->getOffset());
664 else
665 A.Sym->setOffset(A.Offset - Delta);
666 }
667
668 return Changed;
669 }
670
relaxOnce(LinkGraph & G,RelaxAux & Aux)671 static bool relaxOnce(LinkGraph &G, RelaxAux &Aux) {
672 bool Changed = false;
673
674 for (auto &[B, BlockAux] : Aux.Blocks)
675 Changed |= relaxBlock(G, *B, BlockAux, Aux.Config);
676
677 return Changed;
678 }
679
finalizeBlockRelax(LinkGraph & G,Block & Block,BlockRelaxAux & Aux)680 static void finalizeBlockRelax(LinkGraph &G, Block &Block, BlockRelaxAux &Aux) {
681 auto Contents = Block.getAlreadyMutableContent();
682 auto *Dest = Contents.data();
683 auto NextWrite = Aux.Writes.begin();
684 uint32_t Offset = 0;
685 uint32_t Delta = 0;
686
687 // Update section content: remove NOPs for R_RISCV_ALIGN and rewrite
688 // instructions for relaxed relocations.
689 for (auto [I, E] : llvm::enumerate(Aux.RelaxEdges)) {
690 uint32_t Remove = Aux.RelocDeltas[I] - Delta;
691 Delta = Aux.RelocDeltas[I];
692 if (Remove == 0 && Aux.EdgeKinds[I] == Edge::Invalid)
693 continue;
694
695 // Copy from last location to the current relocated location.
696 const auto Size = E->getOffset() - Offset;
697 std::memmove(Dest, Contents.data() + Offset, Size);
698 Dest += Size;
699
700 uint32_t Skip = 0;
701 switch (Aux.EdgeKinds[I]) {
702 case Edge::Invalid:
703 break;
704 case AlignRelaxable:
705 // For R_RISCV_ALIGN, we will place Offset in a location (among NOPs) to
706 // satisfy the alignment requirement. If both Remove and E->getAddend()
707 // are multiples of 4, it is as if we have skipped some NOPs. Otherwise we
708 // are in the middle of a 4-byte NOP, and we need to rewrite the NOP
709 // sequence.
710 if (Remove % 4 || E->getAddend() % 4) {
711 Skip = E->getAddend() - Remove;
712 uint32_t J = 0;
713 for (; J + 4 <= Skip; J += 4)
714 support::endian::write32le(Dest + J, 0x00000013); // nop
715 if (J != Skip) {
716 assert(J + 2 == Skip);
717 support::endian::write16le(Dest + J, 0x0001); // c.nop
718 }
719 }
720 break;
721 case R_RISCV_RVC_JUMP:
722 Skip = 2;
723 support::endian::write16le(Dest, *NextWrite++);
724 break;
725 case R_RISCV_JAL:
726 Skip = 4;
727 support::endian::write32le(Dest, *NextWrite++);
728 break;
729 }
730
731 Dest += Skip;
732 Offset = E->getOffset() + Skip + Remove;
733 }
734
735 std::memmove(Dest, Contents.data() + Offset, Contents.size() - Offset);
736
737 // Fixup edge offsets and kinds.
738 Delta = 0;
739 size_t I = 0;
740 for (auto &E : Block.edges()) {
741 E.setOffset(E.getOffset() - Delta);
742
743 if (I < Aux.RelaxEdges.size() && Aux.RelaxEdges[I] == &E) {
744 if (Aux.EdgeKinds[I] != Edge::Invalid)
745 E.setKind(Aux.EdgeKinds[I]);
746
747 Delta = Aux.RelocDeltas[I];
748 ++I;
749 }
750 }
751
752 // Remove AlignRelaxable edges: all other relaxable edges got modified and
753 // will be used later while linking. Alignment is entirely handled here so we
754 // don't need these edges anymore.
755 for (auto IE = Block.edges().begin(); IE != Block.edges().end();) {
756 if (IE->getKind() == AlignRelaxable)
757 IE = Block.removeEdge(IE);
758 else
759 ++IE;
760 }
761 }
762
finalizeRelax(LinkGraph & G,RelaxAux & Aux)763 static void finalizeRelax(LinkGraph &G, RelaxAux &Aux) {
764 for (auto &[B, BlockAux] : Aux.Blocks)
765 finalizeBlockRelax(G, *B, BlockAux);
766 }
767
relax(LinkGraph & G)768 static Error relax(LinkGraph &G) {
769 auto Aux = initRelaxAux(G);
770 while (relaxOnce(G, Aux)) {
771 }
772 finalizeRelax(G, Aux);
773 return Error::success();
774 }
775
776 template <typename ELFT>
777 class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
778 private:
779 static Expected<riscv::EdgeKind_riscv>
getRelocationKind(const uint32_t Type)780 getRelocationKind(const uint32_t Type) {
781 using namespace riscv;
782 switch (Type) {
783 case ELF::R_RISCV_32:
784 return EdgeKind_riscv::R_RISCV_32;
785 case ELF::R_RISCV_64:
786 return EdgeKind_riscv::R_RISCV_64;
787 case ELF::R_RISCV_BRANCH:
788 return EdgeKind_riscv::R_RISCV_BRANCH;
789 case ELF::R_RISCV_JAL:
790 return EdgeKind_riscv::R_RISCV_JAL;
791 case ELF::R_RISCV_CALL:
792 return EdgeKind_riscv::R_RISCV_CALL;
793 case ELF::R_RISCV_CALL_PLT:
794 return EdgeKind_riscv::R_RISCV_CALL_PLT;
795 case ELF::R_RISCV_GOT_HI20:
796 return EdgeKind_riscv::R_RISCV_GOT_HI20;
797 case ELF::R_RISCV_PCREL_HI20:
798 return EdgeKind_riscv::R_RISCV_PCREL_HI20;
799 case ELF::R_RISCV_PCREL_LO12_I:
800 return EdgeKind_riscv::R_RISCV_PCREL_LO12_I;
801 case ELF::R_RISCV_PCREL_LO12_S:
802 return EdgeKind_riscv::R_RISCV_PCREL_LO12_S;
803 case ELF::R_RISCV_HI20:
804 return EdgeKind_riscv::R_RISCV_HI20;
805 case ELF::R_RISCV_LO12_I:
806 return EdgeKind_riscv::R_RISCV_LO12_I;
807 case ELF::R_RISCV_LO12_S:
808 return EdgeKind_riscv::R_RISCV_LO12_S;
809 case ELF::R_RISCV_ADD8:
810 return EdgeKind_riscv::R_RISCV_ADD8;
811 case ELF::R_RISCV_ADD16:
812 return EdgeKind_riscv::R_RISCV_ADD16;
813 case ELF::R_RISCV_ADD32:
814 return EdgeKind_riscv::R_RISCV_ADD32;
815 case ELF::R_RISCV_ADD64:
816 return EdgeKind_riscv::R_RISCV_ADD64;
817 case ELF::R_RISCV_SUB8:
818 return EdgeKind_riscv::R_RISCV_SUB8;
819 case ELF::R_RISCV_SUB16:
820 return EdgeKind_riscv::R_RISCV_SUB16;
821 case ELF::R_RISCV_SUB32:
822 return EdgeKind_riscv::R_RISCV_SUB32;
823 case ELF::R_RISCV_SUB64:
824 return EdgeKind_riscv::R_RISCV_SUB64;
825 case ELF::R_RISCV_RVC_BRANCH:
826 return EdgeKind_riscv::R_RISCV_RVC_BRANCH;
827 case ELF::R_RISCV_RVC_JUMP:
828 return EdgeKind_riscv::R_RISCV_RVC_JUMP;
829 case ELF::R_RISCV_SUB6:
830 return EdgeKind_riscv::R_RISCV_SUB6;
831 case ELF::R_RISCV_SET6:
832 return EdgeKind_riscv::R_RISCV_SET6;
833 case ELF::R_RISCV_SET8:
834 return EdgeKind_riscv::R_RISCV_SET8;
835 case ELF::R_RISCV_SET16:
836 return EdgeKind_riscv::R_RISCV_SET16;
837 case ELF::R_RISCV_SET32:
838 return EdgeKind_riscv::R_RISCV_SET32;
839 case ELF::R_RISCV_32_PCREL:
840 return EdgeKind_riscv::R_RISCV_32_PCREL;
841 case ELF::R_RISCV_ALIGN:
842 return EdgeKind_riscv::AlignRelaxable;
843 }
844
845 return make_error<JITLinkError>(
846 "Unsupported riscv relocation:" + formatv("{0:d}: ", Type) +
847 object::getELFRelocationTypeName(ELF::EM_RISCV, Type));
848 }
849
getRelaxableRelocationKind(EdgeKind_riscv Kind)850 EdgeKind_riscv getRelaxableRelocationKind(EdgeKind_riscv Kind) {
851 switch (Kind) {
852 default:
853 // Just ignore unsupported relaxations
854 return Kind;
855 case R_RISCV_CALL:
856 case R_RISCV_CALL_PLT:
857 return CallRelaxable;
858 }
859 }
860
addRelocations()861 Error addRelocations() override {
862 LLVM_DEBUG(dbgs() << "Processing relocations:\n");
863
864 using Base = ELFLinkGraphBuilder<ELFT>;
865 using Self = ELFLinkGraphBuilder_riscv<ELFT>;
866 for (const auto &RelSect : Base::Sections)
867 if (Error Err = Base::forEachRelaRelocation(RelSect, this,
868 &Self::addSingleRelocation))
869 return Err;
870
871 return Error::success();
872 }
873
addSingleRelocation(const typename ELFT::Rela & Rel,const typename ELFT::Shdr & FixupSect,Block & BlockToFix)874 Error addSingleRelocation(const typename ELFT::Rela &Rel,
875 const typename ELFT::Shdr &FixupSect,
876 Block &BlockToFix) {
877 using Base = ELFLinkGraphBuilder<ELFT>;
878
879 uint32_t Type = Rel.getType(false);
880 int64_t Addend = Rel.r_addend;
881
882 if (Type == ELF::R_RISCV_RELAX) {
883 if (BlockToFix.edges_empty())
884 return make_error<StringError>(
885 "R_RISCV_RELAX without preceding relocation",
886 inconvertibleErrorCode());
887
888 auto &PrevEdge = *std::prev(BlockToFix.edges().end());
889 auto Kind = static_cast<EdgeKind_riscv>(PrevEdge.getKind());
890 PrevEdge.setKind(getRelaxableRelocationKind(Kind));
891 return Error::success();
892 }
893
894 Expected<riscv::EdgeKind_riscv> Kind = getRelocationKind(Type);
895 if (!Kind)
896 return Kind.takeError();
897
898 uint32_t SymbolIndex = Rel.getSymbol(false);
899 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
900 if (!ObjSymbol)
901 return ObjSymbol.takeError();
902
903 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
904 if (!GraphSymbol)
905 return make_error<StringError>(
906 formatv("Could not find symbol at given index, did you add it to "
907 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
908 SymbolIndex, (*ObjSymbol)->st_shndx,
909 Base::GraphSymbols.size()),
910 inconvertibleErrorCode());
911
912 auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
913 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
914 Edge GE(*Kind, Offset, *GraphSymbol, Addend);
915 LLVM_DEBUG({
916 dbgs() << " ";
917 printEdge(dbgs(), BlockToFix, GE, riscv::getEdgeKindName(*Kind));
918 dbgs() << "\n";
919 });
920
921 BlockToFix.addEdge(std::move(GE));
922 return Error::success();
923 }
924
925 public:
ELFLinkGraphBuilder_riscv(StringRef FileName,const object::ELFFile<ELFT> & Obj,Triple TT,SubtargetFeatures Features)926 ELFLinkGraphBuilder_riscv(StringRef FileName,
927 const object::ELFFile<ELFT> &Obj, Triple TT,
928 SubtargetFeatures Features)
929 : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
930 FileName, riscv::getEdgeKindName) {}
931 };
932
933 Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer)934 createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer) {
935 LLVM_DEBUG({
936 dbgs() << "Building jitlink graph for new input "
937 << ObjectBuffer.getBufferIdentifier() << "...\n";
938 });
939
940 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
941 if (!ELFObj)
942 return ELFObj.takeError();
943
944 auto Features = (*ELFObj)->getFeatures();
945 if (!Features)
946 return Features.takeError();
947
948 if ((*ELFObj)->getArch() == Triple::riscv64) {
949 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
950 return ELFLinkGraphBuilder_riscv<object::ELF64LE>(
951 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
952 (*ELFObj)->makeTriple(), std::move(*Features))
953 .buildGraph();
954 } else {
955 assert((*ELFObj)->getArch() == Triple::riscv32 &&
956 "Invalid triple for RISCV ELF object file");
957 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
958 return ELFLinkGraphBuilder_riscv<object::ELF32LE>(
959 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
960 (*ELFObj)->makeTriple(), std::move(*Features))
961 .buildGraph();
962 }
963 }
964
link_ELF_riscv(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)965 void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
966 std::unique_ptr<JITLinkContext> Ctx) {
967 PassConfiguration Config;
968 const Triple &TT = G->getTargetTriple();
969 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
970
971 Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
972 Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
973 ".eh_frame", G->getPointerSize(), Edge::Invalid, Edge::Invalid,
974 Edge::Invalid, Edge::Invalid, NegDelta32));
975 Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
976
977 if (auto MarkLive = Ctx->getMarkLivePass(TT))
978 Config.PrePrunePasses.push_back(std::move(MarkLive));
979 else
980 Config.PrePrunePasses.push_back(markAllSymbolsLive);
981 Config.PostPrunePasses.push_back(
982 PerGraphGOTAndPLTStubsBuilder_ELF_riscv::asPass);
983 Config.PostAllocationPasses.push_back(relax);
984 }
985 if (auto Err = Ctx->modifyPassConfig(*G, Config))
986 return Ctx->notifyFailed(std::move(Err));
987
988 ELFJITLinker_riscv::link(std::move(Ctx), std::move(G), std::move(Config));
989 }
990
createRelaxationPass_ELF_riscv()991 LinkGraphPassFunction createRelaxationPass_ELF_riscv() { return relax; }
992
993 } // namespace jitlink
994 } // namespace llvm
995