Skip to content

Conversation

zengdage
Copy link
Contributor

This patch is try to fix the issue #153775 . Now the LLVM JITLink don't support R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128 relocation type, so the bolt can't instrument the elf binary which has exception handling table.

@llvmbot
Copy link
Member

llvmbot commented Aug 15, 2025

@llvm/pr-subscribers-lld
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-llvm-support

@llvm/pr-subscribers-backend-risc-v

Author: Zhijin Zeng (zengdage)

Changes

This patch is try to fix the issue #153775 . Now the LLVM JITLink don't support R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128 relocation type, so the bolt can't instrument the elf binary which has exception handling table.


Full diff: https://github.com/llvm/llvm-project/pull/153778.diff

4 Files Affected:

  • (modified) llvm/include/llvm/ExecutionEngine/JITLink/riscv.h (+12)
  • (modified) llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp (+34-2)
  • (modified) llvm/lib/ExecutionEngine/JITLink/riscv.cpp (+4)
  • (added) llvm/test/ExecutionEngine/JITLink/RISCV/ELF_reloc_uleb128.s (+21)
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/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
index 71a0f14368ac6..8830d023a7a77 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 gatherRISCVPair(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 gatherRISCVPair(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,18 @@ 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_SET_ULEB128 or");
+
+    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 +483,18 @@ 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();
+      encodeULEB128(Value, (reinterpret_cast<uint8_t *>(FixupPtr)));
+      break;
+    }
     }
     return Error::success();
   }
@@ -843,6 +871,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..2b9f6f7d6bb37
--- /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","",@progbits
+.type foo,@function
+foo:
+  nop
+  nop
+  .reloc ., R_RISCV_SET_ULEB128, foo+129
+  .reloc ., R_RISCV_SUB_ULEB128, foo+1
+  .word 0
+  .size foo, 8

Copy link

github-actions bot commented Aug 15, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@zengdage zengdage force-pushed the fix-jitlink-uleb128 branch 2 times, most recently from 9f71ff5 to 5e24de8 Compare August 15, 2025 10:54
@zqb-all zqb-all requested review from MaskRay, mtvec and hahnjo August 18, 2025 09:00
Copy link
Member

@hahnjo hahnjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM, but we may need a check that there actually was sufficient space

@zengdage zengdage force-pushed the fix-jitlink-uleb128 branch from e164d5f to ec11fe5 Compare August 20, 2025 10:43
@zengdage zengdage requested a review from hahnjo August 22, 2025 01:34
@hahnjo hahnjo requested review from dwblaikie and rui314 August 23, 2025 20:35
Copy link
Member

@hahnjo hahnjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JITLink code LGTM

@zengdage
Copy link
Contributor Author

zengdage commented Sep 8, 2025

ping

@dwblaikie dwblaikie removed their request for review September 8, 2025 17:12
@zqb-all
Copy link
Contributor

zqb-all commented Sep 9, 2025

LGTM

@zqb-all zqb-all merged commit 7a58e77 into llvm:main Sep 9, 2025
9 checks passed
@maksfb
Copy link
Contributor

maksfb commented Sep 10, 2025

@zengdage Nice! Thanks for the fix.

@zengdage zengdage deleted the fix-jitlink-uleb128 branch September 11, 2025 02:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants