sanitizer_symbolizer.h revision 1.4
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
23namespace __sanitizer {
24
25struct 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).
48struct 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.
61struct 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 *name;
67  uptr start;
68  uptr size;
69
70  DataInfo();
71  void Clear();
72};
73
74class SymbolizerTool;
75
76class Symbolizer final {
77 public:
78  /// Initialize and return platform-specific implementation of symbolizer
79  /// (if it wasn't already initialized).
80  static Symbolizer *GetOrInit();
81  // Returns a list of symbolized frames for a given address (containing
82  // all inlined functions, if necessary).
83  SymbolizedStack *SymbolizePC(uptr address);
84  bool SymbolizeData(uptr address, DataInfo *info);
85
86  // The module names Symbolizer returns are stable and unique for every given
87  // module.  It is safe to store and compare them as pointers.
88  bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
89                                   uptr *module_address);
90  const char *GetModuleNameForPc(uptr pc) {
91    const char *module_name = nullptr;
92    uptr unused;
93    if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))
94      return module_name;
95    return nullptr;
96  }
97
98  // Release internal caches (if any).
99  void Flush();
100  // Attempts to demangle the provided C++ mangled name.
101  const char *Demangle(const char *name);
102  void PrepareForSandboxing();
103
104  // Allow user to install hooks that would be called before/after Symbolizer
105  // does the actual file/line info fetching. Specific sanitizers may need this
106  // to distinguish system library calls made in user code from calls made
107  // during in-process symbolization.
108  typedef void (*StartSymbolizationHook)();
109  typedef void (*EndSymbolizationHook)();
110  // May be called at most once.
111  void AddHooks(StartSymbolizationHook start_hook,
112                EndSymbolizationHook end_hook);
113
114 private:
115  // GetModuleNameAndOffsetForPC has to return a string to the caller.
116  // Since the corresponding module might get unloaded later, we should create
117  // our owned copies of the strings that we can safely return.
118  // ModuleNameOwner does not provide any synchronization, thus calls to
119  // its method should be protected by |mu_|.
120  class ModuleNameOwner {
121   public:
122    explicit ModuleNameOwner(BlockingMutex *synchronized_by)
123        : storage_(kInitialCapacity), last_match_(nullptr),
124          mu_(synchronized_by) {}
125    const char *GetOwnedCopy(const char *str);
126
127   private:
128    static const uptr kInitialCapacity = 1000;
129    InternalMmapVector<const char*> storage_;
130    const char *last_match_;
131
132    BlockingMutex *mu_;
133  } module_names_;
134
135  /// Platform-specific function for creating a Symbolizer object.
136  static Symbolizer *PlatformInit();
137
138  bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
139                                         uptr *module_offset);
140  LoadedModule *FindModuleForAddress(uptr address);
141  LoadedModule modules_[kMaxNumberOfModules];
142  uptr n_modules_;
143  // If stale, need to reload the modules before looking up addresses.
144  bool modules_fresh_;
145
146  // Platform-specific default demangler, must not return nullptr.
147  const char *PlatformDemangle(const char *name);
148  void PlatformPrepareForSandboxing();
149
150  static Symbolizer *symbolizer_;
151  static StaticSpinMutex init_mu_;
152
153  // Mutex locked from public methods of |Symbolizer|, so that the internals
154  // (including individual symbolizer tools and platform-specific methods) are
155  // always synchronized.
156  BlockingMutex mu_;
157
158  typedef IntrusiveList<SymbolizerTool>::Iterator Iterator;
159  IntrusiveList<SymbolizerTool> tools_;
160
161  explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
162
163  static LowLevelAllocator symbolizer_allocator_;
164
165  StartSymbolizationHook start_hook_;
166  EndSymbolizationHook end_hook_;
167  class SymbolizerScope {
168   public:
169    explicit SymbolizerScope(const Symbolizer *sym);
170    ~SymbolizerScope();
171   private:
172    const Symbolizer *sym_;
173  };
174};
175
176}  // namespace __sanitizer
177
178#endif  // SANITIZER_SYMBOLIZER_H
179