[llvm] [BOLT] Remove original relocs when moving JTs in relocation mode (PR #91656)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 9 14:10:33 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-bolt
Author: Amir Ayupov (aaupov)
<details>
<summary>Changes</summary>
Erase original jump table relocations in relocation mode with -jump-tables=move
(or higher). Otherwise we end up updating the original data relocations which
may no longer reference existing labels, as demonstrated by the test case.
Accepted in https://reviews.llvm.org/D147150
Test Plan: added normalize-jump-table-target.s
---
Full diff: https://github.com/llvm/llvm-project/pull/91656.diff
4 Files Affected:
- (modified) bolt/include/bolt/Core/JumpTable.h (+1-1)
- (modified) bolt/lib/Core/BinaryEmitter.cpp (+3-1)
- (modified) bolt/lib/Core/JumpTable.cpp (+3-1)
- (added) bolt/test/X86/normalize-jump-table-target.s (+44)
``````````diff
diff --git a/bolt/include/bolt/Core/JumpTable.h b/bolt/include/bolt/Core/JumpTable.h
index 52b9ccee1f7e1..dd55a93784e64 100644
--- a/bolt/include/bolt/Core/JumpTable.h
+++ b/bolt/include/bolt/Core/JumpTable.h
@@ -120,7 +120,7 @@ class JumpTable : public BinaryData {
MCSymbol *NewDest);
/// Update jump table at its original location.
- void updateOriginal();
+ void updateOriginal(bool Zero);
/// Print for debugging purposes.
void print(raw_ostream &OS) const override;
diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 6f86ddc774544..3fb56bf15aaa3 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -777,7 +777,7 @@ void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) {
if (opts::PrintJumpTables)
JT.print(BC.outs());
if (opts::JumpTables == JTS_BASIC && BC.HasRelocations) {
- JT.updateOriginal();
+ JT.updateOriginal(/*Zero=*/false);
} else {
MCSection *HotSection, *ColdSection;
if (opts::JumpTables == JTS_BASIC) {
@@ -802,6 +802,8 @@ void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) {
}
}
emitJumpTable(JT, HotSection, ColdSection);
+ if (opts::JumpTables > JTS_BASIC && BC.HasRelocations)
+ JT.updateOriginal(/*Zero=*/true);
}
}
}
diff --git a/bolt/lib/Core/JumpTable.cpp b/bolt/lib/Core/JumpTable.cpp
index 65e1032c579b5..86a6d3d11f2ea 100644
--- a/bolt/lib/Core/JumpTable.cpp
+++ b/bolt/lib/Core/JumpTable.cpp
@@ -79,7 +79,7 @@ bool bolt::JumpTable::replaceDestination(uint64_t JTAddress,
return Patched;
}
-void bolt::JumpTable::updateOriginal() {
+void bolt::JumpTable::updateOriginal(bool Zero) {
BinaryContext &BC = getSection().getBinaryContext();
const uint64_t BaseOffset = getAddress() - getSection().getAddress();
uint64_t EntryOffset = BaseOffset;
@@ -92,6 +92,8 @@ void bolt::JumpTable::updateOriginal() {
// to the original jump table.
if (BC.HasRelocations)
getOutputSection().removeRelocationAt(EntryOffset);
+ if (Zero)
+ Entry = BC.registerNameAtAddress("Zero", 0, 0, 0);
getOutputSection().addRelocation(EntryOffset, Entry, RelType, RelAddend);
EntryOffset += EntrySize;
}
diff --git a/bolt/test/X86/normalize-jump-table-target.s b/bolt/test/X86/normalize-jump-table-target.s
new file mode 100644
index 0000000000000..a22d3df0ec1a2
--- /dev/null
+++ b/bolt/test/X86/normalize-jump-table-target.s
@@ -0,0 +1,44 @@
+# This test reproduces an issue with removing a basic block which is referenced
+# from rodata section ("externally referenced offset"/jump table target).
+# If the block is removed (by remove-nops + NormalizeCFG), and BOLT updates the
+# original jump table (with jump-tables=move), this causes an emission error
+# (undefined temporary symbol).
+
+# REQUIRES: system-linux,bolt-runtime
+
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
+# RUN: %clang -no-pie %t.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.out --instrument --instrumentation-file=%t.tmp \
+# RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-BOLT
+
+# CHECK-BOLT-NOT: undefined temporary symbol
+
+# Grab the jump table address in original text section (.bolt.org.text)
+# RUN: llvm-objdump -dj.bolt.org.text %t.out > %t.log
+# Inspect jump table entries, should be two zero values
+# RUN: llvm-objdump -sj.rodata %t.out >> %t.log
+# RUN: FileCheck %s --input-file %t.log --check-prefix=CHECK-OBJDUMP
+
+# CHECK-OBJDUMP: jmpq *0x[[#%x,JTADDR:]](,%rax,8)
+# CHECK-OBJDUMP: [[#JTADDR]] 00000000 00000000 00000000 00000000
+
+ .globl main
+main:
+ .cfi_startproc
+ jmp main
+ jmpq *JT(,%rax,8)
+a:
+ shlq %rax
+.Ltmp:
+ nop
+c:
+ ret
+ .cfi_endproc
+
+.rodata
+# pad to ensure the jump table starts at 16-byte aligned address so it can be
+# matched in objdump output
+.p2align 4
+JT:
+ .quad .Ltmp
+ .quad a
``````````
</details>
https://github.com/llvm/llvm-project/pull/91656
More information about the llvm-commits
mailing list