aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Matveev <earthdok@google.com>2013-11-25 17:39:36 +0000
committerSergey Matveev <earthdok@google.com>2013-11-25 17:39:36 +0000
commit74c88796a4024922144660ed1ade519af5008fe2 (patch)
tree47b21dbbf4aa654445a607b5315a7568a671bb78
parent12f610efe6f48efb2d03b985b3b2a36d4556fca7 (diff)
downloadcompiler-rt-74c88796a4024922144660ed1ade519af5008fe2.tar.gz
Merging r195642:
------------------------------------------------------------------------ r195642 | smatveev | 2013-11-25 18:25:36 +0400 (Mon, 25 Nov 2013) | 5 lines [lsan] Unbreak standalone LSan's initialization by making it more like ASan's. No longer allow interceptors to be called during initialization, use the preinit array (instead of initializing at the first call to an intercepted function) and adopt the calloc() hack from ASan. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/branches/release_34@195666 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/lsan/CMakeLists.txt7
-rw-r--r--lib/lsan/lsan.cc18
-rw-r--r--lib/lsan/lsan.h6
-rw-r--r--lib/lsan/lsan_interceptors.cc43
4 files changed, 52 insertions, 22 deletions
diff --git a/lib/lsan/CMakeLists.txt b/lib/lsan/CMakeLists.txt
index b2e88bcaf..3018a0662 100644
--- a/lib/lsan/CMakeLists.txt
+++ b/lib/lsan/CMakeLists.txt
@@ -9,10 +9,11 @@ set(LSAN_COMMON_SOURCES
lsan_common_linux.cc)
set(LSAN_SOURCES
- lsan_interceptors.cc
+ lsan.cc
lsan_allocator.cc
- lsan_thread.cc
- lsan.cc)
+ lsan_interceptors.cc
+ lsan_preinit.cc
+ lsan_thread.cc)
set(LSAN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/lib/lsan/lsan.cc b/lib/lsan/lsan.cc
index 1424f3b28..058bbdba3 100644
--- a/lib/lsan/lsan.cc
+++ b/lib/lsan/lsan.cc
@@ -20,6 +20,9 @@
#include "lsan_common.h"
#include "lsan_thread.h"
+bool lsan_inited;
+bool lsan_init_is_running;
+
namespace __lsan {
static void InitializeCommonFlags() {
@@ -32,11 +35,15 @@ static void InitializeCommonFlags() {
ParseCommonFlagsFromString(GetEnv("LSAN_OPTIONS"));
}
-void Init() {
- static bool inited;
- if (inited)
+} // namespace __lsan
+
+using namespace __lsan; // NOLINT
+
+extern "C" void __lsan_init() {
+ CHECK(!lsan_init_is_running);
+ if (lsan_inited)
return;
- inited = true;
+ lsan_init_is_running = true;
SanitizerToolName = "LeakSanitizer";
InitializeCommonFlags();
InitializeAllocator();
@@ -58,6 +65,7 @@ void Init() {
InitCommonLsan();
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
Atexit(DoLeakCheck);
+ lsan_inited = true;
+ lsan_init_is_running = false;
}
-} // namespace __lsan
diff --git a/lib/lsan/lsan.h b/lib/lsan/lsan.h
index d89a6ab8f..3e7f76b08 100644
--- a/lib/lsan/lsan.h
+++ b/lib/lsan/lsan.h
@@ -17,7 +17,11 @@
namespace __lsan {
-void Init();
void InitializeInterceptors();
} // namespace __lsan
+
+extern bool lsan_inited;
+extern bool lsan_init_is_running;
+
+extern "C" void __lsan_init();
diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc
index faf2a204b..400230b88 100644
--- a/lib/lsan/lsan_interceptors.cc
+++ b/lib/lsan/lsan_interceptors.cc
@@ -49,6 +49,12 @@ int pthread_setspecific(unsigned key, const void *v);
GET_CURRENT_FRAME(), stack_top, stack_bottom, fast); \
}
+#define ENSURE_LSAN_INITED do { \
+ CHECK(!lsan_init_is_running); \
+ if (!lsan_inited) \
+ __lsan_init(); \
+} while (0)
+
///// Malloc/free interceptors. /////
const bool kAlwaysClearMemory = true;
@@ -58,38 +64,49 @@ namespace std {
}
INTERCEPTOR(void*, malloc, uptr size) {
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
return Allocate(stack, size, 1, kAlwaysClearMemory);
}
INTERCEPTOR(void, free, void *p) {
- Init();
+ ENSURE_LSAN_INITED;
Deallocate(p);
}
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
+ if (lsan_init_is_running) {
+ // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
+ const uptr kCallocPoolSize = 1024;
+ static uptr calloc_memory_for_dlsym[kCallocPoolSize];
+ static uptr allocated;
+ uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
+ void *mem = (void*)&calloc_memory_for_dlsym[allocated];
+ allocated += size_in_words;
+ CHECK(allocated < kCallocPoolSize);
+ return mem;
+ }
if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
size *= nmemb;
return Allocate(stack, size, 1, true);
}
INTERCEPTOR(void*, realloc, void *q, uptr size) {
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
return Reallocate(stack, q, size, 1);
}
INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
return Allocate(stack, size, alignment, kAlwaysClearMemory);
}
INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
*memptr = Allocate(stack, size, alignment, kAlwaysClearMemory);
// FIXME: Return ENOMEM if user requested more than max alloc size.
@@ -97,7 +114,7 @@ INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
}
INTERCEPTOR(void*, valloc, uptr size) {
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
if (size == 0)
size = GetPageSizeCached();
@@ -105,7 +122,7 @@ INTERCEPTOR(void*, valloc, uptr size) {
}
INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
- Init();
+ ENSURE_LSAN_INITED;
return GetMallocUsableSize(ptr);
}
@@ -124,7 +141,7 @@ INTERCEPTOR(int, mallopt, int cmd, int value) {
}
INTERCEPTOR(void*, pvalloc, uptr size) {
- Init();
+ ENSURE_LSAN_INITED;
GET_STACK_TRACE;
uptr PageSize = GetPageSizeCached();
size = RoundUpTo(size, PageSize);
@@ -138,7 +155,7 @@ INTERCEPTOR(void*, pvalloc, uptr size) {
INTERCEPTOR(void, cfree, void *p) ALIAS("free");
#define OPERATOR_NEW_BODY \
- Init(); \
+ ENSURE_LSAN_INITED; \
GET_STACK_TRACE; \
return Allocate(stack, size, 1, kAlwaysClearMemory);
@@ -152,7 +169,7 @@ INTERCEPTOR_ATTRIBUTE
void *operator new[](uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
#define OPERATOR_DELETE_BODY \
- Init(); \
+ ENSURE_LSAN_INITED; \
Deallocate(ptr);
INTERCEPTOR_ATTRIBUTE
@@ -214,7 +231,7 @@ extern "C" void *__lsan_thread_start_func(void *arg) {
INTERCEPTOR(int, pthread_create, void *th, void *attr,
void *(*callback)(void *), void *param) {
- Init();
+ ENSURE_LSAN_INITED;
EnsureMainThreadIDIsCorrect();
__sanitizer_pthread_attr_t myattr;
if (attr == 0) {
@@ -242,7 +259,7 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr,
}
INTERCEPTOR(int, pthread_join, void *th, void **ret) {
- Init();
+ ENSURE_LSAN_INITED;
int tid = ThreadTid((uptr)th);
int res = REAL(pthread_join)(th, ret);
if (res == 0)