aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/lsan
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2019-11-05 14:54:57 +0100
committerMartin Liska <marxin@gcc.gnu.org>2019-11-05 13:54:57 +0000
commit3ca75cd55030a53a858bdbe9aba6d87f6b1e90b8 (patch)
treec3eb5c5658e168b819d23dd20aa46d614089c649 /libsanitizer/lsan
parent9bae89924afc811bd10e249856bf78dd19f20df2 (diff)
Libsanitizer: merge from trunk with merge.sh.
2019-11-05 Martin Liska <mliska@suse.cz> * all source files: Merge from upstream r375507. From-SVN: r277834
Diffstat (limited to 'libsanitizer/lsan')
-rw-r--r--libsanitizer/lsan/lsan.cpp4
-rw-r--r--libsanitizer/lsan/lsan_common.cpp16
-rw-r--r--libsanitizer/lsan/lsan_common.h5
-rw-r--r--libsanitizer/lsan/lsan_common_linux.cpp12
-rw-r--r--libsanitizer/lsan/lsan_common_mac.cpp6
-rw-r--r--libsanitizer/lsan/lsan_interceptors.cpp55
-rw-r--r--libsanitizer/lsan/lsan_mac.cpp2
7 files changed, 80 insertions, 20 deletions
diff --git a/libsanitizer/lsan/lsan.cpp b/libsanitizer/lsan/lsan.cpp
index 5b5f6198a69..4ce03046ffb 100644
--- a/libsanitizer/lsan/lsan.cpp
+++ b/libsanitizer/lsan/lsan.cpp
@@ -50,7 +50,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
}
}
-using namespace __lsan; // NOLINT
+using namespace __lsan;
static void InitializeFlags() {
// Set all the default values.
@@ -89,7 +89,7 @@ static void InitializeFlags() {
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) {
- stack->Unwind(sig.pc, sig.bp, sig.context,
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
common_flags()->fast_unwind_on_fatal);
}
diff --git a/libsanitizer/lsan/lsan_common.cpp b/libsanitizer/lsan/lsan_common.cpp
index c39fab97c64..9ff9f4c5d1c 100644
--- a/libsanitizer/lsan/lsan_common.cpp
+++ b/libsanitizer/lsan/lsan_common.cpp
@@ -84,7 +84,7 @@ static const char kStdSuppressions[] =
void InitializeSuppressions() {
CHECK_EQ(nullptr, suppression_ctx);
- suppression_ctx = new (suppression_placeholder) // NOLINT
+ suppression_ctx = new (suppression_placeholder)
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__lsan_default_suppressions)
@@ -104,7 +104,7 @@ InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
void InitializeRootRegions() {
CHECK(!root_regions);
ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
- root_regions = new (placeholder) InternalMmapVector<RootRegion>(); // NOLINT
+ root_regions = new (placeholder) InternalMmapVector<RootRegion>();
}
const char *MaybeCallLsanDefaultOptions() {
@@ -162,7 +162,7 @@ void ScanRangeForPointers(uptr begin, uptr end,
uptr pp = begin;
if (pp % alignment)
pp = pp + alignment - pp % alignment;
- for (; pp + sizeof(void *) <= end; pp += alignment) { // NOLINT
+ for (; pp + sizeof(void *) <= end; pp += alignment) {
void *p = *reinterpret_cast<void **>(pp);
if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
uptr chunk = PointsIntoChunk(p);
@@ -535,7 +535,7 @@ static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
Report("Running thread %d was not suspended. False leaks are possible.\n",
tctx->os_id);
- };
+ }
}
static void ReportUnsuspendedThreads(
@@ -570,11 +570,7 @@ static bool CheckForLeaks() {
EnsureMainThreadIDIsCorrect();
CheckForLeaksParam param;
param.success = false;
- LockThreadRegistry();
- LockAllocator();
- DoStopTheWorld(CheckForLeaksCallback, &param);
- UnlockAllocator();
- UnlockThreadRegistry();
+ LockStuffAndStopTheWorld(CheckForLeaksCallback, &param);
if (!param.success) {
Report("LeakSanitizer has encountered a fatal error.\n");
@@ -794,7 +790,7 @@ void EnableInThisThread() { }
}
#endif // CAN_SANITIZE_LEAKS
-using namespace __lsan; // NOLINT
+using namespace __lsan;
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
diff --git a/libsanitizer/lsan/lsan_common.h b/libsanitizer/lsan/lsan_common.h
index 58dc00faaee..d24abe31b71 100644
--- a/libsanitizer/lsan/lsan_common.h
+++ b/libsanitizer/lsan/lsan_common.h
@@ -129,8 +129,9 @@ struct RootRegion {
InternalMmapVector<RootRegion> const *GetRootRegions();
void ScanRootRegion(Frontier *frontier, RootRegion const &region,
uptr region_begin, uptr region_end, bool is_readable);
-// Run stoptheworld while holding any platform-specific locks.
-void DoStopTheWorld(StopTheWorldCallback callback, void* argument);
+// Run stoptheworld while holding any platform-specific locks, as well as the
+// allocator and thread registry locks.
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void* argument);
void ScanRangeForPointers(uptr begin, uptr end,
Frontier *frontier,
diff --git a/libsanitizer/lsan/lsan_common_linux.cpp b/libsanitizer/lsan/lsan_common_linux.cpp
index 9ce27a983b5..ea1a4a2f569 100644
--- a/libsanitizer/lsan/lsan_common_linux.cpp
+++ b/libsanitizer/lsan/lsan_common_linux.cpp
@@ -115,10 +115,14 @@ void HandleLeaks() {
if (common_flags()->exitcode) Die();
}
-static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
- void *data) {
+static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
+ size_t size, void *data) {
+ LockThreadRegistry();
+ LockAllocator();
DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
StopTheWorld(param->callback, param->argument);
+ UnlockAllocator();
+ UnlockThreadRegistry();
return 1;
}
@@ -130,9 +134,9 @@ static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
// while holding the libdl lock in the parent thread, we can safely reenter it
// in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
// callback in the parent thread.
-void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
DoStopTheWorldParam param = {callback, argument};
- dl_iterate_phdr(DoStopTheWorldCallback, &param);
+ dl_iterate_phdr(LockStuffAndStopTheWorldCallback, &param);
}
} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan_common_mac.cpp b/libsanitizer/lsan/lsan_common_mac.cpp
index 5204a6624ed..c1804e93c11 100644
--- a/libsanitizer/lsan/lsan_common_mac.cpp
+++ b/libsanitizer/lsan/lsan_common_mac.cpp
@@ -193,8 +193,12 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {
// causes rare race conditions.
void HandleLeaks() {}
-void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
+ LockThreadRegistry();
+ LockAllocator();
StopTheWorld(callback, argument);
+ UnlockAllocator();
+ UnlockThreadRegistry();
}
} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan_interceptors.cpp b/libsanitizer/lsan/lsan_interceptors.cpp
index f06d5fff706..f642bb807bc 100644
--- a/libsanitizer/lsan/lsan_interceptors.cpp
+++ b/libsanitizer/lsan/lsan_interceptors.cpp
@@ -345,6 +345,55 @@ INTERCEPTOR(void, thr_exit, tid_t *state) {
#define LSAN_MAYBE_INTERCEPT_THR_EXIT
#endif
+#if SANITIZER_INTERCEPT___CXA_ATEXIT
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+ void *dso_handle) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ return REAL(__cxa_atexit)(func, arg, dso_handle);
+}
+#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
+#else
+#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
+#endif
+
+#if SANITIZER_INTERCEPT_ATEXIT
+INTERCEPTOR(int, atexit, void (*f)()) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
+}
+#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
+#else
+#define LSAN_MAYBE_INTERCEPT_ATEXIT
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATFORK
+extern "C" {
+extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
+ void (*child)());
+};
+
+INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
+ void (*child)()) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ // REAL(pthread_atfork) cannot be called due to symbol indirections at least
+ // on NetBSD
+ return _pthread_atfork(prepare, parent, child);
+}
+#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
+#else
+#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR
+INTERCEPTOR(char *, strerror, int errnum) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ return REAL(strerror)(errnum);
+}
+#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
+#else
+#define LSAN_MAYBE_INTERCEPT_STRERROR
+#endif
+
struct ThreadParam {
void *(*callback)(void *arg);
void *param;
@@ -454,6 +503,12 @@ void InitializeInterceptors() {
LSAN_MAYBE_INTERCEPT__LWP_EXIT;
LSAN_MAYBE_INTERCEPT_THR_EXIT;
+ LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
+ LSAN_MAYBE_INTERCEPT_ATEXIT;
+ LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
+
+ LSAN_MAYBE_INTERCEPT_STRERROR;
+
#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
Report("LeakSanitizer: failed to create thread key.\n");
diff --git a/libsanitizer/lsan/lsan_mac.cpp b/libsanitizer/lsan/lsan_mac.cpp
index 7bcd9c828ef..b96893e2801 100644
--- a/libsanitizer/lsan/lsan_mac.cpp
+++ b/libsanitizer/lsan/lsan_mac.cpp
@@ -90,7 +90,7 @@ extern "C" void lsan_dispatch_call_block_and_release(void *block) {
} // namespace __lsan
-using namespace __lsan; // NOLINT
+using namespace __lsan;
// Wrap |ctxt| and |func| into an lsan_block_context_t.
// The caller retains control of the allocated context.