16db8c59fSFangrui Song // Check that we can patch and unpatch specific function ids. 26db8c59fSFangrui Song // 36db8c59fSFangrui Song // RUN: %clangxx_xray -std=c++11 %s -o %t 4*643a2080SHarini0924 // RUN: env XRAY_OPTIONS="patch_premain=false" %run %t | FileCheck %s 57c7c8e0dSIan Levesque // RUN: %clangxx_xray -fno-xray-function-index -std=c++11 %s -o %t 6*643a2080SHarini0924 // RUN: env XRAY_OPTIONS="patch_premain=false" %run %t | FileCheck %s 76db8c59fSFangrui Song 86db8c59fSFangrui Song // UNSUPPORTED: target-is-mips64,target-is-mips64el 96db8c59fSFangrui Song 106db8c59fSFangrui Song #include "xray/xray_interface.h" 116db8c59fSFangrui Song 126db8c59fSFangrui Song #include <set> 136db8c59fSFangrui Song #include <cstdio> 146db8c59fSFangrui Song #include <cassert> 156db8c59fSFangrui Song 166db8c59fSFangrui Song std::set<int32_t> function_ids; 176db8c59fSFangrui Song 186db8c59fSFangrui Song [[clang::xray_never_instrument]] void coverage_handler(int32_t fid, 196db8c59fSFangrui Song XRayEntryType) { 206db8c59fSFangrui Song thread_local bool patching = false; 216db8c59fSFangrui Song if (patching) return; 226db8c59fSFangrui Song patching = true; 236db8c59fSFangrui Song function_ids.insert(fid); 246db8c59fSFangrui Song __xray_unpatch_function(fid); 256db8c59fSFangrui Song patching = false; 266db8c59fSFangrui Song } 276db8c59fSFangrui Song 286db8c59fSFangrui Song [[clang::xray_always_instrument]] void baz() { 296db8c59fSFangrui Song // do nothing! 306db8c59fSFangrui Song } 316db8c59fSFangrui Song 326db8c59fSFangrui Song [[clang::xray_always_instrument]] void bar() { 336db8c59fSFangrui Song baz(); 346db8c59fSFangrui Song } 356db8c59fSFangrui Song 366db8c59fSFangrui Song [[clang::xray_always_instrument]] void foo() { 376db8c59fSFangrui Song bar(); 386db8c59fSFangrui Song } 396db8c59fSFangrui Song 406db8c59fSFangrui Song [[clang::xray_always_instrument]] int main(int argc, char *argv[]) { 416db8c59fSFangrui Song __xray_set_handler(coverage_handler); 426db8c59fSFangrui Song assert(__xray_patch() == XRayPatchingStatus::SUCCESS); 436db8c59fSFangrui Song foo(); 446db8c59fSFangrui Song assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS); 456db8c59fSFangrui Song 466db8c59fSFangrui Song // print out the function_ids. 476db8c59fSFangrui Song printf("first pass.\n"); 486db8c59fSFangrui Song for (const auto id : function_ids) 496db8c59fSFangrui Song printf("patched: %d\n", id); 506db8c59fSFangrui Song 516db8c59fSFangrui Song // CHECK-LABEL: first pass. 526db8c59fSFangrui Song // CHECK-DAG: patched: [[F1:.*]] 536db8c59fSFangrui Song // CHECK-DAG: patched: [[F2:.*]] 546db8c59fSFangrui Song // CHECK-DAG: patched: [[F3:.*]] 556db8c59fSFangrui Song 566db8c59fSFangrui Song // make a copy of the function_ids, then patch them later. 576db8c59fSFangrui Song auto called_fns = function_ids; 586db8c59fSFangrui Song 596db8c59fSFangrui Song // clear the function_ids. 606db8c59fSFangrui Song function_ids.clear(); 616db8c59fSFangrui Song 626db8c59fSFangrui Song // patch the functions we've called before. 636db8c59fSFangrui Song for (const auto id : called_fns) 646db8c59fSFangrui Song assert(__xray_patch_function(id) == XRayPatchingStatus::SUCCESS); 656db8c59fSFangrui Song 666db8c59fSFangrui Song // then call them again. 676db8c59fSFangrui Song foo(); 686db8c59fSFangrui Song assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS); 696db8c59fSFangrui Song 706db8c59fSFangrui Song // confirm that we've seen the same functions again. 716db8c59fSFangrui Song printf("second pass.\n"); 726db8c59fSFangrui Song for (const auto id : function_ids) 736db8c59fSFangrui Song printf("patched: %d\n", id); 746db8c59fSFangrui Song // CHECK-LABEL: second pass. 756db8c59fSFangrui Song // CHECK-DAG: patched: [[F1]] 766db8c59fSFangrui Song // CHECK-DAG: patched: [[F2]] 776db8c59fSFangrui Song // CHECK-DAG: patched: [[F3]] 786db8c59fSFangrui Song 796db8c59fSFangrui Song // Now we want to make sure that if we unpatch one, that we're only going to 806db8c59fSFangrui Song // see two calls of the coverage_handler. 816db8c59fSFangrui Song function_ids.clear(); 826db8c59fSFangrui Song assert(__xray_patch() == XRayPatchingStatus::SUCCESS); 836db8c59fSFangrui Song assert(__xray_unpatch_function(1) == XRayPatchingStatus::SUCCESS); 846db8c59fSFangrui Song foo(); 856db8c59fSFangrui Song assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS); 866db8c59fSFangrui Song 876db8c59fSFangrui Song // confirm that we don't see function id one called anymore. 886db8c59fSFangrui Song printf("missing 1.\n"); 896db8c59fSFangrui Song for (const auto id : function_ids) 906db8c59fSFangrui Song printf("patched: %d\n", id); 916db8c59fSFangrui Song // CHECK-LABEL: missing 1. 926db8c59fSFangrui Song // CHECK-NOT: patched: 1 936db8c59fSFangrui Song } 94