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