From 66d91e3356a0c4d7aff3beaaaff3e87bbaec805c Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Thu, 31 Oct 2013 21:44:07 +0000 Subject: [Sanitizer] Add Symbolizer::AddHooks() and use it in TSan and MSan. Summary: TSan and MSan need to know if interceptor was called by the user code or by the symbolizer and use pre- and post-symbolization hooks for that. Make Symbolizer class responsible for calling these hooks instead. This would ensure the hooks are only called when necessary (during in-process symbolization, they are not needed for out-of-process) and save specific sanitizers from tracing all places in the code where symbolization will be performed. Reviewers: eugenis, dvyukov Reviewed By: eugenis CC: llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D2067 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@193807 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/msan/msan.cc | 1 + lib/msan/msan_report.cc | 6 +----- lib/sanitizer_common/sanitizer_symbolizer.cc | 20 +++++++++++++++++ lib/sanitizer_common/sanitizer_symbolizer.h | 22 +++++++++++++++++++ .../sanitizer_symbolizer_posix_libcdep.cc | 11 ++++++++-- lib/tsan/rtl/tsan_rtl.cc | 1 + lib/tsan/rtl/tsan_symbolize.cc | 25 +++++++++------------- lib/tsan/rtl/tsan_symbolize.h | 2 ++ 8 files changed, 66 insertions(+), 22 deletions(-) diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc index 8d2c5ec9..694733b7 100644 --- a/lib/msan/msan.cc +++ b/lib/msan/msan.cc @@ -337,6 +337,7 @@ void __msan_init() { if (external_symbolizer && external_symbolizer[0]) { CHECK(external_symbolizer_started); } + Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer); GetThreadStackTopAndBottom(/* at_initialization */true, &__msan_stack_bounds.stack_top, diff --git a/lib/msan/msan_report.cc b/lib/msan/msan_report.cc index a629304e..bb591ebd 100644 --- a/lib/msan/msan_report.cc +++ b/lib/msan/msan_report.cc @@ -35,7 +35,6 @@ class Decorator: private __sanitizer::AnsiColorDecorator { }; static void PrintStack(const uptr *trace, uptr size) { - SymbolizerScope sym_scope; StackTrace::PrintStack(trace, size); Printf("\n"); } @@ -76,10 +75,7 @@ static void ReportSummary(const char *error_type, StackTrace *stack) { if (!stack->size || !Symbolizer::Get()->IsAvailable()) return; AddressInfo ai; uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); - { - SymbolizerScope sym_scope; - Symbolizer::Get()->SymbolizeCode(pc, &ai, 1); - } + Symbolizer::Get()->SymbolizeCode(pc, &ai, 1); ReportErrorSummary(error_type, ai.file, ai.line, ai.function); } diff --git a/lib/sanitizer_common/sanitizer_symbolizer.cc b/lib/sanitizer_common/sanitizer_symbolizer.cc index 6bec459b..2290767b 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer.cc @@ -40,4 +40,24 @@ Symbolizer *Symbolizer::Disable() { return symbolizer_; } +void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook, + Symbolizer::EndSymbolizationHook end_hook) { + CHECK(start_hook_ == 0 && end_hook_ == 0); + start_hook_ = start_hook; + end_hook_ = end_hook; +} + +Symbolizer::Symbolizer() : start_hook_(0), end_hook_(0) {} + +Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym) + : sym_(sym) { + if (sym_->start_hook_) + sym_->start_hook_(); +} + +Symbolizer::SymbolizerScope::~SymbolizerScope() { + if (sym_->end_hook_) + sym_->end_hook_(); +} + } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h index f4191328..886fed20 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer.h +++ b/lib/sanitizer_common/sanitizer_symbolizer.h @@ -105,6 +105,16 @@ class Symbolizer { } virtual void PrepareForSandboxing() {} + // Allow user to install hooks that would be called before/after Symbolizer + // does the actual file/line info fetching. Specific sanitizers may need this + // to distinguish system library calls made in user code from calls made + // during in-process symbolization. + typedef void (*StartSymbolizationHook)(); + typedef void (*EndSymbolizationHook)(); + // May be called at most once. + void AddHooks(StartSymbolizationHook start_hook, + EndSymbolizationHook end_hook); + private: /// Platform-specific function for creating a Symbolizer object. static Symbolizer *PlatformInit(const char *path_to_external); @@ -116,7 +126,19 @@ class Symbolizer { static StaticSpinMutex init_mu_; protected: + Symbolizer(); + static LowLevelAllocator symbolizer_allocator_; + + StartSymbolizationHook start_hook_; + EndSymbolizationHook end_hook_; + class SymbolizerScope { + public: + explicit SymbolizerScope(const Symbolizer *sym); + ~SymbolizerScope(); + private: + const Symbolizer *sym_; + }; }; } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index 206de863..de118328 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -368,7 +368,8 @@ class POSIXSymbolizer : public Symbolizer { public: POSIXSymbolizer(ExternalSymbolizer *external_symbolizer, InternalSymbolizer *internal_symbolizer) - : external_symbolizer_(external_symbolizer), + : Symbolizer(), + external_symbolizer_(external_symbolizer), internal_symbolizer_(internal_symbolizer) {} uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) { @@ -463,14 +464,19 @@ class POSIXSymbolizer : public Symbolizer { void Flush() { BlockingMutexLock l(&mu_); - if (internal_symbolizer_ != 0) + if (internal_symbolizer_ != 0) { + SymbolizerScope sym_scope(this); internal_symbolizer_->Flush(); + } if (external_symbolizer_ != 0) external_symbolizer_->Flush(); } const char *Demangle(const char *name) { BlockingMutexLock l(&mu_); + // Run hooks even if we don't use internal symbolizer, as cxxabi + // demangle may call system functions. + SymbolizerScope sym_scope(this); if (internal_symbolizer_ != 0) return internal_symbolizer_->Demangle(name); return DemangleCXXABI(name); @@ -489,6 +495,7 @@ class POSIXSymbolizer : public Symbolizer { mu_.CheckLocked(); // First, try to use internal symbolizer. if (internal_symbolizer_) { + SymbolizerScope sym_scope(this); return internal_symbolizer_->SendCommand(is_data, module_name, module_offset); } diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index fc2aa767..1f66d29a 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -246,6 +246,7 @@ void Initialize(ThreadState *thr) { external_symbolizer); Die(); } + Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer); #endif internal_start_thread(&BackgroundThread, 0); diff --git a/lib/tsan/rtl/tsan_symbolize.cc b/lib/tsan/rtl/tsan_symbolize.cc index a2ed5d05..24c74722 100644 --- a/lib/tsan/rtl/tsan_symbolize.cc +++ b/lib/tsan/rtl/tsan_symbolize.cc @@ -22,19 +22,17 @@ namespace __tsan { -struct ScopedInSymbolizer { - ScopedInSymbolizer() { - ThreadState *thr = cur_thread(); - CHECK(!thr->in_symbolizer); - thr->in_symbolizer = true; - } +void EnterSymbolizer() { + ThreadState *thr = cur_thread(); + CHECK(!thr->in_symbolizer); + thr->in_symbolizer = true; +} - ~ScopedInSymbolizer() { - ThreadState *thr = cur_thread(); - CHECK(thr->in_symbolizer); - thr->in_symbolizer = false; - } -}; +void ExitSymbolizer() { + ThreadState *thr = cur_thread(); + CHECK(thr->in_symbolizer); + thr->in_symbolizer = false; +} ReportStack *NewReportStackEntry(uptr addr) { ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, @@ -121,7 +119,6 @@ ReportStack *SymbolizeCode(uptr addr) { } if (!Symbolizer::Get()->IsAvailable()) return SymbolizeCodeAddr2Line(addr); - ScopedInSymbolizer in_symbolizer; static const uptr kMaxAddrFrames = 16; InternalScopedBuffer addr_frames(kMaxAddrFrames); for (uptr i = 0; i < kMaxAddrFrames; i++) @@ -148,7 +145,6 @@ ReportStack *SymbolizeCode(uptr addr) { ReportLocation *SymbolizeData(uptr addr) { if (!Symbolizer::Get()->IsAvailable()) return 0; - ScopedInSymbolizer in_symbolizer; DataInfo info; if (!Symbolizer::Get()->SymbolizeData(addr, &info)) return 0; @@ -168,7 +164,6 @@ ReportLocation *SymbolizeData(uptr addr) { void SymbolizeFlush() { if (!Symbolizer::Get()->IsAvailable()) return; - ScopedInSymbolizer in_symbolizer; Symbolizer::Get()->Flush(); } diff --git a/lib/tsan/rtl/tsan_symbolize.h b/lib/tsan/rtl/tsan_symbolize.h index 7bc6123d..6282e45b 100644 --- a/lib/tsan/rtl/tsan_symbolize.h +++ b/lib/tsan/rtl/tsan_symbolize.h @@ -18,6 +18,8 @@ namespace __tsan { +void EnterSymbolizer(); +void ExitSymbolizer(); ReportStack *SymbolizeCode(uptr addr); ReportLocation *SymbolizeData(uptr addr); void SymbolizeFlush(); -- cgit v1.2.3