[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