Skip to content

Commit a18482a

Browse files
treapstertru
authored andcommitted
[BOLT][AArch64] Replace NOP with adrp in AdrRelaxationPass to preserve relative offsets.
Avoid replacing one adr instruction with two adrp+add by utilizing linker-provided nops when they are present. By doing so we preserve relative offsets of next instructions in a function which reduces chances to break undetected jump tables. This commit makes release-mode lld-linked clang, lld and etc work after BOLT. Reviewed By: rafauler, yota9 Differential Revision: https://reviews.llvm.org/D143887
1 parent c2ef325 commit a18482a

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

bolt/lib/Passes/ADRRelaxationPass.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include "bolt/Passes/ADRRelaxationPass.h"
1414
#include "bolt/Core/ParallelUtilities.h"
15+
#include "bolt/Utils/CommandLineOpts.h"
16+
#include <iterator>
1517

1618
using namespace llvm;
1719

@@ -54,6 +56,20 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
5456
int64_t Addend = BC.MIB->getTargetAddend(Inst);
5557
InstructionListType Addr =
5658
BC.MIB->materializeAddress(Symbol, BC.Ctx.get(), Reg, Addend);
59+
60+
if (It != BB.begin() && BC.MIB->isNoop(*std::prev(It))) {
61+
It = BB.eraseInstruction(std::prev(It));
62+
} else if (opts::StrictMode && !BF.isSimple()) {
63+
// If the function is not simple, it may contain a jump table undetected
64+
// by us. This jump table may use an offset from the branch instruction
65+
// to land in the desired place. If we add new instructions, we
66+
// invalidate this offset, so we have to rely on linker-inserted NOP to
67+
// replace it with ADRP, and abort if it is not present.
68+
errs() << formatv("BOLT-ERROR: Cannot relax adr in non-simple function "
69+
"{0}. Can't proceed in current mode.\n",
70+
BF.getOneName());
71+
exit(1);
72+
}
5773
It = BB.replaceInstruction(It, Addr);
5874
}
5975
}

bolt/test/runtime/AArch64/adrrelaxationpass.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# The second and third ADR instructions are non-local to functions
22
# and must be replaced with ADRP + ADD by BOLT
3+
# Also since main is non-simple, we can't change it's length so we have to
4+
# replace NOP with adrp, and if there is no nop before adr in non-simple
5+
# function, we can't guarantee we didn't break possible jump tables, so we
6+
# fail in strict mode
37

48
# REQUIRES: system-linux
59

@@ -9,6 +13,8 @@
913
# RUN: llvm-bolt %t.exe -o %t.bolt --adr-relaxation=true
1014
# RUN: llvm-objdump --no-print-imm-hex -d --disassemble-symbols=main %t.bolt | FileCheck %s
1115
# RUN: %t.bolt
16+
# RUN: not llvm-bolt %t.exe -o %t.bolt --adr-relaxation=true --strict \
17+
# RUN: 2>&1 | FileCheck %s --check-prefix CHECK-ERROR
1218

1319
.data
1420
.align 8
@@ -31,6 +37,7 @@ test:
3137
.type main, %function
3238
main:
3339
adr x0, .CI
40+
nop
3441
adr x1, test
3542
adr x2, Gvar2
3643
adr x3, br
@@ -47,3 +54,4 @@ br:
4754
# CHECK-NEXT: adrp x2, 0x{{[1-8a-f][0-9a-f]*}}
4855
# CHECK-NEXT: add x2, x2, #{{[1-8a-f][0-9a-f]*}}
4956
# CHECK-NEXT: adr x3, #{{[0-9][0-9]*}}
57+
# CHECK-ERROR: BOLT-ERROR: Cannot relax adr in non-simple function main

0 commit comments

Comments
 (0)