Skip to content

Commit 3bba268

Browse files
author
Ash Dobrescu
authored
[BOLT] Support computed goto and allow map addrs inside functions (#120267)
Create entry points for addresses referenced by dynamic relocations and allow getNewFunctionOrDataAddress to map addrs inside functions. By adding addresses referenced by dynamic relocations as entry points. This patch fixes an issue where bolt fails on code using computing goto's. This also fixes a mapping issue with the bugfix from this PR: #117766.
1 parent 2b8f887 commit 3bba268

File tree

6 files changed

+114
-20
lines changed

6 files changed

+114
-20
lines changed

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2455,6 +2455,30 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
24552455
if (Symbol)
24562456
SymbolIndex[Symbol] = getRelocationSymbol(InputFile, Rel);
24572457

2458+
const uint64_t ReferencedAddress = SymbolAddress + Addend;
2459+
BinaryFunction *Func =
2460+
BC->getBinaryFunctionContainingAddress(ReferencedAddress);
2461+
2462+
if (Relocation::isRelative(RType) && SymbolAddress == 0) {
2463+
if (Func) {
2464+
if (!Func->isInConstantIsland(ReferencedAddress)) {
2465+
if (const uint64_t ReferenceOffset =
2466+
ReferencedAddress - Func->getAddress()) {
2467+
Func->addEntryPointAtOffset(ReferenceOffset);
2468+
}
2469+
} else {
2470+
BC->errs() << "BOLT-ERROR: referenced address at 0x"
2471+
<< Twine::utohexstr(ReferencedAddress)
2472+
<< " is in constant island of function " << *Func << "\n";
2473+
exit(1);
2474+
}
2475+
}
2476+
} else if (Relocation::isRelative(RType) && SymbolAddress != 0) {
2477+
BC->errs() << "BOLT-ERROR: symbol address non zero for RELATIVE "
2478+
"relocation type\n";
2479+
exit(1);
2480+
}
2481+
24582482
BC->addDynamicRelocation(Rel.getOffset(), Symbol, RType, Addend);
24592483
}
24602484
}
@@ -5696,7 +5720,7 @@ uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
56965720
for (const BinaryBasicBlock &BB : *BF)
56975721
if (BB.isEntryPoint() &&
56985722
(BF->getAddress() + BB.getOffset()) == OldAddress)
5699-
return BF->getOutputAddress() + BB.getOffset();
5723+
return BB.getOutputStartAddress();
57005724
}
57015725
BC->errs() << "BOLT-ERROR: unable to get new address corresponding to "
57025726
"input address 0x"

bolt/test/AArch64/computed-goto.s

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// This test checks that BOLT creates entry points for addresses
2+
// referenced by dynamic relocations.
3+
// The test also checks that BOLT can map addresses inside functions.
4+
5+
// Checks for error and entry points.
6+
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
7+
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
8+
# RUN: llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s
9+
# RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg | FileCheck --check-prefix=CHECK-ENTRIES %s
10+
11+
// Checks for dynamic relocations.
12+
# RUN: llvm-readelf -dr %t.bolt > %t.out.txt
13+
# RUN: llvm-objdump -j .rela.dyn -d %t.bolt >> %t.out.txt
14+
# RUN: FileCheck --check-prefix=CHECK-RELOCS %s --input-file=%t.out.txt
15+
16+
// Before bolt could handle mapping addresses within moved functions, it
17+
// would bail out with an error of the form:
18+
// BOLT-ERROR: unable to get new address corresponding to input address 0x10390 in function main. Consider adding this function to --skip-funcs=...
19+
// These addresses arise if computed GOTO is in use.
20+
// Check that bolt does not emit any error.
21+
# CHECK-NOT: BOLT-ERROR
22+
23+
// Check that there are dynamic relocations.
24+
# CHECK-RELOCS: Dynamic section at offset {{.*}} contains {{.*}} entries:
25+
# CHECK-RELOCS: Relocation section '.rela.dyn' at offset {{.*}} contains {{.*}} entries
26+
27+
// Check that dynamic relocations were updated
28+
# CHECK-RELOCS: [[#%x,OFF:]] [[#%x,INFO_DYN:]] R_AARCH64_RELATIVE [[#%x,ADDR:]]
29+
# CHECK-RELOCS-NEXT: [[#OFF + 8]] {{0*}}[[#INFO_DYN]] R_AARCH64_RELATIVE [[#ADDR + 8]]
30+
# CHECK-RELOCS: [[#ADDR]] <unknown>
31+
# CHECK-RELOCS: [[#ADDR + 8]] <unknown>
32+
33+
// Check that BOLT registers extra entry points for dynamic relocations.
34+
# CHECK-ENTRIES: Binary Function "main" after building cfg {
35+
# CHECK-ENTRIES: IsMultiEntry: 1
36+
# CHECK-ENTRIES: .Ltmp0 {{.*}}
37+
# CHECK-ENTRIES-NEXT: Secondary Entry Point: {{.*}}
38+
# CHECK-ENTRIES: .Ltmp1 {{.*}}
39+
# CHECK-ENTRIES-NEXT: Secondary Entry Point: {{.*}}
40+
41+
.globl main
42+
.p2align 2
43+
.type main,@function
44+
main:
45+
.cfi_startproc
46+
adrp x8, .L__const.main.ptrs+8
47+
add x8, x8, :lo12:.L__const.main.ptrs+8
48+
ldr x9, [x8], #8
49+
br x9
50+
51+
.Label0: // Block address taken
52+
ldr x9, [x8], #8
53+
br x9
54+
55+
.Label1: // Block address taken
56+
mov w0, #42
57+
ret
58+
59+
.Lfunc_end0:
60+
.size main, .Lfunc_end0-main
61+
.cfi_endproc
62+
.type .L__const.main.ptrs,@object
63+
.section .data.rel.ro,"aw",@progbits
64+
.p2align 3, 0x0
65+
.L__const.main.ptrs:
66+
.xword .Label0
67+
.xword .Label1

bolt/test/X86/Inputs/indirect_goto.c renamed to bolt/test/Inputs/indirect_goto.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
int main(int argc, char *argv[]) {
2-
static const void *T1[] = { &&L1, &&L2 };
3-
static const void *T2[] = { &&L2, &&L3 };
2+
static const void *T1[] = {&&L1, &&L2};
3+
static const void *T2[] = {&&L2, &&L3};
44

55
const void **T = (argc > 1) ? T1 : T2;
66

bolt/test/X86/indirect-goto-pie.test

Lines changed: 0 additions & 16 deletions
This file was deleted.

bolt/test/X86/indirect-goto.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## Check llvm-bolt processes binaries compiled from sources that use indirect goto.
2-
RUN: %clang %cflags -no-pie %S/Inputs/indirect_goto.c -Wl,-q -o %t
2+
RUN: %clang %cflags -no-pie %S/../Inputs/indirect_goto.c -Wl,-q -o %t
33
RUN: llvm-bolt %t -o %t.null --relocs=1 --print-cfg --print-only=main \
44
RUN: --strict \
55
RUN: 2>&1 | FileCheck %s

bolt/test/indirect-goto-relocs.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// This test checks that BOLT creates entry points from sources
2+
// that use indirect goto.
3+
4+
RUN: %clang %cflags -pie %S/Inputs/indirect_goto.c -o %t.exe -Wl,-q
5+
RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg | FileCheck --check-prefix=CHECK-PIE %s
6+
7+
RUN: %clang %cflags -no-pie %S/Inputs/indirect_goto.c -o %t.exe -Wl,-q
8+
RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg | FileCheck --check-prefix=CHECK-NO-PIE %s
9+
10+
// Check that BOLT registers extra entry points for dynamic relocations with PIE.
11+
CHECK-PIE: Binary Function "main" after building cfg {
12+
CHECK-PIE: IsMultiEntry: 1
13+
CHECK-PIE: Secondary Entry Points : {{.*}}
14+
15+
// Check that BOLT does not register extra entry points for dynamic relocations
16+
// without PIE
17+
CHECK-NO-PIE: Binary Function "main" after building cfg {
18+
CHECK-NO-PIE-NOT: IsMultiEntry: 1
19+
CHECK-NO-PIE-NOT: Secondary Entry Points : {{.*}}

0 commit comments

Comments
 (0)