[compiler-rt] r231478 - Symbolizer refactoring: Make WinSymbolizer use SymbolizerTool interface

Kuba Brecka kuba.brecka at gmail.com
Fri Mar 6 06:33:56 PST 2015


Author: kuba.brecka
Date: Fri Mar  6 08:33:56 2015
New Revision: 231478

URL: http://llvm.org/viewvc/llvm-project?rev=231478&view=rev
Log:
Symbolizer refactoring: Make WinSymbolizer use SymbolizerTool interface

Reviewed at http://reviews.llvm.org/D8089


Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h?rev=231478&r1=231477&r2=231478&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_internal.h Fri Mar  6 08:33:56 2015
@@ -26,6 +26,9 @@ const char *ExtractToken(const char *str
 const char *ExtractInt(const char *str, const char *delims, int *result);
 const char *ExtractUptr(const char *str, const char *delims, uptr *result);
 
+// SymbolizerTool is an interface that is implemented by individual "tools"
+// that can perform symbolication (external llvm-symbolizer, libbacktrace,
+// Windows DbgHelp symbolizer, etc.).
 class SymbolizerTool {
  public:
   // POSIXSymbolizer implements a "fallback chain" of symbolizer tools. In a

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc?rev=231478&r1=231477&r2=231478&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc Fri Mar  6 08:33:56 2015
@@ -18,139 +18,171 @@
 #include <dbghelp.h>
 #pragma comment(lib, "dbghelp.lib")
 
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_win.h"
+#include "sanitizer_symbolizer_internal.h"
 
 namespace __sanitizer {
 
-class WinSymbolizer : public Symbolizer {
- public:
-  WinSymbolizer() : initialized_(false) {}
+namespace {
 
-  SymbolizedStack *SymbolizePC(uptr addr) override {
-    SymbolizedStack *frame = SymbolizedStack::New(addr);
+bool is_dbghelp_initialized = false;
 
-    BlockingMutexLock l(&dbghelp_mu_);
-    InitializeIfNeeded();
+bool TrySymInitialize() {
+  SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
+  return SymInitialize(GetCurrentProcess(), 0, TRUE);
+  // FIXME: We don't call SymCleanup() on exit yet - should we?
+}
 
-    // 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 frame;
-
-    DWORD unused;
-    IMAGEHLP_LINE64 line_info;
-    line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-    BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
-                                             &unused, &line_info);
-    frame->info.function = internal_strdup(symbol->Name);
-    frame->info.function_offset = (uptr)offset;
-    if (got_fileline) {
-      frame->info.file = internal_strdup(line_info.FileName);
-      frame->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))
-      frame->info.FillModuleInfo(mod_info.ImageName,
-                                 addr - (uptr)mod_info.BaseOfImage);
-    return frame;
+// Initializes DbgHelp library, if it's not yet initialized. Calls to this
+// function should be synchronized with respect to other calls to DbgHelp API
+// (e.g. from WinSymbolizerTool).
+void InitializeDbgHelpIfNeeded() {
+  if (is_dbghelp_initialized)
+    return;
+  if (!TrySymInitialize()) {
+    // OK, maybe the client app has called SymInitialize already.
+    // That's a bit unfortunate for us as all the DbgHelp functions are
+    // single-threaded and we can't coordinate with the app.
+    // FIXME: Can we stop the other threads at this point?
+    // Anyways, we have to reconfigure stuff to make sure that SymInitialize
+    // has all the appropriate options set.
+    // Cross our fingers and reinitialize DbgHelp.
+    Report("*** WARNING: Failed to initialize DbgHelp!              ***\n");
+    Report("*** Most likely this means that the app is already      ***\n");
+    Report("*** using DbgHelp, possibly with incompatible flags.    ***\n");
+    Report("*** Due to technical reasons, symbolization might crash ***\n");
+    Report("*** or produce wrong results.                           ***\n");
+    SymCleanup(GetCurrentProcess());
+    TrySymInitialize();
   }
+  is_dbghelp_initialized = true;
 
-  bool CanReturnFileLineInfo() override {
+  // When an executable is run from a location different from the one where it
+  // was originally built, we may not see the nearby PDB files.
+  // To work around this, let's append the directory of the main module
+  // to the symbol search path.  All the failures below are not fatal.
+  const size_t kSymPathSize = 2048;
+  static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
+  if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
+    Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
+    return;
+  }
+  size_t sz = wcslen(path_buffer);
+  if (sz) {
+    CHECK_EQ(0, wcscat_s(path_buffer, L";"));
+    sz++;
+  }
+  DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
+  if (res == 0 || res == MAX_PATH) {
+    Report("*** WARNING: Failed to getting the EXE directory ***\n");
+    return;
+  }
+  // Write the zero character in place of the last backslash to get the
+  // directory of the main module at the end of path_buffer.
+  wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
+  CHECK_NE(last_bslash, 0);
+  *last_bslash = L'\0';
+  if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
+    Report("*** WARNING: Failed to SymSetSearchPathW\n");
+    return;
+  }
+}
+
+}  // namespace
+
+bool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) {
+  InitializeDbgHelpIfNeeded();
+
+  // 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 line_info;
+  line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+  BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
+                                           &unused, &line_info);
+  frame->info.function = internal_strdup(symbol->Name);
+  frame->info.function_offset = (uptr)offset;
+  if (got_fileline) {
+    frame->info.file = internal_strdup(line_info.FileName);
+    frame->info.line = line_info.LineNumber;
+  }
+  return true;
+}
+
+const char *WinSymbolizerTool::Demangle(const char *name) {
+  CHECK(is_dbghelp_initialized);
+  static char demangle_buffer[1000];
+  if (name[0] == '\01' &&
+      UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
+                           UNDNAME_NAME_ONLY))
+    return demangle_buffer;
+  else
+    return name;
+}
+
+bool FindModuleNameAndOffsetForAddress(uptr addr, const char **module_name,
+                                       uptr *module_offset) {
+  InitializeDbgHelpIfNeeded();
+
+  IMAGEHLP_MODULE64 mod_info;
+  internal_memset(&mod_info, 0, sizeof(mod_info));
+  mod_info.SizeOfStruct = sizeof(mod_info);
+  if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) {
+    *module_name = mod_info.ImageName;
+    *module_offset = addr - (uptr)mod_info.BaseOfImage;
     return true;
   }
+  return false;
+}
 
+// 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 {
-    CHECK(initialized_);
-    static char demangle_buffer[1000];
-    if (name[0] == '\01' &&
-        UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
-                             UNDNAME_NAME_ONLY))
-      return demangle_buffer;
-    else
-      return name;
-  }
-
-  // FIXME: Implement GetModuleNameAndOffsetForPC().
-
- private:
-  void InitializeIfNeeded() {
-    if (initialized_)
-      return;
-    if (!TrySymInitialize()) {
-      // OK, maybe the client app has called SymInitialize already.
-      // That's a bit unfortunate for us as all the DbgHelp functions are
-      // single-threaded and we can't coordinate with the app.
-      // FIXME: Can we stop the other threads at this point?
-      // Anyways, we have to reconfigure stuff to make sure that SymInitialize
-      // has all the appropriate options set.
-      // Cross our fingers and reinitialize DbgHelp.
-      Report("*** WARNING: Failed to initialize DbgHelp!              ***\n");
-      Report("*** Most likely this means that the app is already      ***\n");
-      Report("*** using DbgHelp, possibly with incompatible flags.    ***\n");
-      Report("*** Due to technical reasons, symbolization might crash ***\n");
-      Report("*** or produce wrong results.                           ***\n");
-      SymCleanup(GetCurrentProcess());
-      TrySymInitialize();
-    }
-    initialized_ = true;
-
-    // When an executable is run from a location different from the one where it
-    // was originally built, we may not see the nearby PDB files.
-    // To work around this, let's append the directory of the main module
-    // to the symbol search path.  All the failures below are not fatal.
-    const size_t kSymPathSize = 2048;
-    static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
-    if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
-      Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
-      return;
-    }
-    size_t sz = wcslen(path_buffer);
-    if (sz) {
-      CHECK_EQ(0, wcscat_s(path_buffer, L";"));
-      sz++;
-    }
-    DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
-    if (res == 0 || res == MAX_PATH) {
-      Report("*** WARNING: Failed to getting the EXE directory ***\n");
-      return;
-    }
-    // Write the zero character in place of the last backslash to get the
-    // directory of the main module at the end of path_buffer.
-    wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
-    CHECK_NE(last_bslash, 0);
-    *last_bslash = L'\0';
-    if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
-      Report("*** WARNING: Failed to SymSetSearchPathW\n");
-      return;
-    }
-  }
-
-  bool TrySymInitialize() {
-    SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
-    return SymInitialize(GetCurrentProcess(), 0, TRUE);
-    // FIXME: We don't call SymCleanup() on exit yet - should we?
-  }
-
-  // All DbgHelp functions are single threaded, so we should use a mutex to
-  // serialize accesses.
-  BlockingMutex dbghelp_mu_;
-  bool initialized_;
+    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_;
+  SymbolizerTool *tool_;
 };
 
 Symbolizer *Symbolizer::PlatformInit() {
   static bool called_once = false;
   CHECK(!called_once && "Shouldn't create more than one symbolizer");
   called_once = true;
-  return new(symbolizer_allocator_) WinSymbolizer();
+  SymbolizerTool *tool = new(symbolizer_allocator_) WinSymbolizerTool();
+  return new(symbolizer_allocator_) WinSymbolizer(tool);
 }
 
 }  // namespace __sanitizer

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h?rev=231478&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.h Fri Mar  6 08:33:56 2015
@@ -0,0 +1,31 @@
+//===-- sanitizer_symbolizer_win.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header file for the Windows symbolizer tool.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_WIN_H
+#define SANITIZER_SYMBOLIZER_WIN_H
+
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+class WinSymbolizerTool : public SymbolizerTool {
+ public:
+  bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+  bool SymbolizeData(uptr addr, DataInfo *info) override {
+    return false;
+  }
+  const char *Demangle(const char *name) override;
+};
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_SYMBOLIZER_WIN_H





More information about the llvm-commits mailing list