1// Tests -fsanitize-coverage=control-flow.
2
3// REQUIRES: has_sancovcc,stable-runtime
4// UNSUPPORTED: i386-darwin, x86_64-darwin
5
6// RUN: %clangxx -O0 -std=c++11 -fsanitize-coverage=control-flow %s -o %t
7// RUN: %run %t 2>&1 | FileCheck %s
8
9#include <cstdint>
10#include <cstdio>
11#if __has_feature(ptrauth_calls)
12 #include <ptrauth.h>
13#else
14 #define ptrauth_strip(__value, __key) (__value)
15#endif
16
17uintptr_t *CFS_BEG, *CFS_END;
18
19extern "C" void __sanitizer_cov_cfs_init(const uintptr_t *cfs_beg,
20 const uintptr_t *cfs_end) {
21 CFS_BEG = (uintptr_t *)cfs_beg;
22 CFS_END = (uintptr_t *)cfs_end;
23}
24
25__attribute__((noinline)) void foo(int x) { /* empty body */
26}
27
28void check_cfs_section(uintptr_t main_ptr, uintptr_t foo_ptr) {
29 printf("Control Flow section boundaries: [%p %p)\n", CFS_BEG, CFS_END);
30 uintptr_t *pt = CFS_BEG;
31 uintptr_t currBB;
32
33 while (pt < CFS_END) {
34 currBB = *pt;
35 pt++;
36
37 if (currBB == main_ptr)
38 printf("Saw the main().\n");
39 else if (currBB == foo_ptr)
40 printf("Saw the foo().\n");
41
42 // Iterate over successors.
43 while (*pt) {
44 pt++;
45 }
46 pt++;
47 // Iterate over callees.
48 while (*pt) {
49 if (*pt == foo_ptr && currBB != main_ptr)
50 printf("Direct call matched.\n");
51 if (*pt == -1 && currBB != main_ptr)
52 printf("Indirect call matched.\n");
53 pt++;
54 }
55 pt++;
56 }
57}
58
59int main() {
60 auto main_ptr = ptrauth_strip(&main, ptrauth_key_function_pointer);
61 auto foo_ptr = ptrauth_strip(&foo, ptrauth_key_function_pointer);
62 int x = 10;
63
64 if (x > 0)
65 foo(x);
66 else
67 (*foo_ptr)(x);
68
69 check_cfs_section((uintptr_t)(*main_ptr), (uintptr_t)(*foo_ptr));
70
71 printf("Finished!\n");
72 return 0;
73}
74
75// CHECK: Control Flow section boundaries
76// CHECK-DAG: Saw the foo().
77// CHECK-DAG: Saw the main().
78// CHECK-DAG: Direct call matched.
79// CHECK-DAG: Indirect call matched.
80// CHECK: Finished!
81

source code of compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp