//
//===----------------------------------------------------------------------===//
+#include "lsan.h"
#include "lsan_common.h"
#include "sanitizer_common/sanitizer_common.h"
static bool CheckForLeaks() {
if (&__lsan_is_turned_off && __lsan_is_turned_off())
return false;
+ lsan_check_in_progress = true;
EnsureMainThreadIDIsCorrect();
CheckForLeaksParam param;
param.success = false;
param.leak_report.PrintSummary();
if (common_flags()->print_cmdline)
PrintCmdline();
+ lsan_check_in_progress = false;
return true;
}
+ lsan_check_in_progress = false;
return false;
}
SANITIZER_INTERFACE_ATTRIBUTE
void __lsan_register_root_region(const void *begin, uptr size) {
#if CAN_SANITIZE_LEAKS
- BlockingMutexLock l(&global_mutex);
CHECK(root_regions);
RootRegion region = {begin, size};
root_regions->push_back(region);
SANITIZER_INTERFACE_ATTRIBUTE
void __lsan_unregister_root_region(const void *begin, uptr size) {
#if CAN_SANITIZE_LEAKS
- BlockingMutexLock l(&global_mutex);
CHECK(root_regions);
bool removed = false;
for (uptr i = 0; i < root_regions->size(); i++) {
}
}
if (!removed) {
- Report(
+ VReport(1,
"__lsan_unregister_root_region(): region at %p of size %llu has not "
"been registered.\n",
begin, size);
- Die();
+ // Do nothing
}
#endif // CAN_SANITIZE_LEAKS
}
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
#include "lsan.h"
#include "lsan_allocator.h"
#include "lsan_thread.h"
#include <stddef.h>
+#include <sys/mman.h>
using namespace __lsan;
int pthread_attr_getdetachstate(void *attr, int *v);
int pthread_key_create(unsigned *key, void (*destructor)(void* v));
int pthread_setspecific(unsigned key, const void *v);
+void __lsan_register_root_region(const void *p, size_t size);
+void __lsan_unregister_root_region(const void *p, size_t size);
}
+BlockingMutex mmap_mutex(LINKER_INITIALIZED);
+
#define ENSURE_LSAN_INITED do { \
CHECK(!lsan_init_is_running); \
if (!lsan_inited) \
return res;
}
+static inline bool isSharedMmap(void *addr, int flags) {
+ return (flags & MAP_SHARED) && (addr == NULL);
+}
+
+static inline bool isAnonymousMmap(int flags, int fd) {
+ return ((flags & MAP_ANON) || (flags & MAP_ANONYMOUS)) &&
+ !(flags & MAP_STACK) && (fd == -1);
+}
+
+static inline bool isInterestingMmap(void *addr, int prot, int flags, int fd) {
+ return ((prot & PROT_WRITE) && (prot & PROT_READ)) &&
+ (isAnonymousMmap(flags, fd) || isSharedMmap(addr, flags));
+}
+
+static inline void MaybeRegisterMmapRegion(void *res, size_t length, void *addr,
+ int prot, int flags, int fd) {
+ if (!lsan_check_in_progress && isInterestingMmap(addr, prot, flags, fd)) {
+ BlockingMutexLock l(&mmap_mutex);
+ __lsan_register_root_region(res, length);
+ }
+}
+
+INTERCEPTOR(void *, mmap, void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset) {
+ void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
+ MaybeRegisterMmapRegion(res, length, addr, prot, flags, fd);
+ return res;
+}
+
+INTERCEPTOR(void *, mmap64, void *addr, size_t length, int prot, int flags,
+ int fd, __off64_t offset) {
+ void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
+ MaybeRegisterMmapRegion(res, length, addr, prot, flags, fd);
+ return res;
+}
+
+INTERCEPTOR(int, munmap, void *addr, size_t length) {
+ if (!lsan_check_in_progress) {
+ BlockingMutexLock l(&mmap_mutex);
+ __lsan_unregister_root_region(addr, length);
+ }
+ return REAL(munmap)(addr, length);
+}
+
namespace __lsan {
void InitializeInterceptors() {
INTERCEPT_FUNCTION(mallopt);
INTERCEPT_FUNCTION(pthread_create);
INTERCEPT_FUNCTION(pthread_join);
+ INTERCEPT_FUNCTION(mmap);
+ INTERCEPT_FUNCTION(mmap64);
+ INTERCEPT_FUNCTION(munmap);
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
Report("LeakSanitizer: failed to create thread key.\n");