1//===-- sanitizer_symbolizer.h ----------------------------------*- C++ -*-===// 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// Symbolizer is used by sanitizers to map instruction address to a location in 11// source code at run-time. Symbolizer either uses __sanitizer_symbolize_* 12// defined in the program, or (if they are missing) tries to find and 13// launch "llvm-symbolizer" commandline tool in a separate process and 14// communicate with it. 15// 16// Generally we should try to avoid calling system library functions during 17// symbolization (and use their replacements from sanitizer_libc.h instead). 18//===----------------------------------------------------------------------===// 19#ifndef SANITIZER_SYMBOLIZER_H 20#define SANITIZER_SYMBOLIZER_H 21 22#include "sanitizer_common.h" 23#include "sanitizer_mutex.h" 24 25namespace __sanitizer { 26 27struct AddressInfo { 28 // Owns all the string members. Storage for them is 29 // (de)allocated using sanitizer internal allocator. 30 uptr address; 31 32 char *module; 33 uptr module_offset; 34 ModuleArch module_arch; 35 36 static const uptr kUnknown = ~(uptr)0; 37 char *function; 38 uptr function_offset; 39 40 char *file; 41 int line; 42 int column; 43 44 AddressInfo(); 45 // Deletes all strings and resets all fields. 46 void Clear(); 47 void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch); 48}; 49 50// Linked list of symbolized frames (each frame is described by AddressInfo). 51struct SymbolizedStack { 52 SymbolizedStack *next; 53 AddressInfo info; 54 static SymbolizedStack *New(uptr addr); 55 // Deletes current, and all subsequent frames in the linked list. 56 // The object cannot be accessed after the call to this function. 57 void ClearAll(); 58 59 private: 60 SymbolizedStack(); 61}; 62 63// For now, DataInfo is used to describe global variable. 64struct DataInfo { 65 // Owns all the string members. Storage for them is 66 // (de)allocated using sanitizer internal allocator. 67 char *module; 68 uptr module_offset; 69 ModuleArch module_arch; 70 71 char *file; 72 uptr line; 73 char *name; 74 uptr start; 75 uptr size; 76 77 DataInfo(); 78 void Clear(); 79}; 80 81class SymbolizerTool; 82 83class Symbolizer final { 84 public: 85 /// Initialize and return platform-specific implementation of symbolizer 86 /// (if it wasn't already initialized). 87 static Symbolizer *GetOrInit(); 88 static void LateInitialize(); 89 // Returns a list of symbolized frames for a given address (containing 90 // all inlined functions, if necessary). 91 SymbolizedStack *SymbolizePC(uptr address); 92 bool SymbolizeData(uptr address, DataInfo *info); 93 94 // The module names Symbolizer returns are stable and unique for every given 95 // module. It is safe to store and compare them as pointers. 96 bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, 97 uptr *module_address); 98 const char *GetModuleNameForPc(uptr pc) { 99 const char *module_name = nullptr; 100 uptr unused; 101 if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused)) 102 return module_name; 103 return nullptr; 104 } 105 106 // Release internal caches (if any). 107 void Flush(); 108 // Attempts to demangle the provided C++ mangled name. 109 const char *Demangle(const char *name); 110 111 // Allow user to install hooks that would be called before/after Symbolizer 112 // does the actual file/line info fetching. Specific sanitizers may need this 113 // to distinguish system library calls made in user code from calls made 114 // during in-process symbolization. 115 typedef void (*StartSymbolizationHook)(); 116 typedef void (*EndSymbolizationHook)(); 117 // May be called at most once. 118 void AddHooks(StartSymbolizationHook start_hook, 119 EndSymbolizationHook end_hook); 120 121 void RefreshModules(); 122 const LoadedModule *FindModuleForAddress(uptr address); 123 124 void InvalidateModuleList(); 125 126 private: 127 // GetModuleNameAndOffsetForPC has to return a string to the caller. 128 // Since the corresponding module might get unloaded later, we should create 129 // our owned copies of the strings that we can safely return. 130 // ModuleNameOwner does not provide any synchronization, thus calls to 131 // its method should be protected by |mu_|. 132 class ModuleNameOwner { 133 public: 134 explicit ModuleNameOwner(BlockingMutex *synchronized_by) 135 : last_match_(nullptr), mu_(synchronized_by) { 136 storage_.reserve(kInitialCapacity); 137 } 138 const char *GetOwnedCopy(const char *str); 139 140 private: 141 static const uptr kInitialCapacity = 1000; 142 InternalMmapVector<const char*> storage_; 143 const char *last_match_; 144 145 BlockingMutex *mu_; 146 } module_names_; 147 148 /// Platform-specific function for creating a Symbolizer object. 149 static Symbolizer *PlatformInit(); 150 151 bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name, 152 uptr *module_offset, 153 ModuleArch *module_arch); 154 ListOfModules modules_; 155 ListOfModules fallback_modules_; 156 // If stale, need to reload the modules before looking up addresses. 157 bool modules_fresh_; 158 159 // Platform-specific default demangler, must not return nullptr. 160 const char *PlatformDemangle(const char *name); 161 162 static Symbolizer *symbolizer_; 163 static StaticSpinMutex init_mu_; 164 165 // Mutex locked from public methods of |Symbolizer|, so that the internals 166 // (including individual symbolizer tools and platform-specific methods) are 167 // always synchronized. 168 BlockingMutex mu_; 169 170 IntrusiveList<SymbolizerTool> tools_; 171 172 explicit Symbolizer(IntrusiveList<SymbolizerTool> tools); 173 174 static LowLevelAllocator symbolizer_allocator_; 175 176 StartSymbolizationHook start_hook_; 177 EndSymbolizationHook end_hook_; 178 class SymbolizerScope { 179 public: 180 explicit SymbolizerScope(const Symbolizer *sym); 181 ~SymbolizerScope(); 182 private: 183 const Symbolizer *sym_; 184 }; 185}; 186 187#ifdef SANITIZER_WINDOWS 188void InitializeDbgHelpIfNeeded(); 189#endif 190 191} // namespace __sanitizer 192 193#endif // SANITIZER_SYMBOLIZER_H 194