[lld] 7a58e77 - [JITLink][RISC-V] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 (#153778)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 9 02:51:34 PDT 2025
Author: Zhijin Zeng
Date: 2025-09-09T17:51:30+08:00
New Revision: 7a58e771436bf978fa7debb98296f797cb4e8141
URL: https://github.com/llvm/llvm-project/commit/7a58e771436bf978fa7debb98296f797cb4e8141
DIFF: https://github.com/llvm/llvm-project/commit/7a58e771436bf978fa7debb98296f797cb4e8141.diff
LOG: [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
Added:
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_reloc_uleb128.s
Modified:
lld/ELF/InputSection.cpp
lld/ELF/Target.h
llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
llvm/include/llvm/Support/LEB128.h
llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
llvm/lib/ExecutionEngine/JITLink/riscv.cpp
Removed:
################################################################################
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 784ff7cc79912..ea6bcc5bb272b 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <optional>
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index e121fa1183e9e..bb8c24f052aa2 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -326,15 +326,6 @@ inline void write64(Ctx &ctx, void *p, uint64_t v) {
llvm::support::endian::write64(p, v, ctx.arg.endianness);
}
-// Overwrite a ULEB128 value and keep the original length.
-inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
- while (*bufLoc & 0x80) {
- *bufLoc++ = 0x80 | (val & 0x7f);
- val >>= 7;
- }
- *bufLoc = val;
- return val;
-}
} // namespace elf
} // namespace lld
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
index fcc99787c8e12..9786f5cde3615 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
@@ -221,6 +221,18 @@ enum EdgeKind_riscv : Edge::Kind {
/// Fixup expression:
/// Fixup <- Fixup - Target + Addend
NegDelta32,
+
+ /// Set ULEB128-encoded value
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend
+ R_RISCV_SET_ULEB128,
+
+ /// Subtract from ULEB128-encoded value
+ ///
+ /// Fixup expression:
+ /// Fixup <- V - Target - Addend
+ R_RISCV_SUB_ULEB128,
};
/// Returns a string name for the given riscv edge. For debugging purposes
diff --git a/llvm/include/llvm/Support/LEB128.h b/llvm/include/llvm/Support/LEB128.h
index 6102c1dc1b952..898b4ea1f19ab 100644
--- a/llvm/include/llvm/Support/LEB128.h
+++ b/llvm/include/llvm/Support/LEB128.h
@@ -221,6 +221,16 @@ inline uint64_t decodeULEB128AndIncUnsafe(const uint8_t *&p) {
return decodeULEB128AndInc(p, nullptr);
}
+/// Overwrite a ULEB128 value and keep the original length.
+inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
+ while (*bufLoc & 0x80) {
+ *bufLoc++ = 0x80 | (val & 0x7f);
+ val >>= 7;
+ }
+ *bufLoc = val;
+ return val;
+}
+
enum class LEB128Sign { Unsigned, Signed };
template <LEB128Sign Sign, typename T, typename U = char,
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
index 71a0f14368ac6..0dc97104610bb 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
@@ -154,18 +154,22 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
JITLinkerBase::getPassConfig().PostAllocationPasses.push_back(
- [this](LinkGraph &G) { return gatherRISCVPCRelHi20(G); });
+ [this](LinkGraph &G) { return gatherRISCVPairs(G); });
}
private:
DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
RelHi20;
+ DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
+ SetULEB128;
- Error gatherRISCVPCRelHi20(LinkGraph &G) {
+ Error gatherRISCVPairs(LinkGraph &G) {
for (Block *B : G.blocks())
for (Edge &E : B->edges())
if (E.getKind() == R_RISCV_PCREL_HI20)
RelHi20[{B, E.getOffset()}] = &E;
+ else if (E.getKind() == R_RISCV_SET_ULEB128)
+ SetULEB128[{B, E.getOffset()}] = &E;
return Error::success();
}
@@ -189,6 +193,20 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
"for LO12 PCREL relocation type");
}
+ Expected<const Edge &> getRISCVSetULEB128(const Block &B,
+ const Edge &E) const {
+ using namespace riscv;
+ assert(E.getKind() == R_RISCV_SUB_ULEB128 &&
+ "Can only have pair relocation for R_RISCV_SUB_ULEB128");
+
+ auto It = SetULEB128.find({&B, E.getOffset()});
+ if (It != SetULEB128.end())
+ return *It->second;
+
+ return make_error<JITLinkError>(
+ "No RISCV_SET_ULEB128 relocation type be found");
+ }
+
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
using namespace riscv;
using namespace llvm::support;
@@ -467,6 +485,21 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
+ case R_RISCV_SET_ULEB128:
+ break;
+ case R_RISCV_SUB_ULEB128: {
+ auto SetULEB128 = getRISCVSetULEB128(B, E);
+ if (!SetULEB128)
+ return SetULEB128.takeError();
+ uint64_t Value = SetULEB128->getTarget().getAddress() +
+ SetULEB128->getAddend() - E.getTarget().getAddress() -
+ E.getAddend();
+ if (overwriteULEB128(reinterpret_cast<uint8_t *>(FixupPtr), Value) >=
+ 0x80)
+ return make_error<StringError>("ULEB128 value exceeds available space",
+ inconvertibleErrorCode());
+ break;
+ }
}
return Error::success();
}
@@ -843,6 +876,10 @@ class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
return EdgeKind_riscv::R_RISCV_32_PCREL;
case ELF::R_RISCV_ALIGN:
return EdgeKind_riscv::AlignRelaxable;
+ case ELF::R_RISCV_SET_ULEB128:
+ return EdgeKind_riscv::R_RISCV_SET_ULEB128;
+ case ELF::R_RISCV_SUB_ULEB128:
+ return EdgeKind_riscv::R_RISCV_SUB_ULEB128;
}
return make_error<JITLinkError>(
diff --git a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp
index a4e4daef97fb5..9e9f4433a9fc2 100644
--- a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp
@@ -84,6 +84,10 @@ const char *getEdgeKindName(Edge::Kind K) {
return "AlignRelaxable";
case NegDelta32:
return "NegDelta32";
+ case R_RISCV_SET_ULEB128:
+ return "R_RISCV_SET_ULEB128";
+ case R_RISCV_SUB_ULEB128:
+ return "R_RISCV_SUB_ULEB128";
}
return getGenericEdgeKindName(K);
}
diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_reloc_uleb128.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_reloc_uleb128.s
new file mode 100644
index 0000000000000..b6b778648d1f5
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_reloc_uleb128.s
@@ -0,0 +1,21 @@
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t/riscv64_reloc_uleb128.o %s
+# RUN: llvm-mc -triple=riscv32 -filetype=obj -o %t/riscv32_reloc_uleb128.o %s
+# RUN: llvm-jitlink -noexec -check %s %t/riscv64_reloc_uleb128.o
+# RUN: llvm-jitlink -noexec -check %s %t/riscv32_reloc_uleb128.o
+
+# jitlink-check: *{4}(foo+8) = 0x180
+
+.global main
+main:
+ lw a0, foo
+
+.section ".text","", at progbits
+.type foo, at function
+foo:
+ nop
+ nop
+ .reloc ., R_RISCV_SET_ULEB128, foo+129
+ .reloc ., R_RISCV_SUB_ULEB128, foo+1
+ .uleb128 0x80
+ .size foo, 8
More information about the llvm-commits
mailing list