[llvm] [BOLT] Skip out-of-range pending relocations (PR #116964)

Paschalis Mpeis via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 20 04:54:51 PST 2024


https://github.com/paschalis-mpeis created https://github.com/llvm/llvm-project/pull/116964

When there are not enough bits to encode a pending relocation value, then skip it instead of asserting.

---

> [!NOTE]  
> This is a **minimal change** to get some quick feedback.
> It suggests a way forward that avoids the assertion without fully disabling the optimization (see (S2) in Issue [#116817](https://github.com/llvm/llvm-project/issues/116817)).
> If this is in the right direction, more code will be added, including tests.

>From e9b0066e7e8f86386cf8eb05002ddad6568d9b78 Mon Sep 17 00:00:00 2001
From: Paschalis Mpeis <Paschalis.Mpeis at arm.com>
Date: Tue, 19 Nov 2024 15:53:45 +0000
Subject: [PATCH] [BOLT] Skip out-of-range pending relocations

When there are not enough bits to encode a pending relocation value,
then skip it instead of asserting.
---
 bolt/include/bolt/Core/Relocation.h |  3 +++
 bolt/lib/Core/BinarySection.cpp     | 10 ++++++++++
 bolt/lib/Core/Relocation.cpp        | 16 ++++++++++++++++
 3 files changed, 29 insertions(+)

diff --git a/bolt/include/bolt/Core/Relocation.h b/bolt/include/bolt/Core/Relocation.h
index 933f62a31f8fd7..8846369612ae31 100644
--- a/bolt/include/bolt/Core/Relocation.h
+++ b/bolt/include/bolt/Core/Relocation.h
@@ -67,6 +67,9 @@ struct Relocation {
   // Adjust value depending on relocation type (make it PC relative or not)
   static uint64_t encodeValue(uint64_t Type, uint64_t Value, uint64_t PC);
 
+  // Return true if there are enough bits to encode the relocation value.
+  static bool canEncodeValue(uint64_t Type, uint64_t Value, uint64_t PC);
+
   /// Extract current relocated value from binary contents. This is used for
   /// RISC architectures where values are encoded in specific bits depending
   /// on the relocation value. For X86, we limit to sign extending the value
diff --git a/bolt/lib/Core/BinarySection.cpp b/bolt/lib/Core/BinarySection.cpp
index 9ad49ca1b3a038..1eb237fbb05acb 100644
--- a/bolt/lib/Core/BinarySection.cpp
+++ b/bolt/lib/Core/BinarySection.cpp
@@ -165,11 +165,17 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
     OS.pwrite(Patch.Bytes.data(), Patch.Bytes.size(),
               SectionFileOffset + Patch.Offset);
 
+  uint64_t SkippedPendingRelocations = 0;
   for (Relocation &Reloc : PendingRelocations) {
     uint64_t Value = Reloc.Addend;
     if (Reloc.Symbol)
       Value += Resolver(Reloc.Symbol);
 
+    if (!Relocation::canEncodeValue(Reloc.Type, Value,
+                                    SectionAddress + Reloc.Offset)) {
+      ++SkippedPendingRelocations;
+      continue;
+    }
     Value = Relocation::encodeValue(Reloc.Type, Value,
                                     SectionAddress + Reloc.Offset);
 
@@ -188,6 +194,10 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
   }
 
   clearList(PendingRelocations);
+
+  if (SkippedPendingRelocations > 0)
+    outs() << "BOLT-INFO: Skipped " << SkippedPendingRelocations
+           << " pending relocations as they were out of range\n";
 }
 
 BinarySection::~BinarySection() { updateContents(nullptr, 0); }
diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp
index 4e888a5b147aca..a378961981ee37 100644
--- a/bolt/lib/Core/Relocation.cpp
+++ b/bolt/lib/Core/Relocation.cpp
@@ -361,6 +361,16 @@ static uint64_t encodeValueX86(uint64_t Type, uint64_t Value, uint64_t PC) {
   return Value;
 }
 
+static bool canEncodeValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
+  // TODO: support more cases.
+  switch (Type) {
+  default:
+    llvm_unreachable("unsupported relocation");
+  case ELF::R_AARCH64_CALL26:
+    return isInt<28>(Value - PC);
+  }
+}
+
 static uint64_t encodeValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
   switch (Type) {
   default:
@@ -838,6 +848,12 @@ uint64_t Relocation::encodeValue(uint64_t Type, uint64_t Value, uint64_t PC) {
   }
 }
 
+bool Relocation::canEncodeValue(uint64_t Type, uint64_t Value, uint64_t PC) {
+  // TODO: support more architectures.
+  assert(Arch == Triple::aarch64);
+  return canEncodeValueAArch64(Type, Value, PC);
+}
+
 uint64_t Relocation::extractValue(uint64_t Type, uint64_t Contents,
                                   uint64_t PC) {
   switch (Arch) {



More information about the llvm-commits mailing list