Skip to content

Commit 59ab292

Browse files
authored
[BOLT] Register Linux kernel dynamic branch offsets (#90677)
To match profile data to code we need to know branch instruction offsets within a function. For this reason, we mark branches with the "Offset" annotation while disassembling the code. However, _dynamic_ branches in the Linux kernel could be NOPs in disassembled code, and we ignore them while adding annotations. We need to explicitly add the "Offset" annotation while creating dynamic branches. Note that without this change, `getInstructionAtOffset()` would still return a branch instruction if the offset matched the last instruction in a basic block (and the profile data was matched correctly). However, the function failed for cases when the searched instruction was followed by an unconditional jump. "Offset" annotation solves this case.
1 parent dd09a7d commit 59ab292

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,9 @@ Error LinuxKernelRewriter::readStaticKeysJumpTable() {
17221722
if (!BC.MIB->getSize(*Inst))
17231723
BC.MIB->setSize(*Inst, Size);
17241724

1725+
if (!BC.MIB->getOffset(*Inst))
1726+
BC.MIB->setOffset(*Inst, JumpAddress - BF->getAddress());
1727+
17251728
if (opts::LongJumpLabels)
17261729
BC.MIB->setSize(*Inst, 5);
17271730
}

bolt/test/X86/linux-static-keys.s

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## Check that BOLT correctly updates the Linux kernel static keys jump table.
44

55
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
6+
# RUN: link_fdata %s %t.o %t.fdata
7+
# RUN: llvm-strip --strip-unneeded %t.o
68
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
79
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr
810

@@ -11,6 +13,12 @@
1113
# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 \
1214
# RUN: --bolt-info=0 |& FileCheck %s
1315

16+
## Verify that profile is matched correctly.
17+
18+
# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 \
19+
# RUN: --bolt-info=0 --data %t.fdata |& \
20+
# RUN: FileCheck --check-prefix=CHECK-FDATA %s
21+
1422
## Verify the bindings again on the rewritten binary with nops removed.
1523

1624
# RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized |& FileCheck %s
@@ -25,15 +33,24 @@ _start:
2533
# CHECK: Binary Function "_start"
2634
nop
2735
.L0:
28-
jmp .L1
36+
jmp L1
2937
# CHECK: jit
3038
# CHECK-SAME: # ID: 1 {{.*}} # Likely: 0 # InitValue: 1
3139
nop
32-
.L1:
40+
L1:
3341
.nops 5
42+
jmp .L0
3443
# CHECK: jit
3544
# CHECK-SAME: # ID: 2 {{.*}} # Likely: 1 # InitValue: 1
36-
.L2:
45+
46+
## Check that a branch profile associated with a NOP is handled properly when
47+
## dynamic branch is created.
48+
49+
# FDATA: 1 _start #L1# 1 _start #L2# 3 42
50+
# CHECK-FDATA: jit {{.*}} # ID: 2
51+
# CHECK-FDATA-NEXT: jmp
52+
# CHECK-FDATA-NEXT: Successors: {{.*}} (mispreds: 3, count: 42)
53+
L2:
3754
nop
3855
.size _start, .-_start
3956

@@ -51,11 +68,11 @@ foo:
5168
__start___jump_table:
5269

5370
.long .L0 - . # Jump address
54-
.long .L1 - . # Target address
71+
.long L1 - . # Target address
5572
.quad 1 # Key address
5673

57-
.long .L1 - . # Jump address
58-
.long .L2 - . # Target address
74+
.long L1 - . # Jump address
75+
.long L2 - . # Target address
5976
.quad 0 # Key address
6077

6178
.globl __stop___jump_table

0 commit comments

Comments
 (0)