Index: lib/tsan/CMakeLists.txt =================================================================== --- lib/tsan/CMakeLists.txt +++ lib/tsan/CMakeLists.txt @@ -39,7 +39,6 @@ rtl/tsan_mman.cc rtl/tsan_mutex.cc rtl/tsan_mutexset.cc - rtl/tsan_preinit.cc rtl/tsan_report.cc rtl/tsan_rtl.cc rtl/tsan_rtl_mutex.cc Index: lib/tsan/rtl/tsan_preinit.cc =================================================================== --- lib/tsan/rtl/tsan_preinit.cc +++ /dev/null @@ -1,27 +0,0 @@ -//===-- tsan_preinit.cc ---------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer. -// -// Call __tsan_init at the very early stage of process startup. -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_internal_defs.h" -#include "tsan_interface.h" - -#if SANITIZER_CAN_USE_PREINIT_ARRAY - -// The symbol is called __local_tsan_preinit, because it's not intended to be -// exported. -// This code linked into the main executable when -fsanitize=thread is in -// the link flags. It can only use exported interface functions. -__attribute__((section(".preinit_array"), used)) -void (*__local_tsan_preinit)(void) = __tsan_init; - -#endif Index: lib/tsan/rtl/tsan_rtl.cc =================================================================== --- lib/tsan/rtl/tsan_rtl.cc +++ lib/tsan/rtl/tsan_rtl.cc @@ -66,6 +66,8 @@ static char thread_registry_placeholder[sizeof(ThreadRegistry)]; +static bool is_initialized = false; + static ThreadContextBase *CreateThreadContext(u32 tid) { // Map thread trace when context is created. char name[50]; @@ -324,7 +326,6 @@ void Initialize(ThreadState *thr) { // Thread safe because done before all threads exist. - static bool is_initialized = false; if (is_initialized) return; is_initialized = true; @@ -944,6 +945,8 @@ ALWAYS_INLINE USED void FuncEntry(ThreadState *thr, uptr pc) { + if (!is_initialized) + Initialize(thr); StatInc(thr, StatFuncEnter); DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); if (kCollectHistory) { Index: test/tsan/Linux/check_preinit.cc =================================================================== --- test/tsan/Linux/check_preinit.cc +++ test/tsan/Linux/check_preinit.cc @@ -1,16 +1,12 @@ // 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. +// Test checks that instrumented code triggers __tsan_init even if it's called +// as early as from .preinit_array. #include @@ -20,6 +16,7 @@ volatile int counter = 0; volatile int lib_constructor_call = 0; volatile int tsan_init_call = 0; +volatile int preinit_array_call = 0; __attribute__ ((constructor)) void LibConstructor() { @@ -31,6 +28,7 @@ extern int counter; extern int lib_constructor_call; extern int tsan_init_call; +extern int preinit_array_call; volatile int bin_constructor_call = 0; @@ -47,11 +45,20 @@ } +void PreinitArray() { + preinit_array_call = ++counter; +}; + +__attribute__((section(".preinit_array"), used)) +void (*__preinit_test)(void) = PreinitArray; + int main() { // CHECK: TSAN_INIT 1 - // CHECK: LIB_CONSTRUCTOR 2 - // CHECK: BIN_CONSTRUCTOR 3 + // CHECK: PREINIT_ARRAY 2 + // CHECK: LIB_CONSTRUCTOR 3 + // CHECK: BIN_CONSTRUCTOR 4 printf("TSAN_INIT %d\n", tsan_init_call); + printf("PREINIT_ARRAY %d\n", preinit_array_call); printf("LIB_CONSTRUCTOR %d\n", lib_constructor_call); printf("BIN_CONSTRUCTOR %d\n", bin_constructor_call); return 0;