xref: /llvm-project/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp (revision c6e83ddb37aff90b3fff2deb8605bc0adc54b393)
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 
17 uintptr_t *CFS_BEG, *CFS_END;
18 
__sanitizer_cov_cfs_init(const uintptr_t * cfs_beg,const uintptr_t * cfs_end)19 extern "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 
foo(int x)25 __attribute__((noinline)) void foo(int x) { /* empty body */
26 }
27 
check_cfs_section(uintptr_t main_ptr,uintptr_t foo_ptr)28 void 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 
main()59 int 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