[llvm] [BOLT] Prevent .rela.plt reordering (PR #207412)

Ilija Tovilo via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 3 08:23:04 PDT 2026


https://github.com/iluuu1994 created https://github.com/llvm/llvm-project/pull/207412

BOLT reorders .rela.plt entries without also updating the corresponding PLT stub relocation indices. Rather than patching the stubs, prevent reordering the relocations.

Fixes GH-207222

>From 769e1b4694e56f0e717eb793a5dc53bc3c1cdd1f Mon Sep 17 00:00:00 2001
From: Ilija Tovilo <ilija.tovilo at me.com>
Date: Fri, 3 Jul 2026 17:14:32 +0200
Subject: [PATCH] [BOLT] Prevent .rela.plt reordering

BOLT reorders .rela.plt entries without also updating the corresponding
PLT stub relocation indices. Rather than patching the stubs, prevent
reordering the relocations.

Fixes GH-207222
---
 bolt/include/bolt/Rewrite/RewriteInstance.h |  4 +++
 bolt/lib/Rewrite/RewriteInstance.cpp        | 28 ++++++++++++-------
 bolt/test/AArch64/runtime-relocs.test       |  2 +-
 bolt/test/runtime/X86/rela-plt-order.c      | 31 +++++++++++++++++++++
 4 files changed, 54 insertions(+), 11 deletions(-)
 create mode 100644 bolt/test/runtime/X86/rela-plt-order.c

diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h
index 3873d944e01ba..ede8e0d58fa55 100644
--- a/bolt/include/bolt/Rewrite/RewriteInstance.h
+++ b/bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -17,6 +17,7 @@
 #include "bolt/Core/Linker.h"
 #include "bolt/Rewrite/MetadataManager.h"
 #include "bolt/Utils/NameResolver.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ObjectFile.h"
@@ -514,6 +515,9 @@ class RewriteInstance {
   /// True if relocation of specified type came from .rela.plt
   DenseMap<uint64_t, bool> IsJmpRelocation;
 
+  /// Original dynamic relocation order.
+  SmallVector<uint64_t, 0> DynamicRelocationOrder;
+
   /// Index of specified symbol in the dynamic symbol table. NOTE Currently it
   /// is filled and used only with the relocations-related symbols.
   std::unordered_map<const MCSymbol *, uint32_t> SymbolIndex;
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 9e00d48e03853..359074ab0660e 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -2799,6 +2799,7 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
              << " : + 0x" << Twine::utohexstr(Addend) << '\n'
     );
 
+    DynamicRelocationOrder.push_back(Rel.getOffset());
     if (IsJmpRel)
       IsJmpRelocation[RType] = true;
 
@@ -5888,16 +5889,28 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
     Offset += sizeof(*RelA);
   };
 
-  auto writeRelocations = [&](bool PatchRelative) {
-    for (BinarySection &Section : BC->allocatableSections()) {
+  {
+    for (const uint64_t Address : DynamicRelocationOrder) {
+      ErrorOr<BinarySection &> SectionOrError = BC->getSectionForAddress(Address);
+      if (!SectionOrError) {
+        BC->errs()
+          << "Cannot find section for dynamic relocation at 0x"
+          << Twine::utohexstr(Address)
+          << "\n";
+        exit(1);
+      }
+
+      BinarySection &Section = *SectionOrError;
       const uint64_t SectionInputAddress = Section.getAddress();
       uint64_t SectionAddress = Section.getOutputAddress();
       if (!SectionAddress)
         SectionAddress = SectionInputAddress;
 
-      for (const Relocation &Rel : Section.dynamicRelocations()) {
+      const Relocation &Rel = *Section.getDynamicRelocationAt(Address - SectionInputAddress);
+
+      {
         const bool IsRelative = Rel.isRelative();
-        if (PatchRelative != IsRelative || Rel.isRELR())
+        if (Rel.isRELR())
           continue;
 
         if (IsRelative)
@@ -5941,12 +5954,7 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
         writeRela(&NewRelA, Offset);
       }
     }
-  };
-
-  // The dynamic linker expects all R_*_RELATIVE relocations in RELA
-  // to be emitted first.
-  writeRelocations(/* PatchRelative */ true);
-  writeRelocations(/* PatchRelative */ false);
+  }
 
   auto fillNone = [&](uint64_t &Offset, uint64_t EndOffset) {
     if (!Offset)
diff --git a/bolt/test/AArch64/runtime-relocs.test b/bolt/test/AArch64/runtime-relocs.test
index a8347b531c144..daf9a45d125e6 100644
--- a/bolt/test/AArch64/runtime-relocs.test
+++ b/bolt/test/AArch64/runtime-relocs.test
@@ -10,8 +10,8 @@ RUN: llvm-bolt %t.exe -o %t.bolt.exe --use-old-text=0 --lite=0
 RUN: llvm-readelf -rW %t.bolt.so | FileCheck %s -check-prefix=CHECKLIB
 
 CHECKLIB: {{.*}} R_AARCH64_GLOB_DAT     {{.*}} a + 0
-CHECKLIB: {{.*}} R_AARCH64_TLSDESC      {{.*}} t1 + 0
 CHECKLIB: {{.*}} R_AARCH64_ABS64        {{.*}} a + 0
+CHECKLIB: {{.*}} R_AARCH64_TLSDESC      {{.*}} t1 + 0
 
 // Check relocations in executable:
 
diff --git a/bolt/test/runtime/X86/rela-plt-order.c b/bolt/test/runtime/X86/rela-plt-order.c
new file mode 100644
index 0000000000000..f5acaf00cdf3c
--- /dev/null
+++ b/bolt/test/runtime/X86/rela-plt-order.c
@@ -0,0 +1,31 @@
+// REQUIRES: x86_64-linux, gnu_ld
+//
+// RUN: split-file %s %t
+// RUN: %clang %cflags -fPIC -shared -o %t/libexample.so \
+// RUN:   %t/example.c
+// RUN: %clang %cflags -fno-pie -no-pie -fuse-ld=bfd \
+// RUN:   -Wl,--emit-relocs -Wl,-rpath,\$ORIGIN -o %t/main %t/main.c \
+// RUN:   -L%t -lexample
+// RUN: llvm-bolt %t/main -o %t/main.bolt
+// RUN: llvm-readelf --dyn-relocations %t/main.bolt | FileCheck %s
+// RUN: %t/main.bolt
+
+// CHECK-LABEL: 'PLT' relocation section
+// CHECK:      R_X86_64_JUMP_SLOT{{.*}}long_name
+// CHECK-NEXT: R_X86_64_IRELATIVE
+
+//--- main.c
+extern int long_name(void);
+
+__attribute__((target_clones("default,avx2"))) int foo(int x) { return x + 1; }
+
+int main(void) {
+  if (foo(1) != 2)
+    return 1;
+  if (long_name() != 0)
+    return 1;
+  return 0;
+}
+
+//--- example.c
+int long_name(void) { return 0; }



More information about the llvm-commits mailing list