diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 7c4d23a6a0d7..a4bc3d6cff91 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -3085,6 +3085,10 @@ void InitializeInterceptors() { #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 c83efec8eaca..d8be21284b93 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -679,6 +679,12 @@ void CheckUnwind() { 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 4dc5e630c524..0be53599b6a4 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 51a98e2f2d5e..0820bf1adee4 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 }