diff options
author | Alexey Samsonov <samsonov@google.com> | 2012-09-24 13:19:47 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2012-09-24 13:19:47 +0000 |
commit | 4f0ea398bdc99a4a32402057c23bbcc6d19a8eb4 (patch) | |
tree | f55f9875ac43563f30fdbf45a3460b32021978a5 /lib/tsan | |
parent | b46941a1d23012491a7a8a52718cacbde3c19ba1 (diff) |
[TSan] Provide replacements for operators new/delete instead of declaring extern C functions with weirdly mangled names (same strategy is used in ASan).
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@164487 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r-- | lib/tsan/rtl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/Makefile.old | 2 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cc | 201 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.h | 54 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_mman.cc | 26 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_mman.h | 4 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_new_delete.cc | 70 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.h | 1 |
8 files changed, 181 insertions, 178 deletions
diff --git a/lib/tsan/rtl/CMakeLists.txt b/lib/tsan/rtl/CMakeLists.txt index 2538f99b9..4131a8586 100644 --- a/lib/tsan/rtl/CMakeLists.txt +++ b/lib/tsan/rtl/CMakeLists.txt @@ -8,6 +8,7 @@ set(TSAN_SOURCES tsan_md5.cc tsan_mman.cc tsan_mutex.cc + tsan_new_delete.cc tsan_printf.cc tsan_report.cc tsan_rtl.cc diff --git a/lib/tsan/rtl/Makefile.old b/lib/tsan/rtl/Makefile.old index 89ce83221..d674a2ecd 100644 --- a/lib/tsan/rtl/Makefile.old +++ b/lib/tsan/rtl/Makefile.old @@ -42,6 +42,8 @@ LIBTSAN_OBJ=$(patsubst %.cc,%.o,$(LIBTSAN_SRC)) \ %_linux.o: %_linux.cc Makefile.old $(LIBTSAN_HEADERS) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< +%_new_delete.o: %_new_delete.cc Makefile.old $(LIBTSAN_HEADERS) + $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< %.o: %.cc Makefile.old $(LIBTSAN_HEADERS) $(CXX) $(CXXFLAGS) $(INCLUDES) $(NO_SYSROOT) -c $< %.o: $(INTERCEPTION)/%.cc Makefile.old $(LIBTSAN_HEADERS) diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 2adb1c022..5f4375b8b 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -1,4 +1,4 @@ -//===-- tsan_interceptors_linux.cc ----------------------------------------===// +//===-- tsan_interceptors.cc ----------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "interception/interception.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_placement_new.h" -#include "tsan_rtl.h" +#include "tsan_interceptors.h" #include "tsan_interface.h" #include "tsan_platform.h" +#include "tsan_rtl.h" #include "tsan_mman.h" using namespace __tsan; // NOLINT @@ -133,89 +133,27 @@ static unsigned g_thread_finalize_key; static void process_pending_signals(ThreadState *thr); -class ScopedInterceptor { - public: - ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc) - : thr_(thr) - , in_rtl_(thr->in_rtl) { - if (thr_->in_rtl == 0) { - Initialize(thr); - FuncEntry(thr, pc); - thr_->in_rtl++; - DPrintf("#%d: intercept %s()\n", thr_->tid, fname); - } else { - thr_->in_rtl++; - } - } - - ~ScopedInterceptor() { - thr_->in_rtl--; - if (thr_->in_rtl == 0) { - FuncExit(thr_); - process_pending_signals(thr_); - } - CHECK_EQ(in_rtl_, thr_->in_rtl); +ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, + uptr pc) + : thr_(thr) + , in_rtl_(thr->in_rtl) { + if (thr_->in_rtl == 0) { + Initialize(thr); + FuncEntry(thr, pc); + thr_->in_rtl++; + DPrintf("#%d: intercept %s()\n", thr_->tid, fname); + } else { + thr_->in_rtl++; } - - private: - ThreadState *const thr_; - const int in_rtl_; -}; - -#define SCOPED_INTERCEPTOR_RAW(func, ...) \ - ThreadState *thr = cur_thread(); \ - StatInc(thr, StatInterceptor); \ - StatInc(thr, StatInt_##func); \ - ScopedInterceptor si(thr, #func, \ - (__sanitizer::uptr)__builtin_return_address(0)); \ - const uptr pc = (uptr)&func; \ - (void)pc; \ -/**/ - -#define SCOPED_TSAN_INTERCEPTOR(func, ...) \ - SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ - if (thr->in_rtl > 1) \ - return REAL(func)(__VA_ARGS__); \ -/**/ - -#define SCOPED_INTERCEPTOR_LIBC(func, ...) \ - ThreadState *thr = cur_thread(); \ - StatInc(thr, StatInterceptor); \ - StatInc(thr, StatInt_##func); \ - ScopedInterceptor si(thr, #func, callpc); \ - const uptr pc = (uptr)&func; \ - (void)pc; \ - if (thr->in_rtl > 1) \ - return REAL(func)(__VA_ARGS__); \ -/**/ - -#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) -#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func) - -// May be overriden by front-end. -extern "C" void WEAK __tsan_malloc_hook(void *ptr, uptr size) { - (void)ptr; - (void)size; -} - -extern "C" void WEAK __tsan_free_hook(void *ptr) { - (void)ptr; -} - -static void invoke_malloc_hook(void *ptr, uptr size) { - Context *ctx = CTX(); - ThreadState *thr = cur_thread(); - if (ctx == 0 || !ctx->initialized || thr->in_rtl) - return; - __tsan_malloc_hook(ptr, size); } -static void invoke_free_hook(void *ptr) { - Context *ctx = CTX(); - ThreadState *thr = cur_thread(); - if (ctx == 0 || !ctx->initialized || thr->in_rtl) - return; - __tsan_free_hook(ptr); +ScopedInterceptor::~ScopedInterceptor() { + thr_->in_rtl--; + if (thr_->in_rtl == 0) { + FuncExit(thr_); + process_pending_signals(thr_); + } + CHECK_EQ(in_rtl_, thr_->in_rtl); } TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) { @@ -562,92 +500,6 @@ TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { return res; } -#ifdef __LP64__ - -// void *operator new(size_t) -TSAN_INTERCEPTOR(void*, _Znwm, uptr sz) { - void *p = 0; - { - SCOPED_TSAN_INTERCEPTOR(_Znwm, sz); - p = user_alloc(thr, pc, sz); - } - invoke_malloc_hook(p, sz); - return p; -} - -// void *operator new(size_t, nothrow_t) -TSAN_INTERCEPTOR(void*, _ZnwmRKSt9nothrow_t, uptr sz) { - void *p = 0; - { - SCOPED_TSAN_INTERCEPTOR(_ZnwmRKSt9nothrow_t, sz); - p = user_alloc(thr, pc, sz); - } - invoke_malloc_hook(p, sz); - return p; -} - -// void *operator new[](size_t) -TSAN_INTERCEPTOR(void*, _Znam, uptr sz) { - void *p = 0; - { - SCOPED_TSAN_INTERCEPTOR(_Znam, sz); - p = user_alloc(thr, pc, sz); - } - invoke_malloc_hook(p, sz); - return p; -} - -// void *operator new[](size_t, nothrow_t) -TSAN_INTERCEPTOR(void*, _ZnamRKSt9nothrow_t, uptr sz) { - void *p = 0; - { - SCOPED_TSAN_INTERCEPTOR(_ZnamRKSt9nothrow_t, sz); - p = user_alloc(thr, pc, sz); - } - invoke_malloc_hook(p, sz); - return p; -} - -#else -#error "Not implemented" -#endif - -// void operator delete(void*) -TSAN_INTERCEPTOR(void, _ZdlPv, void *p) { - if (p == 0) - return; - invoke_free_hook(p); - SCOPED_TSAN_INTERCEPTOR(_ZdlPv, p); - user_free(thr, pc, p); -} - -// void operator delete(void*, nothrow_t) -TSAN_INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *p) { - if (p == 0) - return; - invoke_free_hook(p); - SCOPED_TSAN_INTERCEPTOR(_ZdlPvRKSt9nothrow_t, p); - user_free(thr, pc, p); -} - -// void operator delete[](void*) -TSAN_INTERCEPTOR(void, _ZdaPv, void *p) { - if (p == 0) - return; - invoke_free_hook(p); - SCOPED_TSAN_INTERCEPTOR(_ZdaPv, p); - user_free(thr, pc, p); -} - -// void operator delete[](void*, nothrow_t) -TSAN_INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *p) { - if (p == 0) - return; - invoke_free_hook(p); - SCOPED_TSAN_INTERCEPTOR(_ZdaPvRKSt9nothrow_t, p); - user_free(thr, pc, p); -} - TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { SCOPED_TSAN_INTERCEPTOR(memalign, align, sz); return user_alloc(thr, pc, sz, align); @@ -1447,7 +1299,7 @@ static void process_pending_signals(ThreadState *thr) { sigactions[sig].sa_handler(sig); if (errno != 0) { ScopedInRtl in_rtl; - StackTrace stack; + __tsan::StackTrace stack; uptr pc = signal->sigaction ? (uptr)sigactions[sig].sa_sigaction : (uptr)sigactions[sig].sa_handler; @@ -1491,14 +1343,7 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pvalloc); TSAN_INTERCEPT(posix_memalign); - TSAN_INTERCEPT(_Znwm); - TSAN_INTERCEPT(_ZnwmRKSt9nothrow_t); - TSAN_INTERCEPT(_Znam); - TSAN_INTERCEPT(_ZnamRKSt9nothrow_t); - TSAN_INTERCEPT(_ZdlPv); - TSAN_INTERCEPT(_ZdlPvRKSt9nothrow_t); - TSAN_INTERCEPT(_ZdaPv); - TSAN_INTERCEPT(_ZdaPvRKSt9nothrow_t); + ReplaceOperatorsNewAndDelete(); TSAN_INTERCEPT(strlen); TSAN_INTERCEPT(memset); diff --git a/lib/tsan/rtl/tsan_interceptors.h b/lib/tsan/rtl/tsan_interceptors.h new file mode 100644 index 000000000..34b182305 --- /dev/null +++ b/lib/tsan/rtl/tsan_interceptors.h @@ -0,0 +1,54 @@ +//===-- tsan_interceptors.h -------------------------------------*- C++ -*-===// +// +// 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 (TSan), a race detector. +// +//===----------------------------------------------------------------------===// + +#ifndef TSAN_INTERCEPTORS_H +#define TSAN_INTERCEPTORS_H + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_stacktrace.h" +#include "tsan_rtl.h" + +namespace __tsan { + +class ScopedInterceptor { + public: + ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc); + ~ScopedInterceptor(); + private: + ThreadState *const thr_; + const int in_rtl_; +}; + +#define SCOPED_INTERCEPTOR_RAW(func, ...) \ + ThreadState *thr = cur_thread(); \ + StatInc(thr, StatInterceptor); \ + StatInc(thr, StatInt_##func); \ + const uptr caller_pc = GET_CALLER_PC(); \ + ScopedInterceptor si(thr, #func, caller_pc); \ + /* Subtract one from pc as we need current instruction address */ \ + const uptr pc = __sanitizer::StackTrace::GetCurrentPc() - 1; \ + (void)pc; \ +/**/ + +#define SCOPED_TSAN_INTERCEPTOR(func, ...) \ + SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ + if (thr->in_rtl > 1) \ + return REAL(func)(__VA_ARGS__); \ +/**/ + +#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) +#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func) + +} // namespace __tsan + +#endif // TSAN_INTERCEPTORS_H diff --git a/lib/tsan/rtl/tsan_mman.cc b/lib/tsan/rtl/tsan_mman.cc index 1e1022bcd..6b334802a 100644 --- a/lib/tsan/rtl/tsan_mman.cc +++ b/lib/tsan/rtl/tsan_mman.cc @@ -17,6 +17,16 @@ #include "tsan_report.h" #include "tsan_flags.h" +// May be overriden by front-end. +extern "C" void WEAK __tsan_malloc_hook(void *ptr, uptr size) { + (void)ptr; + (void)size; +} + +extern "C" void WEAK __tsan_free_hook(void *ptr) { + (void)ptr; +} + namespace __tsan { static char allocator_placeholder[sizeof(Allocator)] ALIGNED(64); @@ -109,6 +119,22 @@ MBlock *user_mblock(ThreadState *thr, void *p) { return (MBlock*)allocator()->GetMetaData(p); } +void invoke_malloc_hook(void *ptr, uptr size) { + Context *ctx = CTX(); + ThreadState *thr = cur_thread(); + if (ctx == 0 || !ctx->initialized || thr->in_rtl) + return; + __tsan_malloc_hook(ptr, size); +} + +void invoke_free_hook(void *ptr) { + Context *ctx = CTX(); + ThreadState *thr = cur_thread(); + if (ctx == 0 || !ctx->initialized || thr->in_rtl) + return; + __tsan_free_hook(ptr); +} + void *internal_alloc(MBlockType typ, uptr sz) { ThreadState *thr = cur_thread(); CHECK_GT(thr->in_rtl, 0); diff --git a/lib/tsan/rtl/tsan_mman.h b/lib/tsan/rtl/tsan_mman.h index 340c4ad2e..06dce8c23 100644 --- a/lib/tsan/rtl/tsan_mman.h +++ b/lib/tsan/rtl/tsan_mman.h @@ -33,6 +33,10 @@ void *user_alloc_aligned(ThreadState *thr, uptr pc, uptr sz, uptr align); // returns the descriptor of the block. MBlock *user_mblock(ThreadState *thr, void *p); +// Invoking malloc/free hooks that may be installed by the user. +void invoke_malloc_hook(void *ptr, uptr size); +void invoke_free_hook(void *ptr); + enum MBlockType { MBlockScopedBuf, MBlockString, diff --git a/lib/tsan/rtl/tsan_new_delete.cc b/lib/tsan/rtl/tsan_new_delete.cc new file mode 100644 index 000000000..0b418aad4 --- /dev/null +++ b/lib/tsan/rtl/tsan_new_delete.cc @@ -0,0 +1,70 @@ +//===-- tsan_new_delete.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 (TSan), a race detector. +// +// Interceptors for operators new and delete. +//===----------------------------------------------------------------------===// + +#include "tsan_interceptors.h" +#include "tsan_mman.h" +#include "tsan_rtl.h" + +#include <stddef.h> +#include <new> + +namespace __tsan { +// This function is a no-op. We need it to make sure that object file +// with our replacements will actually be loaded from static TSan +// run-time library at link-time. +void ReplaceOperatorsNewAndDelete() { } +} + +using namespace __tsan; // NOLINT + +#define OPERATOR_NEW_BODY(mangled_name) \ + void *p = 0; \ + { \ + SCOPED_INTERCEPTOR_RAW(mangled_name, size); \ + p = user_alloc(thr, pc, size); \ + } \ + invoke_malloc_hook(p, size); \ + return p; + +void *operator new(size_t size) throw(std::bad_alloc) { + OPERATOR_NEW_BODY(_Znwm); +} +void *operator new[](size_t size) throw(std::bad_alloc) { + OPERATOR_NEW_BODY(_Znam); +} +void *operator new(size_t size, std::nothrow_t const&) throw() { + OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t); +} +void *operator new[](size_t size, std::nothrow_t const&) throw() { + OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t); +} + +#define OPERATOR_DELETE_BODY(mangled_name) \ + if (ptr == 0) return; \ + invoke_free_hook(ptr); \ + SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \ + user_free(thr, pc, ptr); + +void operator delete(void *ptr) throw() { + OPERATOR_DELETE_BODY(_ZdlPv); +} +void operator delete[](void *ptr) throw() { + OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t); +} +void operator delete(void *ptr, std::nothrow_t const&) throw() { + OPERATOR_DELETE_BODY(_ZdaPv); +} +void operator delete[](void *ptr, std::nothrow_t const&) throw() { + OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t); +} diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index a56025ef4..af9597f33 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -436,6 +436,7 @@ void ALWAYS_INLINE INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) { void InitializeShadowMemory(); void InitializeInterceptors(); void InitializeDynamicAnnotations(); +void ReplaceOperatorsNewAndDelete(); void ReportRace(ThreadState *thr); bool OutputReport(const ScopedReport &srep, |