1*bcaeed49SFangrui Song // RUN: %clang_tsan -fno-sanitize=thread -shared -fPIC -O1 -DBUILD_SO=1 %s -o \
2*bcaeed49SFangrui Song // RUN:  %t.so && \
3*bcaeed49SFangrui Song // RUN:   %clang_tsan -O1 %s %t.so -o %t && %run %t 2>&1 | FileCheck %s
4*bcaeed49SFangrui Song // RUN: llvm-objdump -t %t | FileCheck %s --check-prefix=CHECK-DUMP
5*bcaeed49SFangrui Song // CHECK-DUMP:  {{[.]preinit_array.*__local_tsan_preinit}}
6*bcaeed49SFangrui Song 
7*bcaeed49SFangrui Song // SANITIZER_CAN_USE_PREINIT_ARRAY is undefined on android.
8*bcaeed49SFangrui Song // UNSUPPORTED: android
9*bcaeed49SFangrui Song 
10*bcaeed49SFangrui Song // Test checks if __tsan_init is called from .preinit_array.
11*bcaeed49SFangrui Song // Without initialization from .preinit_array, __tsan_init will be called from
12*bcaeed49SFangrui Song // constructors of the binary which are called after constructors of shared
13*bcaeed49SFangrui Song // library.
14*bcaeed49SFangrui Song 
15*bcaeed49SFangrui Song #include <stdio.h>
16*bcaeed49SFangrui Song 
17*bcaeed49SFangrui Song #if BUILD_SO
18*bcaeed49SFangrui Song 
19*bcaeed49SFangrui Song // "volatile" is needed to avoid compiler optimize-out constructors.
20*bcaeed49SFangrui Song volatile int counter = 0;
21*bcaeed49SFangrui Song volatile int lib_constructor_call = 0;
22*bcaeed49SFangrui Song volatile int tsan_init_call = 0;
23*bcaeed49SFangrui Song 
24*bcaeed49SFangrui Song __attribute__ ((constructor))
LibConstructor()25*bcaeed49SFangrui Song void LibConstructor() {
26*bcaeed49SFangrui Song   lib_constructor_call = ++counter;
27*bcaeed49SFangrui Song };
28*bcaeed49SFangrui Song 
29*bcaeed49SFangrui Song #else  // BUILD_SO
30*bcaeed49SFangrui Song 
31*bcaeed49SFangrui Song extern int counter;
32*bcaeed49SFangrui Song extern int lib_constructor_call;
33*bcaeed49SFangrui Song extern int tsan_init_call;
34*bcaeed49SFangrui Song 
35*bcaeed49SFangrui Song volatile int bin_constructor_call = 0;
36*bcaeed49SFangrui Song 
37*bcaeed49SFangrui Song __attribute__ ((constructor))
BinConstructor()38*bcaeed49SFangrui Song void BinConstructor() {
39*bcaeed49SFangrui Song   bin_constructor_call = ++counter;
40*bcaeed49SFangrui Song };
41*bcaeed49SFangrui Song 
42*bcaeed49SFangrui Song namespace __tsan {
43*bcaeed49SFangrui Song 
OnInitialize()44*bcaeed49SFangrui Song void OnInitialize() {
45*bcaeed49SFangrui Song   tsan_init_call = ++counter;
46*bcaeed49SFangrui Song }
47*bcaeed49SFangrui Song 
48*bcaeed49SFangrui Song }
49*bcaeed49SFangrui Song 
main()50*bcaeed49SFangrui Song int main() {
51*bcaeed49SFangrui Song   // CHECK: TSAN_INIT 1
52*bcaeed49SFangrui Song   // CHECK: LIB_CONSTRUCTOR 2
53*bcaeed49SFangrui Song   // CHECK: BIN_CONSTRUCTOR 3
54*bcaeed49SFangrui Song   printf("TSAN_INIT %d\n", tsan_init_call);
55*bcaeed49SFangrui Song   printf("LIB_CONSTRUCTOR %d\n", lib_constructor_call);
56*bcaeed49SFangrui Song   printf("BIN_CONSTRUCTOR %d\n", bin_constructor_call);
57*bcaeed49SFangrui Song   return 0;
58*bcaeed49SFangrui Song }
59*bcaeed49SFangrui Song 
60*bcaeed49SFangrui Song #endif  // BUILD_SO
61