sanitizer_symbolizer_win.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //===-- sanitizer_symbolizer_win.cc ---------------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is shared between AddressSanitizer and ThreadSanitizer
  9. // run-time libraries.
  10. // Windows-specific implementation of symbolizer parts.
  11. //===----------------------------------------------------------------------===//
  12. #include "sanitizer_platform.h"
  13. #if SANITIZER_WINDOWS
  14. #include <windows.h>
  15. #include <dbghelp.h>
  16. #pragma comment(lib, "dbghelp.lib")
  17. #include "sanitizer_symbolizer.h"
  18. namespace __sanitizer {
  19. class WinSymbolizer : public Symbolizer {
  20. public:
  21. WinSymbolizer() : initialized_(false) {}
  22. uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) {
  23. if (max_frames == 0)
  24. return 0;
  25. BlockingMutexLock l(&dbghelp_mu_);
  26. if (!initialized_) {
  27. if (!TrySymInitialize()) {
  28. // OK, maybe the client app has called SymInitialize already.
  29. // That's a bit unfortunate for us as all the DbgHelp functions are
  30. // single-threaded and we can't coordinate with the app.
  31. // FIXME: Can we stop the other threads at this point?
  32. // Anyways, we have to reconfigure stuff to make sure that SymInitialize
  33. // has all the appropriate options set.
  34. // Cross our fingers and reinitialize DbgHelp.
  35. Report("*** WARNING: Failed to initialize DbgHelp! ***\n");
  36. Report("*** Most likely this means that the app is already ***\n");
  37. Report("*** using DbgHelp, possibly with incompatible flags. ***\n");
  38. Report("*** Due to technical reasons, symbolization might crash ***\n");
  39. Report("*** or produce wrong results. ***\n");
  40. SymCleanup(GetCurrentProcess());
  41. TrySymInitialize();
  42. }
  43. initialized_ = true;
  44. }
  45. // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
  46. char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
  47. PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
  48. symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  49. symbol->MaxNameLen = MAX_SYM_NAME;
  50. DWORD64 offset = 0;
  51. BOOL got_objname = SymFromAddr(GetCurrentProcess(),
  52. (DWORD64)addr, &offset, symbol);
  53. if (!got_objname)
  54. return 0;
  55. DWORD unused;
  56. IMAGEHLP_LINE64 line_info;
  57. line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
  58. BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
  59. &unused, &line_info);
  60. AddressInfo *info = &frames[0];
  61. info->Clear();
  62. info->function = internal_strdup(symbol->Name);
  63. info->function_offset = (uptr)offset;
  64. if (got_fileline) {
  65. info->file = internal_strdup(line_info.FileName);
  66. info->line = line_info.LineNumber;
  67. }
  68. IMAGEHLP_MODULE64 mod_info;
  69. internal_memset(&mod_info, 0, sizeof(mod_info));
  70. mod_info.SizeOfStruct = sizeof(mod_info);
  71. if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info))
  72. info->FillAddressAndModuleInfo(addr, mod_info.ImageName,
  73. addr - (uptr)mod_info.BaseOfImage);
  74. return 1;
  75. }
  76. bool CanReturnFileLineInfo() {
  77. return true;
  78. }
  79. const char *Demangle(const char *name) {
  80. CHECK(initialized_);
  81. static char demangle_buffer[1000];
  82. if (name[0] == '\01' &&
  83. UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
  84. UNDNAME_NAME_ONLY))
  85. return demangle_buffer;
  86. else
  87. return name;
  88. }
  89. // FIXME: Implement GetModuleNameAndOffsetForPC().
  90. private:
  91. bool TrySymInitialize() {
  92. SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
  93. return SymInitialize(GetCurrentProcess(), 0, TRUE);
  94. // FIXME: We don't call SymCleanup() on exit yet - should we?
  95. }
  96. // All DbgHelp functions are single threaded, so we should use a mutex to
  97. // serialize accesses.
  98. BlockingMutex dbghelp_mu_;
  99. bool initialized_;
  100. };
  101. Symbolizer *Symbolizer::PlatformInit() {
  102. static bool called_once = false;
  103. CHECK(!called_once && "Shouldn't create more than one symbolizer");
  104. called_once = true;
  105. return new(symbolizer_allocator_) WinSymbolizer();
  106. }
  107. } // namespace __sanitizer
  108. #endif // _WIN32