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