94 lines · cpp
1// Check that we can patch and unpatch specific function ids.2//3// RUN: %clangxx_xray -std=c++11 %s -o %t4// RUN: env XRAY_OPTIONS="patch_premain=false" %run %t | FileCheck %s5// RUN: %clangxx_xray -fno-xray-function-index -std=c++11 %s -o %t6// RUN: env XRAY_OPTIONS="patch_premain=false" %run %t | FileCheck %s7 8// UNSUPPORTED: target-is-mips64,target-is-mips64el9 10#include "xray/xray_interface.h"11 12#include <set>13#include <cstdio>14#include <cassert>15 16std::set<int32_t> function_ids;17 18[[clang::xray_never_instrument]] void coverage_handler(int32_t fid,19 XRayEntryType) {20 thread_local bool patching = false;21 if (patching) return;22 patching = true;23 function_ids.insert(fid);24 __xray_unpatch_function(fid);25 patching = false;26}27 28[[clang::xray_always_instrument]] void baz() {29 // do nothing!30}31 32[[clang::xray_always_instrument]] void bar() {33 baz();34}35 36[[clang::xray_always_instrument]] void foo() {37 bar();38}39 40[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {41 __xray_set_handler(coverage_handler);42 assert(__xray_patch() == XRayPatchingStatus::SUCCESS);43 foo();44 assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);45 46 // print out the function_ids.47 printf("first pass.\n");48 for (const auto id : function_ids)49 printf("patched: %d\n", id);50 51 // CHECK-LABEL: first pass.52 // CHECK-DAG: patched: [[F1:.*]]53 // CHECK-DAG: patched: [[F2:.*]]54 // CHECK-DAG: patched: [[F3:.*]]55 56 // make a copy of the function_ids, then patch them later.57 auto called_fns = function_ids;58 59 // clear the function_ids.60 function_ids.clear();61 62 // patch the functions we've called before.63 for (const auto id : called_fns)64 assert(__xray_patch_function(id) == XRayPatchingStatus::SUCCESS);65 66 // then call them again.67 foo();68 assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);69 70 // confirm that we've seen the same functions again.71 printf("second pass.\n");72 for (const auto id : function_ids)73 printf("patched: %d\n", id);74 // CHECK-LABEL: second pass.75 // CHECK-DAG: patched: [[F1]]76 // CHECK-DAG: patched: [[F2]]77 // CHECK-DAG: patched: [[F3]]78 79 // Now we want to make sure that if we unpatch one, that we're only going to80 // see two calls of the coverage_handler.81 function_ids.clear();82 assert(__xray_patch() == XRayPatchingStatus::SUCCESS);83 assert(__xray_unpatch_function(1) == XRayPatchingStatus::SUCCESS);84 foo();85 assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);86 87 // confirm that we don't see function id one called anymore.88 printf("missing 1.\n");89 for (const auto id : function_ids)90 printf("patched: %d\n", id);91 // CHECK-LABEL: missing 1.92 // CHECK-NOT: patched: 193}94