forked from OSchip/llvm-project
Symbolizer refactoring: Merge common parts of POSIXSymbolizer and WinSymbolizer
Reviewed at http://reviews.llvm.org/D8105 llvm-svn: 231680
This commit is contained in:
parent
37dce44f73
commit
ae219d3d3c
|
|
@ -16,7 +16,7 @@
|
||||||
#include "sanitizer_internal_defs.h"
|
#include "sanitizer_internal_defs.h"
|
||||||
#include "sanitizer_libc.h"
|
#include "sanitizer_libc.h"
|
||||||
#include "sanitizer_placement_new.h"
|
#include "sanitizer_placement_new.h"
|
||||||
#include "sanitizer_symbolizer.h"
|
#include "sanitizer_symbolizer_internal.h"
|
||||||
|
|
||||||
namespace __sanitizer {
|
namespace __sanitizer {
|
||||||
|
|
||||||
|
|
@ -68,13 +68,6 @@ Symbolizer *Symbolizer::symbolizer_;
|
||||||
StaticSpinMutex Symbolizer::init_mu_;
|
StaticSpinMutex Symbolizer::init_mu_;
|
||||||
LowLevelAllocator Symbolizer::symbolizer_allocator_;
|
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,
|
void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
|
||||||
Symbolizer::EndSymbolizationHook end_hook) {
|
Symbolizer::EndSymbolizationHook end_hook) {
|
||||||
CHECK(start_hook_ == 0 && end_hook_ == 0);
|
CHECK(start_hook_ == 0 && end_hook_ == 0);
|
||||||
|
|
@ -82,7 +75,8 @@ void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
|
||||||
end_hook_ = end_hook;
|
end_hook_ = end_hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbolizer::Symbolizer() : start_hook_(0), end_hook_(0) {}
|
Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
|
||||||
|
: tools_(tools), start_hook_(0), end_hook_(0) {}
|
||||||
|
|
||||||
Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
|
Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
|
||||||
: sym_(sym) {
|
: sym_(sym) {
|
||||||
|
|
@ -95,4 +89,76 @@ Symbolizer::SymbolizerScope::~SymbolizerScope() {
|
||||||
sym_->end_hook_();
|
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
|
} // namespace __sanitizer
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,8 @@ struct DataInfo {
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SymbolizerTool;
|
||||||
|
|
||||||
class Symbolizer {
|
class Symbolizer {
|
||||||
public:
|
public:
|
||||||
/// Initialize and return platform-specific implementation of symbolizer
|
/// Initialize and return platform-specific implementation of symbolizer
|
||||||
|
|
@ -80,16 +82,10 @@ class Symbolizer {
|
||||||
static Symbolizer *GetOrInit();
|
static Symbolizer *GetOrInit();
|
||||||
// Returns a list of symbolized frames for a given address (containing
|
// Returns a list of symbolized frames for a given address (containing
|
||||||
// all inlined functions, if necessary).
|
// all inlined functions, if necessary).
|
||||||
virtual SymbolizedStack *SymbolizePC(uptr address) {
|
SymbolizedStack *SymbolizePC(uptr address);
|
||||||
return SymbolizedStack::New(address);
|
bool SymbolizeData(uptr address, DataInfo *info);
|
||||||
}
|
bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
|
||||||
virtual bool SymbolizeData(uptr address, DataInfo *info) {
|
uptr *module_address);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
|
|
||||||
uptr *module_address) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const char *GetModuleNameForPc(uptr pc) {
|
const char *GetModuleNameForPc(uptr pc) {
|
||||||
const char *module_name = 0;
|
const char *module_name = 0;
|
||||||
uptr unused;
|
uptr unused;
|
||||||
|
|
@ -97,16 +93,12 @@ class Symbolizer {
|
||||||
return module_name;
|
return module_name;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
virtual bool CanReturnFileLineInfo() {
|
bool CanReturnFileLineInfo() { return !tools_.empty(); }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Release internal caches (if any).
|
// Release internal caches (if any).
|
||||||
virtual void Flush() {}
|
void Flush();
|
||||||
// Attempts to demangle the provided C++ mangled name.
|
// Attempts to demangle the provided C++ mangled name.
|
||||||
virtual const char *Demangle(const char *name) {
|
const char *Demangle(const char *name);
|
||||||
return name;
|
void PrepareForSandboxing();
|
||||||
}
|
|
||||||
virtual void PrepareForSandboxing() {}
|
|
||||||
|
|
||||||
// Allow user to install hooks that would be called before/after Symbolizer
|
// Allow user to install hooks that would be called before/after Symbolizer
|
||||||
// does the actual file/line info fetching. Specific sanitizers may need this
|
// does the actual file/line info fetching. Specific sanitizers may need this
|
||||||
|
|
@ -121,14 +113,28 @@ class Symbolizer {
|
||||||
private:
|
private:
|
||||||
/// Platform-specific function for creating a Symbolizer object.
|
/// Platform-specific function for creating a Symbolizer object.
|
||||||
static Symbolizer *PlatformInit();
|
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 Symbolizer *symbolizer_;
|
||||||
static StaticSpinMutex init_mu_;
|
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<SymbolizerTool>::Iterator Iterator;
|
||||||
|
IntrusiveList<SymbolizerTool> tools_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Symbolizer();
|
explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
|
||||||
|
|
||||||
static LowLevelAllocator symbolizer_allocator_;
|
static LowLevelAllocator symbolizer_allocator_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@ const char *ExtractUptr(const char *str, const char *delims, uptr *result);
|
||||||
// Windows DbgHelp symbolizer, etc.).
|
// Windows DbgHelp symbolizer, etc.).
|
||||||
class SymbolizerTool {
|
class SymbolizerTool {
|
||||||
public:
|
public:
|
||||||
// POSIXSymbolizer implements a "fallback chain" of symbolizer tools. In a
|
// The main |Symbolizer| class implements a "fallback chain" of symbolizer
|
||||||
// request to symbolize an address, if one tool returns false, the next tool
|
// tools. In a request to symbolize an address, if one tool returns false,
|
||||||
// in the chain will be tried.
|
// the next tool in the chain will be tried.
|
||||||
SymbolizerTool *next;
|
SymbolizerTool *next;
|
||||||
|
|
||||||
SymbolizerTool() : next(nullptr) { }
|
SymbolizerTool() : next(nullptr) { }
|
||||||
|
|
@ -56,7 +56,7 @@ class SymbolizerTool {
|
||||||
|
|
||||||
virtual void Flush() {}
|
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) {
|
virtual const char *Demangle(const char *name) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ Symbolizer *Symbolizer::GetOrInit() {
|
||||||
SpinMutexLock l(&init_mu_);
|
SpinMutexLock l(&init_mu_);
|
||||||
if (symbolizer_)
|
if (symbolizer_)
|
||||||
return symbolizer_;
|
return symbolizer_;
|
||||||
if ((symbolizer_ = PlatformInit()))
|
symbolizer_ = PlatformInit();
|
||||||
return symbolizer_;
|
CHECK(symbolizer_);
|
||||||
return Disable();
|
return symbolizer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace __sanitizer
|
} // namespace __sanitizer
|
||||||
|
|
|
||||||
|
|
@ -351,88 +351,21 @@ class InternalSymbolizer : public SymbolizerTool {
|
||||||
class POSIXSymbolizer : public Symbolizer {
|
class POSIXSymbolizer : public Symbolizer {
|
||||||
public:
|
public:
|
||||||
explicit POSIXSymbolizer(IntrusiveList<SymbolizerTool> tools)
|
explicit POSIXSymbolizer(IntrusiveList<SymbolizerTool> tools)
|
||||||
: Symbolizer(), tools_(tools) {}
|
: Symbolizer(tools) {}
|
||||||
|
|
||||||
SymbolizedStack *SymbolizePC(uptr addr) override {
|
private:
|
||||||
BlockingMutexLock l(&mu_);
|
const char *PlatformDemangle(const char *name) override {
|
||||||
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;
|
|
||||||
}
|
|
||||||
return DemangleCXXABI(name);
|
return DemangleCXXABI(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareForSandboxing() override {
|
void PlatformPrepareForSandboxing() override {
|
||||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||||
BlockingMutexLock l(&mu_);
|
|
||||||
// Cache /proc/self/exe on Linux.
|
// Cache /proc/self/exe on Linux.
|
||||||
CacheBinaryName();
|
CacheBinaryName();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
LoadedModule *FindModuleForAddress(uptr address) {
|
LoadedModule *FindModuleForAddress(uptr address) {
|
||||||
mu_.CheckLocked();
|
|
||||||
bool modules_were_reloaded = false;
|
bool modules_were_reloaded = false;
|
||||||
if (modules_ == 0 || !modules_fresh_) {
|
if (modules_ == 0 || !modules_fresh_) {
|
||||||
modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate(
|
modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate(
|
||||||
|
|
@ -461,9 +394,9 @@ class POSIXSymbolizer : public Symbolizer {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
|
bool PlatformFindModuleNameAndOffsetForAddress(uptr address,
|
||||||
uptr *module_offset) {
|
const char **module_name,
|
||||||
mu_.CheckLocked();
|
uptr *module_offset) override {
|
||||||
LoadedModule *module = FindModuleForAddress(address);
|
LoadedModule *module = FindModuleForAddress(address);
|
||||||
if (module == 0)
|
if (module == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -478,10 +411,6 @@ class POSIXSymbolizer : public Symbolizer {
|
||||||
uptr n_modules_;
|
uptr n_modules_;
|
||||||
// If stale, need to reload the modules before looking up addresses.
|
// If stale, need to reload the modules before looking up addresses.
|
||||||
bool modules_fresh_;
|
bool modules_fresh_;
|
||||||
BlockingMutex mu_;
|
|
||||||
|
|
||||||
typedef IntrusiveList<SymbolizerTool>::Iterator Iterator;
|
|
||||||
IntrusiveList<SymbolizerTool> tools_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static SymbolizerTool *ChooseSymbolizer(LowLevelAllocator *allocator) {
|
static SymbolizerTool *ChooseSymbolizer(LowLevelAllocator *allocator) {
|
||||||
|
|
|
||||||
|
|
@ -147,42 +147,24 @@ bool FindModuleNameAndOffsetForAddress(uptr addr, const char **module_name,
|
||||||
// TODO(kuba.brecka): To be merged with POSIXSymbolizer.
|
// TODO(kuba.brecka): To be merged with POSIXSymbolizer.
|
||||||
class WinSymbolizer : public Symbolizer {
|
class WinSymbolizer : public Symbolizer {
|
||||||
public:
|
public:
|
||||||
explicit WinSymbolizer(SymbolizerTool *tool) : Symbolizer(), tool_(tool) {
|
explicit WinSymbolizer(IntrusiveList<SymbolizerTool> tools)
|
||||||
CHECK(tool);
|
: 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))
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockingMutex mu_;
|
private:
|
||||||
SymbolizerTool *tool_;
|
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() {
|
Symbolizer *Symbolizer::PlatformInit() {
|
||||||
static bool called_once = false;
|
IntrusiveList<SymbolizerTool> list;
|
||||||
CHECK(!called_once && "Shouldn't create more than one symbolizer");
|
list.clear();
|
||||||
called_once = true;
|
list.push_back(new(symbolizer_allocator_) WinSymbolizerTool());
|
||||||
SymbolizerTool *tool = new(symbolizer_allocator_) WinSymbolizerTool();
|
return new(symbolizer_allocator_) WinSymbolizer(list);
|
||||||
return new(symbolizer_allocator_) WinSymbolizer(tool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace __sanitizer
|
} // namespace __sanitizer
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue