Skip to content

Commit 7a58e77

Browse files
authored
[JITLink][RISC-V] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 (#153778)
Support bolt instrument the elf binary which has exception handling table. Fixes #153775
1 parent 8aa9e1e commit 7a58e77

File tree

7 files changed

+87
-11
lines changed

7 files changed

+87
-11
lines changed

lld/ELF/InputSection.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/Support/Compiler.h"
2020
#include "llvm/Support/Compression.h"
2121
#include "llvm/Support/Endian.h"
22+
#include "llvm/Support/LEB128.h"
2223
#include "llvm/Support/xxhash.h"
2324
#include <algorithm>
2425
#include <optional>

lld/ELF/Target.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,6 @@ inline void write64(Ctx &ctx, void *p, uint64_t v) {
326326
llvm::support::endian::write64(p, v, ctx.arg.endianness);
327327
}
328328

329-
// Overwrite a ULEB128 value and keep the original length.
330-
inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
331-
while (*bufLoc & 0x80) {
332-
*bufLoc++ = 0x80 | (val & 0x7f);
333-
val >>= 7;
334-
}
335-
*bufLoc = val;
336-
return val;
337-
}
338329
} // namespace elf
339330
} // namespace lld
340331

llvm/include/llvm/ExecutionEngine/JITLink/riscv.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,18 @@ enum EdgeKind_riscv : Edge::Kind {
221221
/// Fixup expression:
222222
/// Fixup <- Fixup - Target + Addend
223223
NegDelta32,
224+
225+
/// Set ULEB128-encoded value
226+
///
227+
/// Fixup expression:
228+
/// Fixup <- Target + Addend
229+
R_RISCV_SET_ULEB128,
230+
231+
/// Subtract from ULEB128-encoded value
232+
///
233+
/// Fixup expression:
234+
/// Fixup <- V - Target - Addend
235+
R_RISCV_SUB_ULEB128,
224236
};
225237

226238
/// Returns a string name for the given riscv edge. For debugging purposes

llvm/include/llvm/Support/LEB128.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,16 @@ inline uint64_t decodeULEB128AndIncUnsafe(const uint8_t *&p) {
221221
return decodeULEB128AndInc(p, nullptr);
222222
}
223223

224+
/// Overwrite a ULEB128 value and keep the original length.
225+
inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
226+
while (*bufLoc & 0x80) {
227+
*bufLoc++ = 0x80 | (val & 0x7f);
228+
val >>= 7;
229+
}
230+
*bufLoc = val;
231+
return val;
232+
}
233+
224234
enum class LEB128Sign { Unsigned, Signed };
225235

226236
template <LEB128Sign Sign, typename T, typename U = char,

llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,18 +154,22 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
154154
std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
155155
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
156156
JITLinkerBase::getPassConfig().PostAllocationPasses.push_back(
157-
[this](LinkGraph &G) { return gatherRISCVPCRelHi20(G); });
157+
[this](LinkGraph &G) { return gatherRISCVPairs(G); });
158158
}
159159

160160
private:
161161
DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
162162
RelHi20;
163+
DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
164+
SetULEB128;
163165

164-
Error gatherRISCVPCRelHi20(LinkGraph &G) {
166+
Error gatherRISCVPairs(LinkGraph &G) {
165167
for (Block *B : G.blocks())
166168
for (Edge &E : B->edges())
167169
if (E.getKind() == R_RISCV_PCREL_HI20)
168170
RelHi20[{B, E.getOffset()}] = &E;
171+
else if (E.getKind() == R_RISCV_SET_ULEB128)
172+
SetULEB128[{B, E.getOffset()}] = &E;
169173

170174
return Error::success();
171175
}
@@ -189,6 +193,20 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
189193
"for LO12 PCREL relocation type");
190194
}
191195

196+
Expected<const Edge &> getRISCVSetULEB128(const Block &B,
197+
const Edge &E) const {
198+
using namespace riscv;
199+
assert(E.getKind() == R_RISCV_SUB_ULEB128 &&
200+
"Can only have pair relocation for R_RISCV_SUB_ULEB128");
201+
202+
auto It = SetULEB128.find({&B, E.getOffset()});
203+
if (It != SetULEB128.end())
204+
return *It->second;
205+
206+
return make_error<JITLinkError>(
207+
"No RISCV_SET_ULEB128 relocation type be found");
208+
}
209+
192210
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
193211
using namespace riscv;
194212
using namespace llvm::support;
@@ -467,6 +485,21 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
467485
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
468486
break;
469487
}
488+
case R_RISCV_SET_ULEB128:
489+
break;
490+
case R_RISCV_SUB_ULEB128: {
491+
auto SetULEB128 = getRISCVSetULEB128(B, E);
492+
if (!SetULEB128)
493+
return SetULEB128.takeError();
494+
uint64_t Value = SetULEB128->getTarget().getAddress() +
495+
SetULEB128->getAddend() - E.getTarget().getAddress() -
496+
E.getAddend();
497+
if (overwriteULEB128(reinterpret_cast<uint8_t *>(FixupPtr), Value) >=
498+
0x80)
499+
return make_error<StringError>("ULEB128 value exceeds available space",
500+
inconvertibleErrorCode());
501+
break;
502+
}
470503
}
471504
return Error::success();
472505
}
@@ -843,6 +876,10 @@ class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
843876
return EdgeKind_riscv::R_RISCV_32_PCREL;
844877
case ELF::R_RISCV_ALIGN:
845878
return EdgeKind_riscv::AlignRelaxable;
879+
case ELF::R_RISCV_SET_ULEB128:
880+
return EdgeKind_riscv::R_RISCV_SET_ULEB128;
881+
case ELF::R_RISCV_SUB_ULEB128:
882+
return EdgeKind_riscv::R_RISCV_SUB_ULEB128;
846883
}
847884

848885
return make_error<JITLinkError>(

llvm/lib/ExecutionEngine/JITLink/riscv.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ const char *getEdgeKindName(Edge::Kind K) {
8484
return "AlignRelaxable";
8585
case NegDelta32:
8686
return "NegDelta32";
87+
case R_RISCV_SET_ULEB128:
88+
return "R_RISCV_SET_ULEB128";
89+
case R_RISCV_SUB_ULEB128:
90+
return "R_RISCV_SUB_ULEB128";
8791
}
8892
return getGenericEdgeKindName(K);
8993
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# RUN: rm -rf %t && mkdir -p %t
2+
# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t/riscv64_reloc_uleb128.o %s
3+
# RUN: llvm-mc -triple=riscv32 -filetype=obj -o %t/riscv32_reloc_uleb128.o %s
4+
# RUN: llvm-jitlink -noexec -check %s %t/riscv64_reloc_uleb128.o
5+
# RUN: llvm-jitlink -noexec -check %s %t/riscv32_reloc_uleb128.o
6+
7+
# jitlink-check: *{4}(foo+8) = 0x180
8+
9+
.global main
10+
main:
11+
lw a0, foo
12+
13+
.section ".text","",@progbits
14+
.type foo,@function
15+
foo:
16+
nop
17+
nop
18+
.reloc ., R_RISCV_SET_ULEB128, foo+129
19+
.reloc ., R_RISCV_SUB_ULEB128, foo+1
20+
.uleb128 0x80
21+
.size foo, 8

0 commit comments

Comments
 (0)