xref: /llvm-project/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_control_flow.cpp (revision c6e83ddb37aff90b3fff2deb8605bc0adc54b393)
13e52c092SNavid Emamdoost // Tests -fsanitize-coverage=control-flow.
23e52c092SNavid Emamdoost 
33e52c092SNavid Emamdoost // REQUIRES: has_sancovcc,stable-runtime
43e52c092SNavid Emamdoost // UNSUPPORTED: i386-darwin, x86_64-darwin
53e52c092SNavid Emamdoost 
63e52c092SNavid Emamdoost // RUN: %clangxx -O0 -std=c++11 -fsanitize-coverage=control-flow %s -o %t
73e52c092SNavid Emamdoost // RUN: %run %t 2>&1 | FileCheck %s
83e52c092SNavid Emamdoost 
93e52c092SNavid Emamdoost #include <cstdint>
103e52c092SNavid Emamdoost #include <cstdio>
11*c6e83ddbSBlue Gaston #if __has_feature(ptrauth_calls)
12*c6e83ddbSBlue Gaston   #include <ptrauth.h>
13*c6e83ddbSBlue Gaston #else
14*c6e83ddbSBlue Gaston   #define ptrauth_strip(__value, __key) (__value)
15*c6e83ddbSBlue Gaston #endif
163e52c092SNavid Emamdoost 
173e52c092SNavid Emamdoost uintptr_t *CFS_BEG, *CFS_END;
183e52c092SNavid Emamdoost 
__sanitizer_cov_cfs_init(const uintptr_t * cfs_beg,const uintptr_t * cfs_end)193e52c092SNavid Emamdoost extern "C" void __sanitizer_cov_cfs_init(const uintptr_t *cfs_beg,
203e52c092SNavid Emamdoost                                          const uintptr_t *cfs_end) {
213e52c092SNavid Emamdoost   CFS_BEG = (uintptr_t *)cfs_beg;
223e52c092SNavid Emamdoost   CFS_END = (uintptr_t *)cfs_end;
233e52c092SNavid Emamdoost }
243e52c092SNavid Emamdoost 
foo(int x)253e52c092SNavid Emamdoost __attribute__((noinline)) void foo(int x) { /* empty body */
263e52c092SNavid Emamdoost }
273e52c092SNavid Emamdoost 
check_cfs_section(uintptr_t main_ptr,uintptr_t foo_ptr)283e52c092SNavid Emamdoost void check_cfs_section(uintptr_t main_ptr, uintptr_t foo_ptr) {
293e52c092SNavid Emamdoost   printf("Control Flow section boundaries: [%p %p)\n", CFS_BEG, CFS_END);
303e52c092SNavid Emamdoost   uintptr_t *pt = CFS_BEG;
313e52c092SNavid Emamdoost   uintptr_t currBB;
323e52c092SNavid Emamdoost 
333e52c092SNavid Emamdoost   while (pt < CFS_END) {
343e52c092SNavid Emamdoost     currBB = *pt;
353e52c092SNavid Emamdoost     pt++;
363e52c092SNavid Emamdoost 
373e52c092SNavid Emamdoost     if (currBB == main_ptr)
383e52c092SNavid Emamdoost       printf("Saw the main().\n");
393e52c092SNavid Emamdoost     else if (currBB == foo_ptr)
403e52c092SNavid Emamdoost       printf("Saw the foo().\n");
413e52c092SNavid Emamdoost 
423e52c092SNavid Emamdoost     // Iterate over successors.
433e52c092SNavid Emamdoost     while (*pt) {
443e52c092SNavid Emamdoost       pt++;
453e52c092SNavid Emamdoost     }
463e52c092SNavid Emamdoost     pt++;
473e52c092SNavid Emamdoost     // Iterate over callees.
483e52c092SNavid Emamdoost     while (*pt) {
493e52c092SNavid Emamdoost       if (*pt == foo_ptr && currBB != main_ptr)
503e52c092SNavid Emamdoost         printf("Direct call matched.\n");
513e52c092SNavid Emamdoost       if (*pt == -1 && currBB != main_ptr)
523e52c092SNavid Emamdoost         printf("Indirect call matched.\n");
533e52c092SNavid Emamdoost       pt++;
543e52c092SNavid Emamdoost     }
553e52c092SNavid Emamdoost     pt++;
563e52c092SNavid Emamdoost   }
573e52c092SNavid Emamdoost }
583e52c092SNavid Emamdoost 
main()593e52c092SNavid Emamdoost int main() {
60*c6e83ddbSBlue Gaston   auto main_ptr = ptrauth_strip(&main, ptrauth_key_function_pointer);
61*c6e83ddbSBlue Gaston   auto foo_ptr = ptrauth_strip(&foo, ptrauth_key_function_pointer);
623e52c092SNavid Emamdoost   int x = 10;
633e52c092SNavid Emamdoost 
643e52c092SNavid Emamdoost   if (x > 0)
653e52c092SNavid Emamdoost     foo(x);
663e52c092SNavid Emamdoost   else
673e52c092SNavid Emamdoost     (*foo_ptr)(x);
683e52c092SNavid Emamdoost 
693e52c092SNavid Emamdoost   check_cfs_section((uintptr_t)(*main_ptr), (uintptr_t)(*foo_ptr));
703e52c092SNavid Emamdoost 
713e52c092SNavid Emamdoost   printf("Finished!\n");
723e52c092SNavid Emamdoost   return 0;
733e52c092SNavid Emamdoost }
743e52c092SNavid Emamdoost 
753e52c092SNavid Emamdoost // CHECK: Control Flow section boundaries
763e52c092SNavid Emamdoost // CHECK-DAG: Saw the foo().
773e52c092SNavid Emamdoost // CHECK-DAG: Saw the main().
783e52c092SNavid Emamdoost // CHECK-DAG: Direct call matched.
793e52c092SNavid Emamdoost // CHECK-DAG: Indirect call matched.
803e52c092SNavid Emamdoost // CHECK: Finished!
81