[compiler-rt] [tsan] Don't symbolize stack traces if dl_iterate_phdr is not ready (PR #143199)
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 6 13:22:40 PDT 2025
https://github.com/thurstond created https://github.com/llvm/llvm-project/pull/143199
When a CHECK() fails during TSan initialization, it may segfault (e.g., https://github.com/google/sanitizers/issues/837#issuecomment-2939267531). This is because a failed CHECK() will attempt to print a symbolized stack trace, which requires dl_iterate_phdr, for which the interceptor may not yet be set up.
This patch fixes the issue by not symbolizing the stack trace if the dl_iterate_phdr interceptor is not ready.
>From 6eaf4632a21aa8ad8ba526b3810a360f0811bcba Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 6 Jun 2025 20:06:29 +0000
Subject: [PATCH 1/2] [NFCI][tsan] Don't symbolize stack traces if
dl_iterate_phdr is not ready
When a CHECK() fails before TSan is fully initialized, it may segfault
(e.g., https://github.com/google/sanitizers/issues/837#issuecomment-2939267531). This is because a failed CHECK() will attempt to print a symbolized stack trace, which requires dl_iterate_phdr, for which the interceptor is not yet set up.
This patch fixes the issue by not symbolizing the stack trace if
the dl_iterate_phdr interceptor is not ready.
---
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp | 5 +++++
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp | 7 +++++++
compiler-rt/lib/tsan/rtl/tsan_rtl.h | 2 ++
compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp | 11 ++++++++++-
4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 7c4d23a6a0d74..3565e50892ecf 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -3082,9 +3082,14 @@ void InitializeInterceptors() {
#if SANITIZER_LINUX
TSAN_INTERCEPT(clone);
#endif
+
#if !SANITIZER_ANDROID
TSAN_INTERCEPT(dl_iterate_phdr);
#endif
+
+ // Symbolization indirectly calls dl_iterate_phdr
+ ready_to_symbolize = true;
+
TSAN_MAYBE_INTERCEPT_ON_EXIT;
TSAN_INTERCEPT(__cxa_atexit);
TSAN_INTERCEPT(_exit);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index c83efec8eaca2..00f113834b4af 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -673,12 +673,19 @@ void CheckUnwind() {
thr->ignore_reads_and_writes++;
atomic_store_relaxed(&thr->in_signal_handler, 0);
#endif
+
PrintCurrentStack(StackTrace::GetCurrentPc(),
common_flags()->fast_unwind_on_fatal);
}
bool is_initialized;
+// Symbolization indirectly calls dl_iterate_phdr. If a CHECK() fails early on
+// (prior to the dl_iterate_phdr interceptor setup), resulting in an attempted
+// symbolization, it will segfault.
+// dl_iterate_phdr is not intercepted for Android.
+bool ready_to_symbolize = SANITIZER_ANDROID;
+
void Initialize(ThreadState *thr) {
// Thread safe because done before all threads exist.
if (is_initialized)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index 4dc5e630c5249..0be53599b6a49 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -54,6 +54,8 @@
namespace __tsan {
+extern bool ready_to_symbolize;
+
#if !SANITIZER_GO
struct MapUnmapCallback;
# if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
index 51a98e2f2d5e7..0820bf1adee43 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
@@ -846,7 +846,16 @@ ALWAYS_INLINE USED void PrintCurrentStack(uptr pc, bool fast) {
ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
ptrace->trace_buffer[ptrace->size - i - 1] = tmp;
}
- PrintStack(SymbolizeStack(*ptrace));
+
+ if (ready_to_symbolize) {
+ PrintStack(SymbolizeStack(*ptrace));
+ } else {
+ Printf(
+ "WARNING: PrintCurrentStack() has been called too early, before "
+ "symbolization is possible. Printing unsymbolized stack trace:\n");
+ for (unsigned int i = 0; i < ptrace->size; i++)
+ Printf(" #%u: 0x%zx\n", i, ptrace->trace[i]);
+ }
#endif
}
>From 8c705231b843274dd99e7f14255fac9c4dff46a6 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 6 Jun 2025 20:21:15 +0000
Subject: [PATCH 2/2] Revert newlines
---
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp | 1 -
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp | 1 -
2 files changed, 2 deletions(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 3565e50892ecf..a4bc3d6cff91a 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -3082,7 +3082,6 @@ void InitializeInterceptors() {
#if SANITIZER_LINUX
TSAN_INTERCEPT(clone);
#endif
-
#if !SANITIZER_ANDROID
TSAN_INTERCEPT(dl_iterate_phdr);
#endif
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index 00f113834b4af..d8be21284b934 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -673,7 +673,6 @@ void CheckUnwind() {
thr->ignore_reads_and_writes++;
atomic_store_relaxed(&thr->in_signal_handler, 0);
#endif
-
PrintCurrentStack(StackTrace::GetCurrentPc(),
common_flags()->fast_unwind_on_fatal);
}
More information about the llvm-commits
mailing list