Index: lib/lsan/lsan_interceptors.cc =================================================================== --- lib/lsan/lsan_interceptors.cc +++ lib/lsan/lsan_interceptors.cc @@ -50,7 +50,27 @@ struct nothrow_t; } +static uptr allocated_for_dlsym; +static const uptr kDlsymAllocPoolSize = 1024; +static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; + +static bool IsInDlsymAllocPool(const void *ptr) { + uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + return off < sizeof(alloc_memory_for_dlsym); +} + +static void *AllocateFromLocalPool(uptr size_in_bytes) { + uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; + void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym]; + allocated_for_dlsym += size_in_words; + CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); + return mem; +} + INTERCEPTOR(void*, malloc, uptr size) { + if (UNLIKELY(!lsan_inited)) + // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. + return AllocateFromLocalPool(size); ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; return Allocate(stack, size, 1, kAlwaysClearMemory); @@ -58,21 +78,15 @@ INTERCEPTOR(void, free, void *p) { ENSURE_LSAN_INITED; + if (UNLIKELY(IsInDlsymAllocPool(p))) + return; Deallocate(p); } INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { - if (lsan_init_is_running) { + if (UNLIKELY(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; - } + return AllocateFromLocalPool(nmemb * size); if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return nullptr; ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; @@ -83,6 +97,13 @@ INTERCEPTOR(void*, realloc, void *q, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; + if (UNLIKELY(IsInDlsymAllocPool(q))) { + uptr offset = (uptr)q - (uptr)alloc_memory_for_dlsym; + uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); + void *new_q = Allocate(stack, size, 1, true); + internal_memcpy(new_q, q, copy_size); + return new_q; + } return Reallocate(stack, q, size, 1); }