//
//===----------------------------------------------------------------------===//
+#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;
// Inside LockStuffAndStopTheWorld we can't run symbolizer, so we can't match
// suppressions. However if a stack id was previously suppressed, it should be
// suppressed in future checks as well.
}
LeakReport leak_report;
leak_report.AddLeakedChunks(param.leaks);
+ lsan_check_in_progress = false;
// No new suppressions stacks, so rerun will not help and we can report.
if (!leak_report.ApplySuppressions())
SANITIZER_INTERFACE_ATTRIBUTE
void __lsan_register_root_region(const void *begin, uptr size) {
#if CAN_SANITIZE_LEAKS
- Lock l(&global_mutex);
RootRegion region = {reinterpret_cast<uptr>(begin), size};
root_regions.push_back(region);
VReport(1, "Registered root region at %p of size %zu\n", begin, size);
SANITIZER_INTERFACE_ATTRIBUTE
void __lsan_unregister_root_region(const void *begin, uptr size) {
#if CAN_SANITIZE_LEAKS
- Lock l(&global_mutex);
bool removed = false;
for (uptr i = 0; i < root_regions.size(); i++) {
RootRegion region = root_regions[i];
}
}
if (!removed) {
- Report(
+ VReport(1,
"__lsan_unregister_root_region(): region at %p of size %zu has not "
"been registered.\n",
begin, size);
- Die();
+ // Do nothing
}
#endif // CAN_SANITIZE_LEAKS
}
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#if SANITIZER_POSIX
#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
#endif
#include "sanitizer_common/sanitizer_tls_get_addr.h"
#include "lsan.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);
}
+Mutex mmap_mutex;
+
struct DlsymAlloc : DlSymAllocator<DlsymAlloc> {
static bool UseImpl() { return lsan_init_is_running; }
static void OnAllocate(const void *ptr, uptr size) {
REAL(_exit)(status);
}
+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)) {
+ Lock 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) {
+ Lock l(&mmap_mutex);
+ __lsan_unregister_root_region(addr, length);
+ }
+ return REAL(munmap)(addr, length);
+}
+
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
INTERCEPT_FUNCTION(pthread_create);
INTERCEPT_FUNCTION(pthread_join);
INTERCEPT_FUNCTION(_exit);
+ INTERCEPT_FUNCTION(mmap);
+ INTERCEPT_FUNCTION(mmap64);
+ INTERCEPT_FUNCTION(munmap);
LSAN_MAYBE_INTERCEPT__LWP_EXIT;
LSAN_MAYBE_INTERCEPT_THR_EXIT;