1 // RUN: %clangxx_dfsan %s -fno-exceptions -o %t && %run %t 2 // RUN: %clangxx_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 %s -fno-exceptions -o %t && %run %t 3 // 4 // REQUIRES: x86_64-target-arch 5 // 6 // Use -fno-exceptions to turn off exceptions to avoid instrumenting 7 // __cxa_begin_catch, std::terminate and __gxx_personality_v0. 8 // 9 // TODO: Support builtin atomics. For example, https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html 10 // DFSan instrumentation pass cannot identify builtin callsites yet. 11 12 #include <sanitizer/dfsan_interface.h> 13 14 #include <assert.h> 15 #include <atomic> 16 #include <pthread.h> 17 18 std::atomic<int> atomic_i{0}; 19 20 struct arg_struct { 21 size_t index; 22 dfsan_origin origin; 23 }; 24 25 static void *ThreadFn(void *arg) { 26 if (((arg_struct *)arg)->index % 2) { 27 int i = 10; 28 dfsan_set_label(8, (void *)&i, sizeof(i)); 29 atomic_i.store(i, std::memory_order_relaxed); 30 return 0; 31 } 32 int j = atomic_i.load(); 33 assert(dfsan_get_label(j) == 0 || dfsan_get_label(j) == 2); 34 #ifdef ORIGIN_TRACKING 35 if (dfsan_get_label(j) == 2) 36 assert(dfsan_get_init_origin(&j) == ((arg_struct *)arg)->origin); 37 #endif 38 return 0; 39 } 40 41 int main(void) { 42 int i = 10; 43 dfsan_set_label(2, (void *)&i, sizeof(i)); 44 #ifdef ORIGIN_TRACKING 45 dfsan_origin origin = dfsan_get_origin(i); 46 #endif 47 atomic_i.store(i, std::memory_order_relaxed); 48 const int kNumThreads = 24; 49 pthread_t t[kNumThreads]; 50 arg_struct args[kNumThreads]; 51 for (int i = 0; i < kNumThreads; ++i) { 52 args[i].index = i; 53 #ifdef ORIGIN_TRACKING 54 args[i].origin = origin; 55 #endif 56 pthread_create(&t[i], 0, ThreadFn, (void *)(args + i)); 57 } 58 for (int i = 0; i < kNumThreads; ++i) 59 pthread_join(t[i], 0); 60 return 0; 61 } 62