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