Skip to content

Commit 52cd00c

Browse files
nhuhuanaaupov
authored andcommitted
[BOLT] Ignore functions accessing false positive jump tables
Disassembly and branch target analysis are not decoupled, so any analysis that depends on disassembly may not operate properly. In specific, analyzeJumpTable uses instruction bounds check property. A jump table was analyzed twice: (a) during disassembly, and (b) after disassembly, so there are potentially some mismatched results. In this update, functions that access JTs which fail the second check will be marked as ignored. Test Plan: ``` ninja check-bolt ``` Reviewed By: Amir Differential Revision: https://reviews.llvm.org/D130431
1 parent ccabbff commit 52cd00c

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

bolt/lib/Core/BinaryContext.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,10 @@ bool BinaryContext::analyzeJumpTable(
622622
void BinaryContext::populateJumpTables() {
623623
LLVM_DEBUG(dbgs() << "DataPCRelocations: " << DataPCRelocations.size()
624624
<< '\n');
625+
626+
// Collect jump tables that pass the analyzeJumpTable's first check,
627+
// but fail the analyzeJumpTable's second check
628+
SmallVector<JumpTable *, 1> AbortedJTs;
625629
for (auto JTI = JumpTables.begin(), JTE = JumpTables.end(); JTI != JTE;
626630
++JTI) {
627631
JumpTable *JT = JTI->second;
@@ -640,6 +644,13 @@ void BinaryContext::populateJumpTables() {
640644
const bool Success =
641645
analyzeJumpTable(JT->getAddress(), JT->Type, *(JT->Parents[0]),
642646
NextJTAddress, &JT->EntriesAsAddress);
647+
// !Success means a false positive from earlier analysis run due to
648+
// different context. A possible culprit is instruction bounds check.
649+
// Previous run happens during disassembly. If the target function
650+
// is not disassembled, the check will be skipped, leading to a false
651+
// positive
652+
//
653+
// Solution: Ignore fragments accessing JT that fails the check
643654
if (!Success) {
644655
LLVM_DEBUG(ListSeparator LS;
645656
dbgs() << "failed to analyze jump table in function ";
@@ -659,7 +670,8 @@ void BinaryContext::populateJumpTables() {
659670
dbgs() << "\n";);
660671
NextJTI->second->print(dbgs());
661672
}
662-
llvm_unreachable("jump table heuristic failure");
673+
AbortedJTs.push_back(JT);
674+
continue;
663675
}
664676
for (BinaryFunction *Frag : JT->Parents) {
665677
for (uint64_t EntryAddress : JT->EntriesAsAddress)
@@ -689,6 +701,15 @@ void BinaryContext::populateJumpTables() {
689701
addFragmentsToSkip(Frag);
690702
}
691703

704+
// Ignore fragments accessing JT that fails analyzeJumpTable check
705+
for (JumpTable *JT : AbortedJTs) {
706+
for (BinaryFunction *Frag : JT->Parents) {
707+
Frag->setIgnored();
708+
Frag->JumpTables.erase(Frag->JumpTables.find(JT->getAddress()));
709+
}
710+
JumpTables.erase(JumpTables.find(JT->getAddress()));
711+
}
712+
692713
if (opts::StrictMode && DataPCRelocations.size()) {
693714
LLVM_DEBUG({
694715
dbgs() << DataPCRelocations.size()

bolt/test/X86/fake_jump_table.s

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Currently disassembly is not decoupled from branch target analysis.
2+
# This causes a few checks related to availability of target insn to
3+
# fail for stripped binaries:
4+
# (a) analyzeJumpTable
5+
# (b) postProcessEntryPoints
6+
# This test checks if BOLT can safely support instruction bounds check
7+
# for cross-function targets.
8+
9+
# REQUIRES: system-linux
10+
11+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
12+
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
13+
# RUN: llvm-bolt %t.exe -o %t.out -v=1 -print-cfg
14+
15+
.text
16+
.globl main
17+
.type main, %function
18+
.p2align 2
19+
main:
20+
LBB0:
21+
.cfi_startproc
22+
andl $0xf, %ecx
23+
cmpb $0x4, %cl
24+
ja .main.cold.1
25+
LBB1:
26+
leaq FAKE_JUMP_TABLE(%rip), %r8
27+
cmpq %r8, %r9
28+
LBB2:
29+
xorq %rax, %rax
30+
ret
31+
.cfi_endproc
32+
.size main, .-main
33+
34+
.globl main.cold.1
35+
.type main.cold.1, %function
36+
.p2align 2
37+
main.cold.1:
38+
.cfi_startproc
39+
nop
40+
LBB3:
41+
callq abort
42+
.cfi_endproc
43+
.size main.cold.1, .-main.cold.1
44+
45+
.rodata
46+
.globl FAKE_JUMP_TABLE
47+
FAKE_JUMP_TABLE:
48+
.long LBB2-FAKE_JUMP_TABLE
49+
.long LBB3-FAKE_JUMP_TABLE+0x1

0 commit comments

Comments
 (0)