summaryrefslogtreecommitdiff
path: root/lib/tsan
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2012-09-24 13:19:47 +0000
committerAlexey Samsonov <samsonov@google.com>2012-09-24 13:19:47 +0000
commit4f0ea398bdc99a4a32402057c23bbcc6d19a8eb4 (patch)
treef55f9875ac43563f30fdbf45a3460b32021978a5 /lib/tsan
parentb46941a1d23012491a7a8a52718cacbde3c19ba1 (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.txt1
-rw-r--r--lib/tsan/rtl/Makefile.old2
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc201
-rw-r--r--lib/tsan/rtl/tsan_interceptors.h54
-rw-r--r--lib/tsan/rtl/tsan_mman.cc26
-rw-r--r--lib/tsan/rtl/tsan_mman.h4
-rw-r--r--lib/tsan/rtl/tsan_new_delete.cc70
-rw-r--r--lib/tsan/rtl/tsan_rtl.h1
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,