summaryrefslogtreecommitdiff
path: root/test/tsan/Linux/check_preinit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/tsan/Linux/check_preinit.cc')
-rw-r--r--test/tsan/Linux/check_preinit.cc60
1 files changed, 60 insertions, 0 deletions
diff --git a/test/tsan/Linux/check_preinit.cc b/test/tsan/Linux/check_preinit.cc
new file mode 100644
index 0000000000000..8f5bf40337606
--- /dev/null
+++ b/test/tsan/Linux/check_preinit.cc
@@ -0,0 +1,60 @@
+// RUN: %clang_tsan -fno-sanitize=thread -shared -fPIC -O1 -DBUILD_SO=1 %s -o \
+// RUN: %t.so && \
+// RUN: %clang_tsan -O1 %s %t.so -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: llvm-objdump -t %t | FileCheck %s --check-prefix=CHECK-DUMP
+// CHECK-DUMP: {{[.]preinit_array.*__local_tsan_preinit}}
+
+// SANITIZER_CAN_USE_PREINIT_ARRAY is undefined on android.
+// UNSUPPORTED: android
+
+// Test checks if __tsan_init is called from .preinit_array.
+// Without initialization from .preinit_array, __tsan_init will be called from
+// constructors of the binary which are called after constructors of shared
+// library.
+
+#include <stdio.h>
+
+#if BUILD_SO
+
+// "volatile" is needed to avoid compiler optimize-out constructors.
+volatile int counter = 0;
+volatile int lib_constructor_call = 0;
+volatile int tsan_init_call = 0;
+
+__attribute__ ((constructor))
+void LibConstructor() {
+ lib_constructor_call = ++counter;
+};
+
+#else // BUILD_SO
+
+extern int counter;
+extern int lib_constructor_call;
+extern int tsan_init_call;
+
+volatile int bin_constructor_call = 0;
+
+__attribute__ ((constructor))
+void BinConstructor() {
+ bin_constructor_call = ++counter;
+};
+
+namespace __tsan {
+
+void OnInitialize() {
+ tsan_init_call = ++counter;
+}
+
+}
+
+int main() {
+ // CHECK: TSAN_INIT 1
+ // CHECK: LIB_CONSTRUCTOR 2
+ // CHECK: BIN_CONSTRUCTOR 3
+ printf("TSAN_INIT %d\n", tsan_init_call);
+ printf("LIB_CONSTRUCTOR %d\n", lib_constructor_call);
+ printf("BIN_CONSTRUCTOR %d\n", bin_constructor_call);
+ return 0;
+}
+
+#endif // BUILD_SO