diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2013-12-18 14:29:16 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2013-12-18 14:29:16 +0000 |
commit | 65bedc8fad65ba417e945ba2b04a73ef70384580 (patch) | |
tree | f5018597217c1578910670239aec94225ea53165 | |
parent | ce0ccbea81e3db32904502d9e2566ab27ed5ff00 (diff) |
[Sanitizer] Implement Symbolizer class on Windows
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@197571 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/asan/asan_stack.cc | 2 | ||||
-rw-r--r-- | lib/asan/asan_win.cc | 53 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_stacktrace.cc | 3 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_symbolizer.h | 9 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_symbolizer_win.cc | 74 |
5 files changed, 85 insertions, 56 deletions
diff --git a/lib/asan/asan_stack.cc b/lib/asan/asan_stack.cc index 33b9fc927..8934913f3 100644 --- a/lib/asan/asan_stack.cc +++ b/lib/asan/asan_stack.cc @@ -39,7 +39,7 @@ void PrintStack(StackTrace *stack) { // Provide default implementation of __asan_symbolize that does nothing // and may be overriden by user if he wants to use his own symbolization. // ASan on Windows has its own implementation of this. -#if !SANITIZER_WINDOWS && !SANITIZER_SUPPORTS_WEAK_HOOKS +#if !SANITIZER_SUPPORTS_WEAK_HOOKS SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) { return false; diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index 9e66b3417..ed7261801 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -35,11 +35,6 @@ extern "C" { namespace __asan { -// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1 -static BlockingMutex dbghelp_lock(LINKER_INITIALIZED); -static bool dbghelp_initialized = false; -#pragma comment(lib, "dbghelp.lib") - // ---------------------- TSD ---------------- {{{1 static bool tsd_key_inited = false; @@ -97,52 +92,4 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) { } // namespace __asan -// ---------------------- Interface ---------------- {{{1 -using namespace __asan; // NOLINT - -extern "C" { -SANITIZER_INTERFACE_ATTRIBUTE NOINLINE -bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) { - BlockingMutexLock lock(&dbghelp_lock); - if (!dbghelp_initialized) { - SymSetOptions(SYMOPT_DEFERRED_LOADS | - SYMOPT_UNDNAME | - SYMOPT_LOAD_LINES); - CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); - // FIXME: We don't call SymCleanup() on exit yet - should we? - dbghelp_initialized = true; - } - - // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx - char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; - PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; - DWORD64 offset = 0; - BOOL got_objname = SymFromAddr(GetCurrentProcess(), - (DWORD64)addr, &offset, symbol); - if (!got_objname) - return false; - - DWORD unused; - IMAGEHLP_LINE64 info; - info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), - (DWORD64)addr, &unused, &info); - int written = 0; - out_buffer[0] = '\0'; - // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. - if (got_fileline) { - written += internal_snprintf(out_buffer + written, buffer_size - written, - " %s %s:%d", symbol->Name, - info.FileName, info.LineNumber); - } else { - written += internal_snprintf(out_buffer + written, buffer_size - written, - " %s+0x%p", symbol->Name, offset); - } - return true; -} -} // extern "C" - - #endif // _WIN32 diff --git a/lib/sanitizer_common/sanitizer_stacktrace.cc b/lib/sanitizer_common/sanitizer_stacktrace.cc index c6c3c69f6..a52fa2eef 100644 --- a/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -79,6 +79,9 @@ void StackTrace::PrintStack(const uptr *addr, uptr size, PrintStackFramePrefix(&frame_desc, frame_num, pc); if (info.function) { frame_desc.append(" in %s", info.function); + // Print offset in function if we don't know the source file. + if (!info.file && info.function_offset != AddressInfo::kUnknown) + frame_desc.append("+0x%zx", info.function_offset); } if (info.file) { frame_desc.append(" "); diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h index 4271fa67f..776cdebb6 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer.h +++ b/lib/sanitizer_common/sanitizer_symbolizer.h @@ -27,23 +27,30 @@ namespace __sanitizer { struct AddressInfo { uptr address; + char *module; uptr module_offset; + + static const uptr kUnknown = ~(uptr)0; char *function; + uptr function_offset; + char *file; int line; int column; AddressInfo() { internal_memset(this, 0, sizeof(AddressInfo)); + function_offset = kUnknown; } - // Deletes all strings and sets all fields to zero. + // Deletes all strings and resets all fields. void Clear() { InternalFree(module); InternalFree(function); InternalFree(file); internal_memset(this, 0, sizeof(AddressInfo)); + function_offset = kUnknown; } void FillAddressAndModuleInfo(uptr addr, const char *mod_name, diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc index 5d451eff6..f95abcd27 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -14,11 +14,83 @@ #include "sanitizer_platform.h" #if SANITIZER_WINDOWS +#include <windows.h> +#include <dbghelp.h> +#pragma comment(lib, "dbghelp.lib") + #include "sanitizer_symbolizer.h" namespace __sanitizer { -Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) { return 0; } +class WinSymbolizer : public Symbolizer { + public: + WinSymbolizer() : initialized_(false) {} + + uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) { + if (max_frames == 0) + return 0; + + BlockingMutexLock l(&dbghelp_mu_); + if (!initialized_) { + SymSetOptions(SYMOPT_DEFERRED_LOADS | + SYMOPT_UNDNAME | + SYMOPT_LOAD_LINES); + CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); + // FIXME: We don't call SymCleanup() on exit yet - should we? + initialized_ = true; + } + + // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + DWORD64 offset = 0; + BOOL got_objname = SymFromAddr(GetCurrentProcess(), + (DWORD64)addr, &offset, symbol); + if (!got_objname) + return 0; + + DWORD unused; + IMAGEHLP_LINE64 line_info; + line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr, + &unused, &line_info); + AddressInfo *info = &frames[0]; + info->Clear(); + info->function = internal_strdup(symbol->Name); + info->function_offset = offset; + if (got_fileline) { + info->file = internal_strdup(line_info.FileName); + info->line = line_info.LineNumber; + } + + IMAGEHLP_MODULE64 mod_info; + internal_memset(&mod_info, 0, sizeof(mod_info)); + mod_info.SizeOfStruct = sizeof(mod_info); + if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) + info->FillAddressAndModuleInfo(addr, mod_info.ImageName, + addr - mod_info.BaseOfImage); + return 1; + } + + bool IsAvailable() { + return true; + } + + private: + // All DbgHelp functions are single threaded, so we should use a mutex to + // serialize accesses. + BlockingMutex dbghelp_mu_; + bool initialized_; +}; + +Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) { + static bool called_once = false; + CHECK(!called_once && "Shouldn't create more than one symbolizer"); + called_once = true; + return new(symbolizer_allocator_) WinSymbolizer(); +} } // namespace __sanitizer |