1 | // RUN: %clangxx_cfi_dso -DSHARED_LIB -fPIC -g -fsanitize-stats -shared -o %t.so %s |
2 | // RUN: %clangxx_cfi_dso -g -fsanitize-stats -o %t %s %t.so |
3 | // RUN: env SANITIZER_STATS_PATH=%t.stats %t |
4 | // RUN: sanstats %t.stats | FileCheck %s |
5 | |
6 | // CFI-icall is not implemented in thinlto mode => ".cfi" suffixes are missing |
7 | // in sanstats output. |
8 | |
9 | // FIXME: %t.stats must be transferred from device to host for this to work on Android. |
10 | // XFAIL: android |
11 | |
12 | struct ABase {}; |
13 | |
14 | struct A : ABase { |
15 | virtual void vf() {} |
16 | void nvf() {} |
17 | }; |
18 | |
19 | extern "C" void vcall(A *a); |
20 | extern "C" void nvcall(A *a); |
21 | |
22 | #ifdef SHARED_LIB |
23 | |
24 | extern "C" __attribute__((noinline)) void vcall(A *a) { |
25 | // CHECK-DAG: stats.cpp:[[@LINE+1]] vcall.cfi cfi-vcall 37 |
26 | a->vf(); |
27 | } |
28 | |
29 | extern "C" __attribute__((noinline)) void nvcall(A *a) { |
30 | // CHECK-DAG: stats.cpp:[[@LINE+1]] nvcall.cfi cfi-nvcall 51 |
31 | a->nvf(); |
32 | } |
33 | |
34 | #else |
35 | |
36 | extern "C" __attribute__((noinline)) A *dcast(A *a) { |
37 | // CHECK-DAG: stats.cpp:[[@LINE+1]] dcast.cfi cfi-derived-cast 24 |
38 | return (A *)(ABase *)a; |
39 | } |
40 | |
41 | extern "C" __attribute__((noinline)) A *ucast(A *a) { |
42 | // CHECK-DAG: stats.cpp:[[@LINE+1]] ucast.cfi cfi-unrelated-cast 81 |
43 | return (A *)(char *)a; |
44 | } |
45 | |
46 | extern "C" __attribute__((noinline)) void unreachable(A *a) { |
47 | // CHECK-NOT: unreachable |
48 | a->vf(); |
49 | } |
50 | |
51 | int main() { |
52 | A a; |
53 | for (unsigned i = 0; i != 37; ++i) |
54 | vcall(a: &a); |
55 | for (unsigned i = 0; i != 51; ++i) |
56 | nvcall(a: &a); |
57 | for (unsigned i = 0; i != 24; ++i) |
58 | dcast(a: &a); |
59 | for (unsigned i = 0; i != 81; ++i) |
60 | ucast(a: &a); |
61 | for (unsigned i = 0; i != 0; ++i) |
62 | unreachable(a: &a); |
63 | } |
64 | |
65 | #endif |
66 | |