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