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
11 # Here we test this variant:
12 # movq jt.2397(,%rax,8), %rax
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:
19 # jmp *jt.2397(,%rax,8)
21 # This is the C code fed to GCC:
23 #int interp(char* code) {
24 # static void* jt[] = { &&op_end, &&op_inc, &&do_dec };
27 # goto *jt[code[pc++] - '0'];
31 # printf("%d\n", res);
32 # goto *jt[code[pc++] - '0'];
35 # printf("%d\n", res);
36 # goto *jt[code[pc++] - '0'];
40 #int main(int argc, char** argv) {
41 # return interp(argv[1]);
45 # REQUIRES: system-linux,bolt-runtime
47 # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \
49 # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q
51 # RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \
52 # RUN: -o %t.instrumented
54 # Instrumented program needs to finish returning zero
55 # RUN: %t.instrumented 120
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
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)
71 .section .rodata.str1.1,"aMS",@progbits,1
77 .type interp, @function
82 .cfi_def_cfa_offset 16
86 .cfi_def_cfa_offset 24
90 .cfi_def_cfa_offset 32
94 movq jt.2397
(,%rax
,8), %rax
106 movsbl
-1(%rbx
), %eax
109 movq jt.2397
(,%rax
,8), %rax
116 .cfi_def_cfa_offset 24
119 .cfi_def_cfa_offset 16
121 .cfi_def_cfa_offset 8
131 .size interp, .-interp
132 .section .text.startup,"ax",@progbits
135 .type main, @function
146 .type jt.2397, @object
152 .ident "GCC: (GNU) 8"
153 .section .note.GNU-stack,"",@progbits