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

Alexey Samsonov vonosmas at gmail.com
Fri Mar 6 16:36:31 PST 2015


Please add sanitizer_symbolizer_win.h to SANITIZER_HEADERS in CMakeLists.txt

On Fri, Mar 6, 2015 at 6:33 AM, Kuba Brecka <kuba.brecka at gmail.com> wrote:

> 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
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



-- 
Alexey Samsonov
vonosmas at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150306/ce9266ea/attachment.html>


More information about the llvm-commits mailing list