summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimur Iskhodzhanov <timurrrr@google.com>2013-12-18 14:29:16 +0000
committerTimur Iskhodzhanov <timurrrr@google.com>2013-12-18 14:29:16 +0000
commit65bedc8fad65ba417e945ba2b04a73ef70384580 (patch)
treef5018597217c1578910670239aec94225ea53165
parentce0ccbea81e3db32904502d9e2566ab27ed5ff00 (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.cc2
-rw-r--r--lib/asan/asan_win.cc53
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace.cc3
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer.h9
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_win.cc74
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