1 //===-- sanitizer_symbolizer_win.cc ---------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is shared between AddressSanitizer and ThreadSanitizer 11 // run-time libraries. 12 // Windows-specific implementation of symbolizer parts. 13 //===----------------------------------------------------------------------===// 14 15 #include "sanitizer_platform.h" 16 #if SANITIZER_WINDOWS 17 #include <windows.h> 18 #include <dbghelp.h> 19 #pragma comment(lib, "dbghelp.lib") 20 21 #include "sanitizer_symbolizer.h" 22 23 namespace __sanitizer { 24 25 class WinSymbolizer : public Symbolizer { 26 public: 27 WinSymbolizer() : initialized_(false) {} 28 29 uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) { 30 if (max_frames == 0) 31 return 0; 32 33 BlockingMutexLock l(&dbghelp_mu_); 34 if (!initialized_) { 35 SymSetOptions(SYMOPT_DEFERRED_LOADS | 36 SYMOPT_UNDNAME | 37 SYMOPT_LOAD_LINES); 38 CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); 39 // FIXME: We don't call SymCleanup() on exit yet - should we? 40 initialized_ = true; 41 } 42 43 // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx 44 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; 45 PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; 46 symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 47 symbol->MaxNameLen = MAX_SYM_NAME; 48 DWORD64 offset = 0; 49 BOOL got_objname = SymFromAddr(GetCurrentProcess(), 50 (DWORD64)addr, &offset, symbol); 51 if (!got_objname) 52 return 0; 53 54 DWORD unused; 55 IMAGEHLP_LINE64 line_info; 56 line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 57 BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr, 58 &unused, &line_info); 59 AddressInfo *info = &frames[0]; 60 info->Clear(); 61 info->function = internal_strdup(symbol->Name); 62 info->function_offset = (uptr)offset; 63 if (got_fileline) { 64 info->file = internal_strdup(line_info.FileName); 65 info->line = line_info.LineNumber; 66 } 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 77 bool CanReturnFileLineInfo() { 78 return true; 79 } 80 81 const char *Demangle(const char *name) { 82 CHECK(initialized_); 83 static char demangle_buffer[1000]; 84 if (name[0] == '\01' && 85 UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer), 86 UNDNAME_NAME_ONLY)) 87 return demangle_buffer; 88 else 89 return name; 90 } 91 92 // FIXME: Implement GetModuleNameAndOffsetForPC(). 93 94 private: 95 // All DbgHelp functions are single threaded, so we should use a mutex to 96 // serialize accesses. 97 BlockingMutex dbghelp_mu_; 98 bool initialized_; 99 }; 100 101 Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) { 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 108 } // namespace __sanitizer 109 110 #endif // _WIN32 111