Overhaul the symbolizer interface.

This moves away from creating the symbolizer object and initializing the
external symbolizer as separate steps.  Those steps now always take place
together.

Sanitizers with a legacy requirement to specify their own symbolizer path
should use InitSymbolizer to initialize the symbolizer with the desired
path, and GetSymbolizer to access the symbolizer.  Sanitizers with no
such requirement (e.g. UBSan) can use GetOrInitSymbolizer with no need for
initialization.

The symbolizer interface has been made thread-safe (as far as I can
tell) by protecting its member functions with mutexes.

Finally, the symbolizer interface no longer relies on weak externals, the
introduction of which was probably a mistake on my part.

Differential Revision: http://llvm-reviews.chandlerc.com/D1985

llvm-svn: 193448
This commit is contained in:
Peter Collingbourne 2013-10-25 23:03:29 +00:00
parent 8d27910d7d
commit 791e65dcfb
21 changed files with 206 additions and 103 deletions

View File

@ -137,8 +137,6 @@ endif()
add_compiler_rt_resource_file(asan_blacklist asan_blacklist.txt) add_compiler_rt_resource_file(asan_blacklist asan_blacklist.txt)
add_custom_target(asan DEPENDS asan_blacklist ${ASAN_RUNTIME_LIBRARIES})
if(LLVM_INCLUDE_TESTS) if(LLVM_INCLUDE_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()

View File

@ -181,8 +181,8 @@ static bool IsASCII(unsigned char c) {
static const char *MaybeDemangleGlobalName(const char *name) { static const char *MaybeDemangleGlobalName(const char *name) {
// We can spoil names of globals with C linkage, so use an heuristic // We can spoil names of globals with C linkage, so use an heuristic
// approach to check if the name should be demangled. // approach to check if the name should be demangled.
return (name[0] == '_' && name[1] == 'Z' && &getSymbolizer) return (name[0] == '_' && name[1] == 'Z')
? getSymbolizer()->Demangle(name) ? Symbolizer::Get()->Demangle(name)
: name; : name;
} }
@ -551,11 +551,11 @@ class ScopedInErrorReport {
static void ReportSummary(const char *error_type, StackTrace *stack) { static void ReportSummary(const char *error_type, StackTrace *stack) {
AddressInfo ai; AddressInfo ai;
if (&getSymbolizer && getSymbolizer()->IsAvailable()) { if (Symbolizer::Get()->IsAvailable()) {
// Currently, we include the first stack frame into the report summary. // Currently, we include the first stack frame into the report summary.
// Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
getSymbolizer()->SymbolizeCode(pc, &ai, 1); Symbolizer::Get()->SymbolizeCode(pc, &ai, 1);
} }
ReportErrorSummary(error_type, ai.file, ai.line, ai.function); ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
} }

View File

@ -536,9 +536,10 @@ void __asan_init() {
InitializeAllocator(); InitializeAllocator();
// Start symbolizer process if necessary. // Start symbolizer process if necessary.
if (common_flags()->symbolize && &getSymbolizer) { if (common_flags()->symbolize) {
getSymbolizer() Symbolizer::Init(common_flags()->external_symbolizer_path);
->InitializeExternal(common_flags()->external_symbolizer_path); } else {
Symbolizer::Disable();
} }
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited

View File

@ -53,8 +53,9 @@ void Init() {
// Start symbolizer process if necessary. // Start symbolizer process if necessary.
if (common_flags()->symbolize) { if (common_flags()->symbolize) {
getSymbolizer() Symbolizer::Init(common_flags()->external_symbolizer_path);
->InitializeExternal(common_flags()->external_symbolizer_path); } else {
Symbolizer::Disable();
} }
InitCommonLsan(); InitCommonLsan();

View File

@ -413,8 +413,8 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
static const uptr kMaxAddrFrames = 16; static const uptr kMaxAddrFrames = 16;
InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo(); for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
uptr addr_frames_num = uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode(
getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames); addr, addr_frames.data(), kMaxAddrFrames);
for (uptr i = 0; i < addr_frames_num; i++) { for (uptr i = 0; i < addr_frames_num; i++) {
Suppression* s; Suppression* s;
if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) || if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||

View File

@ -331,10 +331,10 @@ void __msan_init() {
} }
const char *external_symbolizer = common_flags()->external_symbolizer_path; const char *external_symbolizer = common_flags()->external_symbolizer_path;
bool symbolizer_started = bool external_symbolizer_started =
getSymbolizer()->InitializeExternal(external_symbolizer); Symbolizer::Init(external_symbolizer)->IsExternalAvailable();
if (external_symbolizer && external_symbolizer[0]) { if (external_symbolizer && external_symbolizer[0]) {
CHECK(symbolizer_started); CHECK(external_symbolizer_started);
} }
GetThreadStackTopAndBottom(/* at_initialization */true, GetThreadStackTopAndBottom(/* at_initialization */true,

View File

@ -54,7 +54,7 @@ static void DescribeOrigin(u32 origin) {
Printf(" %sUninitialized value was created by an allocation of '%s%s%s'" Printf(" %sUninitialized value was created by an allocation of '%s%s%s'"
" in the stack frame of function '%s%s%s'%s\n", " in the stack frame of function '%s%s%s'%s\n",
d.Origin(), d.Name(), s, d.Origin(), d.Name(), d.Origin(), d.Name(), s, d.Origin(), d.Name(),
getSymbolizer()->Demangle(sep + 1), d.Origin(), d.End()); Symbolizer::Get()->Demangle(sep + 1), d.Origin(), d.End());
InternalFree(s); InternalFree(s);
if (pc) { if (pc) {
@ -73,12 +73,12 @@ static void DescribeOrigin(u32 origin) {
} }
static void ReportSummary(const char *error_type, StackTrace *stack) { static void ReportSummary(const char *error_type, StackTrace *stack) {
if (!stack->size || !getSymbolizer()->IsAvailable()) return; if (!stack->size || !Symbolizer::Get()->IsAvailable()) return;
AddressInfo ai; AddressInfo ai;
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
{ {
SymbolizerScope sym_scope; SymbolizerScope sym_scope;
getSymbolizer()->SymbolizeCode(pc, &ai, 1); Symbolizer::Get()->SymbolizeCode(pc, &ai, 1);
} }
ReportErrorSummary(error_type, ai.file, ai.line, ai.function); ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
} }

View File

@ -16,6 +16,7 @@ set(SANITIZER_SOURCES
sanitizer_stackdepot.cc sanitizer_stackdepot.cc
sanitizer_stacktrace.cc sanitizer_stacktrace.cc
sanitizer_suppressions.cc sanitizer_suppressions.cc
sanitizer_symbolizer.cc
sanitizer_symbolizer_win.cc sanitizer_symbolizer_win.cc
sanitizer_thread_registry.cc sanitizer_thread_registry.cc
sanitizer_win.cc) sanitizer_win.cc)
@ -25,6 +26,7 @@ set(SANITIZER_LIBCDEP_SOURCES
sanitizer_linux_libcdep.cc sanitizer_linux_libcdep.cc
sanitizer_posix_libcdep.cc sanitizer_posix_libcdep.cc
sanitizer_stoptheworld_linux_libcdep.cc sanitizer_stoptheworld_linux_libcdep.cc
sanitizer_symbolizer_libcdep.cc
sanitizer_symbolizer_posix_libcdep.cc) sanitizer_symbolizer_posix_libcdep.cc)
# Explicitly list all sanitizer_common headers. Not all of these are # Explicitly list all sanitizer_common headers. Not all of these are

View File

@ -312,7 +312,8 @@ void PrepareForSandboxing() {
MemoryMappingLayout::CacheMemoryMappings(); MemoryMappingLayout::CacheMemoryMappings();
// Same for /proc/self/exe in the symbolizer. // Same for /proc/self/exe in the symbolizer.
#if !SANITIZER_GO #if !SANITIZER_GO
getSymbolizer()->PrepareForSandboxing(); if (Symbolizer *sym = Symbolizer::GetOrNull())
sym->PrepareForSandboxing();
#endif #endif
} }

View File

@ -62,10 +62,11 @@ void StackTrace::PrintStack(const uptr *addr, uptr size, bool symbolize,
frame_num++; frame_num++;
} }
} }
if (symbolize && addr_frames_num == 0 && &getSymbolizer) { if (symbolize && addr_frames_num == 0) {
// Use our own (online) symbolizer, if necessary. // Use our own (online) symbolizer, if necessary.
addr_frames_num = getSymbolizer()->SymbolizeCode( if (Symbolizer *sym = Symbolizer::GetOrNull())
pc, addr_frames.data(), addr_frames.size()); addr_frames_num =
sym->SymbolizeCode(pc, addr_frames.data(), addr_frames.size());
for (uptr j = 0; j < addr_frames_num; j++) { for (uptr j = 0; j < addr_frames_num; j++) {
AddressInfo &info = addr_frames[j]; AddressInfo &info = addr_frames[j];
PrintStackFramePrefix(frame_num, pc); PrintStackFramePrefix(frame_num, pc);

View File

@ -0,0 +1,43 @@
//===-- sanitizer_symbolizer.cc -------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries.
//===----------------------------------------------------------------------===//
#include "sanitizer_platform.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_symbolizer.h"
namespace __sanitizer {
atomic_uintptr_t Symbolizer::symbolizer_;
LowLevelAllocator Symbolizer::symbolizer_allocator_;
Symbolizer *Symbolizer::GetOrNull() {
return reinterpret_cast<Symbolizer *>(
atomic_load(&symbolizer_, memory_order_acquire));
}
Symbolizer *Symbolizer::Get() {
Symbolizer *sym = GetOrNull();
CHECK(sym);
return sym;
}
Symbolizer *Symbolizer::Disable() {
CHECK_EQ(0, atomic_load(&symbolizer_, memory_order_acquire));
Symbolizer *dummy_sym = new(symbolizer_allocator_) Symbolizer;
atomic_store(&symbolizer_, reinterpret_cast<uptr>(&dummy_sym),
memory_order_release);
return dummy_sym;
}
} // namespace __sanitizer

View File

@ -69,8 +69,24 @@ struct DataInfo {
uptr size; uptr size;
}; };
class SymbolizerInterface { class Symbolizer {
public: public:
/// Returns platform-specific implementation of Symbolizer. The symbolizer
/// must be initialized (with init or disable) before calling this function.
static Symbolizer *Get();
/// Returns platform-specific implementation of Symbolizer, or null if not
/// initialized.
static Symbolizer *GetOrNull();
/// Returns platform-specific implementation of Symbolizer. Will
/// automatically initialize symbolizer as if by calling Init(0) if needed.
static Symbolizer *GetOrInit();
/// Initialize and return the symbolizer, given an optional path to an
/// external symbolizer. The path argument is only required for legacy
/// reasons as this function will check $PATH for an external symbolizer. Not
/// thread safe.
static Symbolizer *Init(const char* path_to_external = 0);
/// Initialize the symbolizer in a disabled state. Not thread safe.
static Symbolizer *Disable();
// Fills at most "max_frames" elements of "frames" with descriptions // Fills at most "max_frames" elements of "frames" with descriptions
// for a given address (in all inlined functions). Returns the number // for a given address (in all inlined functions). Returns the number
// of descriptions actually filled. // of descriptions actually filled.
@ -84,6 +100,9 @@ class SymbolizerInterface {
virtual bool IsAvailable() { virtual bool IsAvailable() {
return false; return false;
} }
virtual bool IsExternalAvailable() {
return false;
}
// Release internal caches (if any). // Release internal caches (if any).
virtual void Flush() {} virtual void Flush() {}
// Attempts to demangle the provided C++ mangled name. // Attempts to demangle the provided C++ mangled name.
@ -91,17 +110,19 @@ class SymbolizerInterface {
return name; return name;
} }
virtual void PrepareForSandboxing() {} virtual void PrepareForSandboxing() {}
// Starts external symbolizer program in a subprocess. Sanitizer communicates
// with external symbolizer via pipes. If path_to_symbolizer is NULL or empty,
// tries to look for llvm-symbolizer in PATH.
virtual bool InitializeExternal(const char *path_to_symbolizer) {
return false;
}
};
// Returns platform-specific implementation of SymbolizerInterface. It can't be private:
// used from multiple threads simultaneously. /// Platform-specific function for creating a Symbolizer object.
SANITIZER_WEAK_ATTRIBUTE SymbolizerInterface *getSymbolizer(); static Symbolizer *PlatformInit(const char *path_to_external);
/// Create a symbolizer and store it to symbolizer_ without checking if one
/// already exists. Not thread safe.
static Symbolizer *CreateAndStore(const char *path_to_external);
static atomic_uintptr_t symbolizer_;
protected:
static LowLevelAllocator symbolizer_allocator_;
};
} // namespace __sanitizer } // namespace __sanitizer

View File

@ -0,0 +1,47 @@
//===-- sanitizer_symbolizer_libcdep.cc -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries.
//===----------------------------------------------------------------------===//
#include "sanitizer_platform.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_symbolizer.h"
namespace __sanitizer {
Symbolizer *Symbolizer::CreateAndStore(const char *path_to_external) {
Symbolizer *platform_symbolizer = PlatformInit(path_to_external);
if (!platform_symbolizer) return Disable();
atomic_store(&symbolizer_, reinterpret_cast<uptr>(platform_symbolizer),
memory_order_release);
return platform_symbolizer;
}
Symbolizer *Symbolizer::Init(const char *path_to_external) {
CHECK_EQ(0, atomic_load(&symbolizer_, memory_order_acquire));
return CreateAndStore(path_to_external);
}
Symbolizer *Symbolizer::GetOrInit() {
static StaticSpinMutex init_mu;
uptr sym = atomic_load(&symbolizer_, memory_order_acquire);
if (!sym) {
SpinMutexLock l(&init_mu);
sym = atomic_load(&symbolizer_, memory_order_relaxed);
if (!sym) return CreateAndStore(0);
}
return reinterpret_cast<Symbolizer *>(sym);
}
} // namespace __sanitizer

View File

@ -285,8 +285,6 @@ class ExternalSymbolizer {
uptr times_restarted_; uptr times_restarted_;
}; };
static LowLevelAllocator symbolizer_allocator; // Linker initialized.
#if SANITIZER_SUPPORTS_WEAK_HOOKS #if SANITIZER_SUPPORTS_WEAK_HOOKS
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
@ -306,11 +304,10 @@ class InternalSymbolizer {
public: public:
typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int); typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
static InternalSymbolizer *get() { static InternalSymbolizer *get(LowLevelAllocator *alloc) {
if (__sanitizer_symbolize_code != 0 && if (__sanitizer_symbolize_code != 0 &&
__sanitizer_symbolize_data != 0) { __sanitizer_symbolize_data != 0) {
void *mem = symbolizer_allocator.Allocate(sizeof(InternalSymbolizer)); return new(*alloc) InternalSymbolizer();
return new(mem) InternalSymbolizer();
} }
return 0; return 0;
} }
@ -357,7 +354,7 @@ class InternalSymbolizer {
class InternalSymbolizer { class InternalSymbolizer {
public: public:
static InternalSymbolizer *get() { return 0; } static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
char *SendCommand(bool is_data, const char *module_name, uptr module_offset) { char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
return 0; return 0;
} }
@ -367,11 +364,15 @@ class InternalSymbolizer {
#endif // SANITIZER_SUPPORTS_WEAK_HOOKS #endif // SANITIZER_SUPPORTS_WEAK_HOOKS
class Symbolizer : public SymbolizerInterface { class POSIXSymbolizer : public Symbolizer {
// This class has no constructor, as global constructors are forbidden in
// sanitizer_common. It should be linker initialized instead.
public: public:
POSIXSymbolizer(ExternalSymbolizer *external_symbolizer,
InternalSymbolizer *internal_symbolizer)
: external_symbolizer_(external_symbolizer),
internal_symbolizer_(internal_symbolizer) {}
uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) { uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
BlockingMutexLock l(&mu_);
if (max_frames == 0) if (max_frames == 0)
return 0; return 0;
LoadedModule *module = FindModuleForAddress(addr); LoadedModule *module = FindModuleForAddress(addr);
@ -432,6 +433,7 @@ class Symbolizer : public SymbolizerInterface {
} }
bool SymbolizeData(uptr addr, DataInfo *info) { bool SymbolizeData(uptr addr, DataInfo *info) {
BlockingMutexLock l(&mu_);
LoadedModule *module = FindModuleForAddress(addr); LoadedModule *module = FindModuleForAddress(addr);
if (module == 0) if (module == 0)
return false; return false;
@ -451,42 +453,32 @@ class Symbolizer : public SymbolizerInterface {
return true; return true;
} }
bool InitializeExternal(const char *path_to_symbolizer) { bool IsAvailable() {
if (!path_to_symbolizer || path_to_symbolizer[0] == '\0') { return internal_symbolizer_ != 0 || external_symbolizer_ != 0;
path_to_symbolizer = FindPathToBinary("llvm-symbolizer");
if (!path_to_symbolizer)
return false;
}
int input_fd, output_fd;
if (!StartSymbolizerSubprocess(path_to_symbolizer, &input_fd, &output_fd))
return false;
void *mem = symbolizer_allocator.Allocate(sizeof(ExternalSymbolizer));
external_symbolizer_ = new(mem) ExternalSymbolizer(path_to_symbolizer,
input_fd, output_fd);
return true;
} }
bool IsAvailable() { bool IsExternalAvailable() {
if (internal_symbolizer_ == 0) return external_symbolizer_ != 0;
internal_symbolizer_ = InternalSymbolizer::get();
return internal_symbolizer_ || external_symbolizer_;
} }
void Flush() { void Flush() {
if (internal_symbolizer_) BlockingMutexLock l(&mu_);
if (internal_symbolizer_ != 0)
internal_symbolizer_->Flush(); internal_symbolizer_->Flush();
if (external_symbolizer_) if (external_symbolizer_ != 0)
external_symbolizer_->Flush(); external_symbolizer_->Flush();
} }
const char *Demangle(const char *name) { const char *Demangle(const char *name) {
if (IsAvailable() && internal_symbolizer_ != 0) BlockingMutexLock l(&mu_);
if (internal_symbolizer_ != 0)
return internal_symbolizer_->Demangle(name); return internal_symbolizer_->Demangle(name);
return DemangleCXXABI(name); return DemangleCXXABI(name);
} }
void PrepareForSandboxing() { void PrepareForSandboxing() {
#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
@ -494,10 +486,8 @@ class Symbolizer : public SymbolizerInterface {
private: private:
char *SendCommand(bool is_data, const char *module_name, uptr module_offset) { char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
mu_.CheckLocked();
// First, try to use internal symbolizer. // First, try to use internal symbolizer.
if (!IsAvailable()) {
return 0;
}
if (internal_symbolizer_) { if (internal_symbolizer_) {
return internal_symbolizer_->SendCommand(is_data, module_name, return internal_symbolizer_->SendCommand(is_data, module_name,
module_offset); module_offset);
@ -526,9 +516,10 @@ class Symbolizer : public SymbolizerInterface {
} }
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(
kMaxNumberOfModuleContexts * sizeof(LoadedModule))); kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
CHECK(modules_); CHECK(modules_);
n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts, n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
@ -571,25 +562,31 @@ class Symbolizer : public SymbolizerInterface {
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_;
ExternalSymbolizer *external_symbolizer_; // Leaked. ExternalSymbolizer *external_symbolizer_; // Leaked.
InternalSymbolizer *internal_symbolizer_; // Leaked. InternalSymbolizer *const internal_symbolizer_; // Leaked.
}; };
static ALIGNED(64) char symbolizer_placeholder[sizeof(Symbolizer)]; Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) {
static Symbolizer *symbolizer; InternalSymbolizer* internal_symbolizer =
InternalSymbolizer::get(&symbolizer_allocator_);
ExternalSymbolizer *external_symbolizer = 0;
SymbolizerInterface *getSymbolizer() { if (!internal_symbolizer) {
static atomic_uint8_t initialized; if (!path_to_external || path_to_external[0] == '\0')
static StaticSpinMutex init_mu; path_to_external = FindPathToBinary("llvm-symbolizer");
if (atomic_load(&initialized, memory_order_acquire) == 0) {
SpinMutexLock l(&init_mu); int input_fd, output_fd;
if (atomic_load(&initialized, memory_order_relaxed) == 0) { if (path_to_external &&
symbolizer = new(symbolizer_placeholder) Symbolizer(); StartSymbolizerSubprocess(path_to_external, &input_fd, &output_fd)) {
atomic_store(&initialized, 1, memory_order_release); external_symbolizer = new(symbolizer_allocator_)
ExternalSymbolizer(path_to_external, input_fd, output_fd);
} }
} }
return symbolizer;
return new(symbolizer_allocator_)
POSIXSymbolizer(external_symbolizer, internal_symbolizer);
} }
} // namespace __sanitizer } // namespace __sanitizer

View File

@ -14,16 +14,11 @@
#include "sanitizer_platform.h" #include "sanitizer_platform.h"
#if SANITIZER_WINDOWS #if SANITIZER_WINDOWS
#include "sanitizer_internal_defs.h"
#include "sanitizer_symbolizer.h" #include "sanitizer_symbolizer.h"
namespace __sanitizer { namespace __sanitizer {
static SymbolizerInterface win_symbolizer; // Linker initialized. Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) { return 0; }
SymbolizerInterface *getSymbolizer() {
return &win_symbolizer;
}
} // namespace __sanitizer } // namespace __sanitizer

View File

@ -238,10 +238,10 @@ void Initialize(ThreadState *thr) {
InitializeLibIgnore(); InitializeLibIgnore();
// Initialize external symbolizer before internal threads are started. // Initialize external symbolizer before internal threads are started.
const char *external_symbolizer = flags()->external_symbolizer_path; const char *external_symbolizer = flags()->external_symbolizer_path;
bool symbolizer_started = bool external_symbolizer_started =
getSymbolizer()->InitializeExternal(external_symbolizer); Symbolizer::Init(external_symbolizer)->IsExternalAvailable();
if (external_symbolizer != 0 && external_symbolizer[0] != '\0' && if (external_symbolizer != 0 && external_symbolizer[0] != '\0' &&
!symbolizer_started) { !external_symbolizer_started) {
Printf("Failed to start external symbolizer: '%s'\n", Printf("Failed to start external symbolizer: '%s'\n",
external_symbolizer); external_symbolizer);
Die(); Die();

View File

@ -119,15 +119,15 @@ ReportStack *SymbolizeCode(uptr addr) {
ent->col = col; ent->col = col;
return ent; return ent;
} }
if (!getSymbolizer()->IsAvailable()) if (!Symbolizer::Get()->IsAvailable())
return SymbolizeCodeAddr2Line(addr); return SymbolizeCodeAddr2Line(addr);
ScopedInSymbolizer in_symbolizer; ScopedInSymbolizer in_symbolizer;
static const uptr kMaxAddrFrames = 16; static const uptr kMaxAddrFrames = 16;
InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
for (uptr i = 0; i < kMaxAddrFrames; i++) for (uptr i = 0; i < kMaxAddrFrames; i++)
new(&addr_frames[i]) AddressInfo(); new(&addr_frames[i]) AddressInfo();
uptr addr_frames_num = uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode(
getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames); addr, addr_frames.data(), kMaxAddrFrames);
if (addr_frames_num == 0) if (addr_frames_num == 0)
return NewReportStackEntry(addr); return NewReportStackEntry(addr);
ReportStack *top = 0; ReportStack *top = 0;
@ -146,11 +146,11 @@ ReportStack *SymbolizeCode(uptr addr) {
} }
ReportLocation *SymbolizeData(uptr addr) { ReportLocation *SymbolizeData(uptr addr) {
if (!getSymbolizer()->IsAvailable()) if (!Symbolizer::Get()->IsAvailable())
return 0; return 0;
ScopedInSymbolizer in_symbolizer; ScopedInSymbolizer in_symbolizer;
DataInfo info; DataInfo info;
if (!getSymbolizer()->SymbolizeData(addr, &info)) if (!Symbolizer::Get()->SymbolizeData(addr, &info))
return 0; return 0;
ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack, ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
sizeof(ReportLocation)); sizeof(ReportLocation));
@ -166,10 +166,10 @@ ReportLocation *SymbolizeData(uptr addr) {
} }
void SymbolizeFlush() { void SymbolizeFlush() {
if (!getSymbolizer()->IsAvailable()) if (!Symbolizer::Get()->IsAvailable())
return; return;
ScopedInSymbolizer in_symbolizer; ScopedInSymbolizer in_symbolizer;
getSymbolizer()->Flush(); Symbolizer::Get()->Flush();
} }
} // namespace __tsan } // namespace __tsan

View File

@ -8,7 +8,6 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
# working binaries. # working binaries.
set(UBSAN_TEST_DEPS set(UBSAN_TEST_DEPS
${SANITIZER_COMMON_LIT_TEST_DEPS} ${SANITIZER_COMMON_LIT_TEST_DEPS}
asan
${UBSAN_RUNTIME_LIBRARIES}) ${UBSAN_RUNTIME_LIBRARIES})
set(UBSAN_TEST_PARAMS set(UBSAN_TEST_PARAMS
ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg

View File

@ -1,4 +1,4 @@
// RUN: %clangxx -fsanitize=address,function %s -O3 -g -o %t // RUN: %clangxx -fsanitize=function %s -O3 -g -o %t
// RUN: %t 2>&1 | FileCheck %s // RUN: %t 2>&1 | FileCheck %s
#include <stdint.h> #include <stdint.h>

View File

@ -54,9 +54,6 @@ config.substitutions.append( ("%clang ", (" " + config.clang + " ")) )
config.substitutions.append( ("%clangxx ", (" " + config.clang + config.substitutions.append( ("%clangxx ", (" " + config.clang +
" --driver-mode=g++ ")) ) " --driver-mode=g++ ")) )
# Setup path to external LLVM symbolizer.
config.environment['ASAN_SYMBOLIZER_PATH'] = config.llvm_symbolizer_path
# Default test suffixes. # Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp'] config.suffixes = ['.c', '.cc', '.cpp']

View File

@ -34,7 +34,7 @@ Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) {
return Location(); return Location();
AddressInfo Info; AddressInfo Info;
if (!getSymbolizer()->SymbolizeCode(Loc, &Info, 1) || if (!Symbolizer::GetOrInit()->SymbolizeCode(Loc, &Info, 1) ||
!Info.module || !*Info.module) !Info.module || !*Info.module)
return Location(Loc); return Location(Loc);
@ -117,7 +117,7 @@ static void renderText(const char *Message, const Diag::Arg *Args) {
Printf("%s", A.String); Printf("%s", A.String);
break; break;
case Diag::AK_Mangled: { case Diag::AK_Mangled: {
Printf("'%s'", getSymbolizer()->Demangle(A.String)); Printf("'%s'", Symbolizer::GetOrInit()->Demangle(A.String));
break; break;
} }
case Diag::AK_SInt: case Diag::AK_SInt: