Index: lib/sanitizer_common/sanitizer_symbolizer.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.h +++ lib/sanitizer_common/sanitizer_symbolizer.h @@ -73,6 +73,8 @@ void Clear(); }; +class SymbolizerTool; + class Symbolizer { public: /// Initialize and return platform-specific implementation of symbolizer @@ -80,16 +82,10 @@ static Symbolizer *GetOrInit(); // Returns a list of symbolized frames for a given address (containing // all inlined functions, if necessary). - virtual SymbolizedStack *SymbolizePC(uptr address) { - return SymbolizedStack::New(address); - } - virtual bool SymbolizeData(uptr address, DataInfo *info) { - return false; - } - virtual bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, - uptr *module_address) { - return false; - } + SymbolizedStack *SymbolizePC(uptr address); + bool SymbolizeData(uptr address, DataInfo *info); + bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, + uptr *module_address); const char *GetModuleNameForPc(uptr pc) { const char *module_name = 0; uptr unused; @@ -97,16 +93,12 @@ return module_name; return nullptr; } - virtual bool CanReturnFileLineInfo() { - return false; - } + bool CanReturnFileLineInfo() { return !tools_.empty(); } // Release internal caches (if any). - virtual void Flush() {} + void Flush(); // Attempts to demangle the provided C++ mangled name. - virtual const char *Demangle(const char *name) { - return name; - } - virtual void PrepareForSandboxing() {} + const char *Demangle(const char *name); + 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 @@ -121,14 +113,28 @@ private: /// Platform-specific function for creating a Symbolizer object. static Symbolizer *PlatformInit(); - /// Initialize the symbolizer in a disabled state. Not thread safe. - static Symbolizer *Disable(); + + virtual bool PlatformFindModuleNameAndOffsetForAddress( + uptr address, const char **module_name, uptr *module_offset) { + UNIMPLEMENTED(); + } + // Platform-specific default demangler, must not return nullptr. + virtual const char *PlatformDemangle(const char *name) { UNIMPLEMENTED(); } + virtual void PlatformPrepareForSandboxing() { UNIMPLEMENTED(); } static Symbolizer *symbolizer_; static StaticSpinMutex init_mu_; + // Mutex locked from public methods of |Symbolizer|, so that the internals + // (including individual symbolizer tools and platform-specific methods) are + // always synchronized. + BlockingMutex mu_; + + typedef IntrusiveList::Iterator Iterator; + IntrusiveList tools_; + protected: - Symbolizer(); + explicit Symbolizer(IntrusiveList tools); static LowLevelAllocator symbolizer_allocator_; Index: lib/sanitizer_common/sanitizer_symbolizer.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.cc +++ lib/sanitizer_common/sanitizer_symbolizer.cc @@ -16,7 +16,7 @@ #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" #include "sanitizer_placement_new.h" -#include "sanitizer_symbolizer.h" +#include "sanitizer_symbolizer_internal.h" namespace __sanitizer { @@ -68,13 +68,6 @@ StaticSpinMutex Symbolizer::init_mu_; LowLevelAllocator Symbolizer::symbolizer_allocator_; -Symbolizer *Symbolizer::Disable() { - CHECK_EQ(0, symbolizer_); - // Initialize a dummy symbolizer. - symbolizer_ = new(symbolizer_allocator_) Symbolizer; - return symbolizer_; -} - void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook, Symbolizer::EndSymbolizationHook end_hook) { CHECK(start_hook_ == 0 && end_hook_ == 0); @@ -82,7 +75,8 @@ end_hook_ = end_hook; } -Symbolizer::Symbolizer() : start_hook_(0), end_hook_(0) {} +Symbolizer::Symbolizer(IntrusiveList tools) + : tools_(tools), start_hook_(0), end_hook_(0) {} Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym) : sym_(sym) { @@ -95,4 +89,76 @@ sym_->end_hook_(); } +SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { + BlockingMutexLock l(&mu_); + const char *module_name; + uptr module_offset; + SymbolizedStack *res = SymbolizedStack::New(addr); + if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name, + &module_offset)) + return res; + // Always fill data about module name and offset. + res->info.FillModuleInfo(module_name, module_offset); + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + if (tool->SymbolizePC(addr, res)) { + return res; + } + } + return res; +} + +bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { + BlockingMutexLock l(&mu_); + const char *module_name; + uptr module_offset; + if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name, + &module_offset)) + return false; + info->Clear(); + info->module = internal_strdup(module_name); + info->module_offset = module_offset; + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + if (tool->SymbolizeData(addr, info)) { + return true; + } + } + return true; +} + +bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, + uptr *module_address) { + BlockingMutexLock l(&mu_); + return PlatformFindModuleNameAndOffsetForAddress(pc, module_name, + module_address); +} + +void Symbolizer::Flush() { + BlockingMutexLock l(&mu_); + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + tool->Flush(); + } +} + +const char *Symbolizer::Demangle(const char *name) { + BlockingMutexLock l(&mu_); + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + if (const char *demangled = tool->Demangle(name)) + return demangled; + } + return PlatformDemangle(name); +} + +void Symbolizer::PrepareForSandboxing() { + BlockingMutexLock l(&mu_); + PlatformPrepareForSandboxing(); +} + } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_symbolizer_internal.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_internal.h +++ lib/sanitizer_common/sanitizer_symbolizer_internal.h @@ -31,9 +31,9 @@ // Windows DbgHelp symbolizer, etc.). class SymbolizerTool { public: - // POSIXSymbolizer implements a "fallback chain" of symbolizer tools. In a - // request to symbolize an address, if one tool returns false, the next tool - // in the chain will be tried. + // The main |Symbolizer| class implements a "fallback chain" of symbolizer + // tools. In a request to symbolize an address, if one tool returns false, + // the next tool in the chain will be tried. SymbolizerTool *next; SymbolizerTool() : next(nullptr) { } @@ -56,7 +56,7 @@ virtual void Flush() {} - // Return nullptr to fallback to the default __cxxabiv1 demangler. + // Return nullptr to fallback to the default platform-specific demangler. virtual const char *Demangle(const char *name) { return nullptr; } Index: lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -51,9 +51,9 @@ SpinMutexLock l(&init_mu_); if (symbolizer_) return symbolizer_; - if ((symbolizer_ = PlatformInit())) - return symbolizer_; - return Disable(); + symbolizer_ = PlatformInit(); + CHECK(symbolizer_); + return symbolizer_; } } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -351,88 +351,21 @@ class POSIXSymbolizer : public Symbolizer { public: explicit POSIXSymbolizer(IntrusiveList tools) - : Symbolizer(), tools_(tools) {} + : Symbolizer(tools) {} - SymbolizedStack *SymbolizePC(uptr addr) override { - BlockingMutexLock l(&mu_); - const char *module_name; - uptr module_offset; - SymbolizedStack *res = SymbolizedStack::New(addr); - if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) - return res; - // Always fill data about module name and offset. - res->info.FillModuleInfo(module_name, module_offset); - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - if (tool->SymbolizePC(addr, res)) { - return res; - } - } - return res; - } - - bool SymbolizeData(uptr addr, DataInfo *info) override { - BlockingMutexLock l(&mu_); - LoadedModule *module = FindModuleForAddress(addr); - if (module == 0) - return false; - const char *module_name = module->full_name(); - uptr module_offset = addr - module->base_address(); - info->Clear(); - info->module = internal_strdup(module_name); - info->module_offset = module_offset; - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - if (tool->SymbolizeData(addr, info)) { - return true; - } - } - return true; - } - - bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, - uptr *module_address) override { - BlockingMutexLock l(&mu_); - return FindModuleNameAndOffsetForAddress(pc, module_name, module_address); - } - - bool CanReturnFileLineInfo() override { - return !tools_.empty(); - } - - void Flush() override { - BlockingMutexLock l(&mu_); - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - tool->Flush(); - } - } - - const char *Demangle(const char *name) override { - BlockingMutexLock l(&mu_); - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - if (const char *demangled = tool->Demangle(name)) - return demangled; - } + private: + const char *PlatformDemangle(const char *name) override { return DemangleCXXABI(name); } - void PrepareForSandboxing() override { + void PlatformPrepareForSandboxing() override { #if SANITIZER_LINUX && !SANITIZER_ANDROID - BlockingMutexLock l(&mu_); // Cache /proc/self/exe on Linux. CacheBinaryName(); #endif } - private: LoadedModule *FindModuleForAddress(uptr address) { - mu_.CheckLocked(); bool modules_were_reloaded = false; if (modules_ == 0 || !modules_fresh_) { modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate( @@ -461,9 +394,9 @@ return 0; } - bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name, - uptr *module_offset) { - mu_.CheckLocked(); + bool PlatformFindModuleNameAndOffsetForAddress(uptr address, + const char **module_name, + uptr *module_offset) override { LoadedModule *module = FindModuleForAddress(address); if (module == 0) return false; @@ -478,10 +411,6 @@ uptr n_modules_; // If stale, need to reload the modules before looking up addresses. bool modules_fresh_; - BlockingMutex mu_; - - typedef IntrusiveList::Iterator Iterator; - IntrusiveList tools_; }; static SymbolizerTool *ChooseSymbolizer(LowLevelAllocator *allocator) { Index: lib/sanitizer_common/sanitizer_symbolizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -147,42 +147,24 @@ // TODO(kuba.brecka): To be merged with POSIXSymbolizer. class WinSymbolizer : public Symbolizer { public: - explicit WinSymbolizer(SymbolizerTool *tool) : Symbolizer(), tool_(tool) { - CHECK(tool); - } - SymbolizedStack *SymbolizePC(uptr addr) override { - BlockingMutexLock l(&mu_); - const char *module_name; - uptr module_offset; - SymbolizedStack *res = SymbolizedStack::New(addr); - if (FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) - res->info.FillModuleInfo(module_name, module_offset); - tool_->SymbolizePC(addr, res); - return res; - } - bool CanReturnFileLineInfo() override { - return true; - } - const char *Demangle(const char *name) override { - BlockingMutexLock l(&mu_); - return tool_->Demangle(name); - } - bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, - uptr *module_address) override { - BlockingMutexLock l(&mu_); - return FindModuleNameAndOffsetForAddress(pc, module_name, module_address); - } + explicit WinSymbolizer(IntrusiveList tools) + : Symbolizer(tools) {} - BlockingMutex mu_; - SymbolizerTool *tool_; + private: + bool PlatformFindModuleNameAndOffsetForAddress( + uptr addr, const char **module_name, uptr *module_offset) override { + return ::FindModuleNameAndOffsetForAddress(addr, module_name, + module_offset); + } + const char *PlatformDemangle(const char *name) override { return name; } + void PlatformPrepareForSandboxing() override { } }; Symbolizer *Symbolizer::PlatformInit() { - static bool called_once = false; - CHECK(!called_once && "Shouldn't create more than one symbolizer"); - called_once = true; - SymbolizerTool *tool = new(symbolizer_allocator_) WinSymbolizerTool(); - return new(symbolizer_allocator_) WinSymbolizer(tool); + IntrusiveList list; + list.clear(); + list.push_back(new(symbolizer_allocator_) WinSymbolizerTool()); + return new(symbolizer_allocator_) WinSymbolizer(list); } } // namespace __sanitizer