xref: /llvm-project/bolt/test/runtime/X86/instrumentation-dup-jts.s (revision d648aa1b8e937de1648524e1f1016b53b29ba2a4)
1# This reproduces a bug with instrumentation when trying to instrument
2# functions that share a jump table with multiple indirect jumps. Usually,
3# each indirect jump that uses a JT will have its own copy of it. When
4# this does not happen, we need to duplicate the jump table safely, so
5# we can split the edges correctly (each copy of the jump table may have
6# different split edges). For this to happen, we need to correctly match
7# the sequence of instructions that perform the indirect jump to identify
8# the base address of the jump table and patch it to point to the new
9# cloned JT.
10#
11# Here we test this variant:
12#	  movq	jt.2397(,%rax,8), %rax
13#   jmp	*%rax
14#
15# Which is suboptimal since the compiler could've avoided using an intermediary
16# register, but GCC does generate this code and it triggered a bug in our
17# matcher. Usual jumps in non-PIC code have this format:
18#
19#   jmp	*jt.2397(,%rax,8)
20#
21# This is the C code fed to GCC:
22#  #include <stdio.h>
23#int interp(char* code) {
24#    static void* jt[] = { &&op_end, &&op_inc, &&do_dec };
25#    int pc = 0;
26#    int res = 0;
27#    goto *jt[code[pc++] - '0'];
28#
29#op_inc:
30#    res += 1;
31#    printf("%d\n", res);
32#    goto *jt[code[pc++] - '0'];
33#do_dec:
34#    res -= 1;
35#    printf("%d\n", res);
36#    goto *jt[code[pc++] - '0'];
37#op_end:
38#    return res;
39#}
40#int main(int argc, char** argv) {
41#    return interp(argv[1]);
42#}
43
44
45# REQUIRES: system-linux,bolt-runtime
46
47# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \
48# RUN:   %s -o %t.o
49# RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q
50
51# RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \
52# RUN:   -o %t.instrumented
53
54# Instrumented program needs to finish returning zero
55# RUN: %t.instrumented 120
56
57# Test that the instrumented data makes sense
58# RUN:  llvm-bolt %t.exe -o %t.bolted --data %t.fdata \
59# RUN:    --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \
60# RUN:    --print-only=interp --print-finalized | FileCheck %s
61
62# RUN: %t.bolted 120
63
64# Check that our two indirect jumps are recorded in the fdata file and that
65# each has its own independent profile
66# CHECK:  Successors: .Ltmp1 (mispreds: 0, count: 1), .Ltmp0 (mispreds: 0, count: 0), .Ltmp2 (mispreds: 0, count: 0)
67# CHECK:  Successors: .Ltmp0 (mispreds: 0, count: 1), .Ltmp2 (mispreds: 0, count: 1), .Ltmp1 (mispreds: 0, count: 0)
68
69	.file	"test.c"
70	.text
71	.section	.rodata.str1.1,"aMS",@progbits,1
72.LC0:
73	.string	"%d\n"
74	.text
75	.p2align 4,,15
76	.globl	interp
77	.type	interp, @function
78interp:
79.LFB11:
80	.cfi_startproc
81	pushq	%rbp
82	.cfi_def_cfa_offset 16
83	.cfi_offset 6, -16
84	xorl	%ebp, %ebp
85	pushq	%rbx
86	.cfi_def_cfa_offset 24
87	.cfi_offset 3, -24
88	leaq	1(%rdi), %rbx
89	subq	$8, %rsp
90	.cfi_def_cfa_offset 32
91	movsbl	(%rdi), %eax
92	subl	$48, %eax
93	cltq
94	movq	jt.2397(,%rax,8), %rax
95	jmp	*%rax
96	.p2align 4,,10
97	.p2align 3
98.L3:
99	addl	$1, %ebp
100.L8:
101	movl	%ebp, %esi
102	movl	$.LC0, %edi
103	xorl	%eax, %eax
104	addq	$1, %rbx
105	call	printf
106	movsbl	-1(%rbx), %eax
107	subl	$48, %eax
108	cltq
109	movq	jt.2397(,%rax,8), %rax
110	jmp	*%rax
111	.p2align 4,,10
112	.p2align 3
113.L6:
114	addq	$8, %rsp
115	.cfi_remember_state
116	.cfi_def_cfa_offset 24
117	movl	%ebp, %eax
118	popq	%rbx
119	.cfi_def_cfa_offset 16
120	popq	%rbp
121	.cfi_def_cfa_offset 8
122	ret
123	.p2align 4,,10
124	.p2align 3
125.L4:
126	.cfi_restore_state
127	subl	$1, %ebp
128	jmp	.L8
129	.cfi_endproc
130.LFE11:
131	.size	interp, .-interp
132	.section	.text.startup,"ax",@progbits
133	.p2align 4,,15
134	.globl	main
135	.type	main, @function
136main:
137.LFB12:
138	.cfi_startproc
139	movq	8(%rsi), %rdi
140	jmp	interp
141	.cfi_endproc
142.LFE12:
143	.size	main, .-main
144	.section	.rodata
145	.align 16
146	.type	jt.2397, @object
147	.size	jt.2397, 24
148jt.2397:
149	.quad	.L6
150	.quad	.L3
151	.quad	.L4
152	.ident	"GCC: (GNU) 8"
153	.section	.note.GNU-stack,"",@progbits
154