sanitizer_symbolizer.h 7.2 KB

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