Skip to content

Commit 19a3196

Browse files
author
Alexey Moksyakov
authored
[bolt][aarch64] Adding test with unsupported indirect branches (llvm#127655)
This test contains the set of common indirect branch patterns. Adding the support will be step by step
1 parent b0a7906 commit 19a3196

File tree

2 files changed

+291
-0
lines changed

2 files changed

+291
-0
lines changed

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,11 @@ void BinaryFunction::handleIndirectBranch(MCInst &Instruction, uint64_t Size,
12191219
case IndirectBranchType::UNKNOWN:
12201220
// Keep processing. We'll do more checks and fixes in
12211221
// postProcessIndirectBranches().
1222+
if (opts::Verbosity > 2) {
1223+
outs() << "BOLT-WARNING: failed to match indirect branch, "
1224+
<< getPrintName() << " at 0x" << Twine::utohexstr(Offset)
1225+
<< " offset\n";
1226+
}
12221227
UnknownIndirectBranchOffsets.emplace(Offset);
12231228
break;
12241229
}
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
## This test checks that disassemble stage works properly
2+
## JT with indirect branch
3+
## 1) nop + adr pair instructions
4+
## 2) sub + ldr pair instructions
5+
## 3) adrp + ldr pair instructions
6+
## 4) pic jt with relive offsets packed to 1-byte entry size
7+
## 5) fixed indirect branch
8+
## 6) normal jt
9+
10+
# REQUIRES: system-linux
11+
12+
# RUN: rm -rf %t && split-file %s %t
13+
14+
## Prepare binary (1)
15+
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %t/jt_nop_adr.s \
16+
# RUN: -o %t/jt_nop_adr.o
17+
# RUN: %clang %cflags --target=aarch64-unknown-linux %t/jt_nop_adr.o \
18+
# RUN: -Wl,-q -Wl,-z,now, -Wl,-T,%t/within-adr-range.t -o %t/jt_nop_adr.exe
19+
# RUN: llvm-objdump --no-show-raw-insn -d %t/jt_nop_adr.exe | FileCheck \
20+
# RUN: --check-prefix=JT-RELAXED %s
21+
22+
# JT-RELAXED: <_start>:
23+
# JT-RELAXED-NEXT: nop
24+
# JT-RELAXED-NEXT: adr {{.*}}x3
25+
26+
# RUN: llvm-bolt %t/jt_nop_adr.exe -o %t/jt_nop_adr.bolt -v 3 2>&1 | FileCheck \
27+
# RUN: --check-prefix=JT-BOLT-RELAXED %s
28+
29+
# JT-BOLT-RELAXED: failed to match indirect branch
30+
31+
## This linker script ensures that .rodata and .text are sufficiently (<1M)
32+
## close to each other so that the adrp + ldr pair can be relaxed to nop + adr.
33+
#--- within-adr-range.t
34+
SECTIONS {
35+
.rodata 0x1000: { *(.rodata) }
36+
.text 0x2000: { *(.text) }
37+
.rela.rodata : { *(.rela.rodata) }
38+
}
39+
40+
## Prepare binary (2)
41+
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %t/jt_sub_ldr.s \
42+
# RUN: -o %t/jt_sub_ldr.o
43+
# RUN: %clang %cflags --target=aarch64-unknown-linux %t/jt_sub_ldr.o \
44+
# RUN: -Wl,-q -Wl,-z,now -o %t/jt_sub_ldr.exe
45+
# RUN: llvm-objdump --no-show-raw-insn -d %t/jt_sub_ldr.exe | FileCheck \
46+
# RUN: --check-prefix=JT-SUB-LDR %s
47+
48+
# JT-SUB-LDR: <_start>:
49+
# JT-SUB-LDR-NEXT: sub
50+
# JT-SUB-LDR-NEXT: ldr
51+
52+
# RUN: llvm-bolt %t/jt_sub_ldr.exe -o %t/jt_sub_ldr.bolt -v 3 2>&1 | FileCheck \
53+
# RUN: --check-prefix=JT-BOLT-SUBLDR %s
54+
# JT-BOLT-SUBLDR: failed to match indirect branch
55+
56+
## Prepare binary (3)
57+
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %t/jt_adrp_ldr.s \
58+
# RUN: -o %t/jt_adrp_ldr.o
59+
# RUN: %clang %cflags --target=aarch64-unknown-linux %t/jt_adrp_ldr.o \
60+
# RUN: -Wl,-q -Wl,-z,now -Wl,--no-relax -o %t/jt_adrp_ldr.exe
61+
# RUN: llvm-objdump --no-show-raw-insn -d %t/jt_adrp_ldr.exe | FileCheck \
62+
# RUN: --check-prefix=JT-ADRP-LDR %s
63+
64+
# JT-ADRP-LDR: <_start>:
65+
# JT-ADRP-LDR-NEXT: adrp
66+
# JT-ADRP-LDR-NEXT: ldr
67+
68+
# RUN: llvm-bolt %t/jt_adrp_ldr.exe -o %t/jt_adrp_ldr.bolt -v 3 2>&1 | FileCheck \
69+
# RUN: --check-prefix=JT-BOLT-ADRP-LDR %s
70+
# JT-BOLT-ADRP-LDR: failed to match indirect branch
71+
72+
## Prepare binary (4)
73+
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
74+
# RUN: --position-independent %t/jt_pic_with_relative_offset.s \
75+
# RUN: -o %t/jt_pic_with_relative_offset.o
76+
# RUN: %clang %cflags -fPIC -O0 %t/jt_pic_with_relative_offset.o \
77+
# RUN: -o %t/jt_pic_with_relative_offset.exe -Wl,-q -Wl,--no-relax
78+
# RUN: llvm-bolt %t/jt_pic_with_relative_offset.exe \
79+
# RUN: -o %t/jt_pic_with_relative_offset.bolt -v 3 2>&1 | FileCheck \
80+
# RUN: --check-prefix=JT-BOLT-JT-PIC-OFFSETS %s
81+
82+
# JT-BOLT-JT-PIC-OFFSETS: failed to match indirect branch
83+
84+
## Prepare binary (5)
85+
# RUN: %clang %cflags %t/jt_fixed_branch.s -Wl,-q -Wl,--no-relax \
86+
# RUN: -o %t/jt_fixed_branch.exe
87+
88+
# RUN: llvm-bolt %t/jt_fixed_branch.exe \
89+
# RUN: -o %t/jt_fixed_branch.bolt -v 3 2>&1 | FileCheck \
90+
# RUN: --check-prefix=JT-BOLT-FIXED-BR %s
91+
92+
# JT-BOLT-FIXED-BR: failed to match indirect branch
93+
94+
## Prepare binary (6)
95+
# RUN: %clang %cflags -no-pie %t/jt_type_normal.c \
96+
# RUN: -Wl,-q -Wl,-z,now -Wl,--no-relax \
97+
# RUN: -o %t/jt_type_normal.exe
98+
# RUN: llvm-objdump --no-show-raw-insn -d %t/jt_type_normal.exe | FileCheck \
99+
# RUN: --check-prefix=JT-OBJDUMP-NORMAL %s
100+
101+
# JT-OBJDUMP-NORMAL: <handleOptionJumpTable>:
102+
# JT-OBJDUMP-NORMAL: adrp
103+
# JT-OBJDUMP-NORMAL-NEXT: add
104+
# JT-OBJDUMP-NORMAL-NEXT: ldr
105+
# JT-OBJDUMP-NORMAL-NEXT: blr
106+
107+
# RUN: llvm-bolt %t/jt_type_normal.exe --dyno-stats \
108+
# RUN: -o %t/jt_type_normal.bolt -v 3 2>&1 | FileCheck \
109+
# RUN: --check-prefix=JT-BOLT-NORMAL %s
110+
111+
# JT-BOLT-NORMAL: 0{{.*}}: indirect calls
112+
113+
#--- jt_nop_adr.s
114+
.globl _start
115+
.type _start, %function
116+
_start:
117+
adrp x3, :got:jump_table
118+
ldr x3, [x3, #:got_lo12:jump_table]
119+
ldrh w3, [x3, x1, lsl #1]
120+
adr x1, test2_0
121+
add x3, x1, w3, sxth #2
122+
br x3
123+
test2_0:
124+
ret
125+
test2_1:
126+
ret
127+
128+
.section .rodata,"a",@progbits
129+
jump_table:
130+
.hword (test2_0-test2_0)>>2
131+
.hword (test2_1-test2_0)>>2
132+
133+
134+
#--- jt_sub_ldr.s
135+
.globl _start
136+
.type _start, %function
137+
_start:
138+
sub x1, x29, #0x4, lsl #12
139+
ldr x1, [x1, #14352]
140+
ldrh w1, [x1, w3, uxtw #1]
141+
adr x3, test2_0
142+
add x1, x3, w1, sxth #2
143+
br x1
144+
test2_0:
145+
ret
146+
test2_1:
147+
ret
148+
149+
.section .rodata,"a",@progbits
150+
jump_table:
151+
.hword (test2_0-test2_0)>>2
152+
.hword (test2_1-test2_0)>>2
153+
154+
155+
#--- jt_adrp_ldr.s
156+
.globl _start
157+
.type _start, %function
158+
_start:
159+
adrp x3, :got:jump_table
160+
ldr x3, [x3, #:got_lo12:jump_table]
161+
ldrh w3, [x3, x1, lsl #1]
162+
adr x1, test2_0
163+
add x3, x1, w3, sxth #2
164+
br x3
165+
test2_0:
166+
ret
167+
test2_1:
168+
ret
169+
170+
.section .rodata,"a",@progbits
171+
jump_table:
172+
.hword (test2_0-test2_0)>>2
173+
.hword (test2_1-test2_0)>>2
174+
175+
176+
#--- jt_pic_with_relative_offset.s
177+
.text
178+
.global _start
179+
_start:
180+
mov x4, 3 // index in jmp table where offset related to adr instr
181+
adrp x0, funcTableSym
182+
add x0, x0, #:lo12:funcTableSym
183+
ldrb w0, [x0, w4, uxtw #0]
184+
adr x2, .LBB1
185+
add x0, x2, w0, sxth #2
186+
br x0
187+
188+
.LBB1:
189+
bl funcA
190+
b .test_exit
191+
192+
.LBB2:
193+
bl funcB
194+
b .test_exit
195+
196+
.LBB3:
197+
bl funcC
198+
b .test_exit
199+
200+
.LBB4:
201+
bl funcD
202+
b .test_exit
203+
204+
.test_exit:
205+
mov x8, #93
206+
mov x0, #0
207+
svc #0
208+
209+
.global funcA
210+
funcA:
211+
ret
212+
213+
.global funcB
214+
funcB:
215+
ret
216+
217+
.global funcC
218+
funcC:
219+
ret
220+
221+
.global funcD
222+
funcD:
223+
ret
224+
225+
.section .rodata,"a",@progbits
226+
.align 2
227+
funcTableSym:
228+
.byte 0x00,0x02,0x04,0x06 // 1 - .LBB1, 3 - .LBB2
229+
230+
#--- jt_fixed_branch.s
231+
232+
.text
233+
.global _start
234+
_start:
235+
mov x0, x13
236+
mov x1, x4
237+
mov x0, x2
238+
movk x1, #0x0, lsl #48
239+
movk x1, #0x0, lsl #32
240+
movk x1, #0x0, lsl #16
241+
movk x1, #0x12
242+
stp x0, x1, [sp, #-16]!
243+
adrp x0, foo
244+
add x0, x0, #:lo12:foo
245+
br x0
246+
mov x8, #93
247+
mov x0, #0
248+
svc #0
249+
250+
.global foo
251+
.type foo,%function
252+
foo:
253+
mov x8, #9
254+
ret
255+
.size foo,.-foo
256+
257+
#--- jt_type_normal.c
258+
259+
void __attribute__ ((noinline)) option0() {
260+
}
261+
262+
void __attribute__ ((noinline)) option1() {
263+
}
264+
265+
void __attribute__ ((noinline)) option2() {
266+
}
267+
268+
void __attribute__ ((noinline)) option3() {
269+
}
270+
271+
void __attribute__ ((noinline)) option4() {
272+
}
273+
274+
void __attribute__ ((noinline)) option5() {
275+
}
276+
277+
void (*jumpTable[6])() = { option0, option1, option2, option3, option4, option5 };
278+
279+
void __attribute__ ((noinline)) handleOptionJumpTable(int option) {
280+
jumpTable[option]();
281+
}
282+
283+
int main(int argc, char *argv[]) {
284+
handleOptionJumpTable(argc);
285+
return 0;
286+
}

0 commit comments

Comments
 (0)