1 //===-- sanitizer_symbolizer.h ----------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Symbolizer is used by sanitizers to map instruction address to a location in
10 // source code at run-time. Symbolizer either uses __sanitizer_symbolize_*
11 // defined in the program, or (if they are missing) tries to find and
12 // launch "llvm-symbolizer" commandline tool in a separate process and
13 // communicate with it.
15 // Generally we should try to avoid calling system library functions during
16 // symbolization (and use their replacements from sanitizer_libc.h instead).
17 //===----------------------------------------------------------------------===//
18 #ifndef SANITIZER_SYMBOLIZER_H
19 #define SANITIZER_SYMBOLIZER_H
21 #include "sanitizer_common.h"
22 #include "sanitizer_mutex.h"
23 #include "sanitizer_vector.h"
25 namespace __sanitizer
{
28 // Owns all the string members. Storage for them is
29 // (de)allocated using sanitizer internal allocator.
34 ModuleArch module_arch
;
35 u8 uuid
[kModuleUUIDSize
];
38 static const uptr kUnknown
= ~(uptr
)0;
47 // Deletes all strings and resets all fields.
49 void FillModuleInfo(const char *mod_name
, uptr mod_offset
, ModuleArch arch
);
50 void FillModuleInfo(const LoadedModule
&mod
);
51 uptr
module_base() const { return address
- module_offset
; }
54 // Linked list of symbolized frames (each frame is described by AddressInfo).
55 struct SymbolizedStack
{
56 SymbolizedStack
*next
;
58 static SymbolizedStack
*New(uptr addr
);
59 // Deletes current, and all subsequent frames in the linked list.
60 // The object cannot be accessed after the call to this function.
67 // For now, DataInfo is used to describe global variable.
69 // Owns all the string members. Storage for them is
70 // (de)allocated using sanitizer internal allocator.
73 ModuleArch module_arch
;
86 char *function_name
= nullptr;
88 char *decl_file
= nullptr;
89 unsigned decl_line
= 0;
91 bool has_frame_offset
= false;
92 bool has_size
= false;
93 bool has_tag_offset
= false;
105 ModuleArch module_arch
;
107 InternalMmapVector
<LocalInfo
> locals
;
111 class SymbolizerTool
;
113 class Symbolizer final
{
115 /// Initialize and return platform-specific implementation of symbolizer
116 /// (if it wasn't already initialized).
117 static Symbolizer
*GetOrInit();
118 static void LateInitialize();
119 // Returns a list of symbolized frames for a given address (containing
120 // all inlined functions, if necessary).
121 SymbolizedStack
*SymbolizePC(uptr address
);
122 bool SymbolizeData(uptr address
, DataInfo
*info
);
123 bool SymbolizeFrame(uptr address
, FrameInfo
*info
);
125 // The module names Symbolizer returns are stable and unique for every given
126 // module. It is safe to store and compare them as pointers.
127 bool GetModuleNameAndOffsetForPC(uptr pc
, const char **module_name
,
128 uptr
*module_address
);
129 const char *GetModuleNameForPc(uptr pc
) {
130 const char *module_name
= nullptr;
132 if (GetModuleNameAndOffsetForPC(pc
, &module_name
, &unused
))
137 // Release internal caches (if any).
139 // Attempts to demangle the provided C++ mangled name.
140 const char *Demangle(const char *name
);
142 // Allow user to install hooks that would be called before/after Symbolizer
143 // does the actual file/line info fetching. Specific sanitizers may need this
144 // to distinguish system library calls made in user code from calls made
145 // during in-process symbolization.
146 typedef void (*StartSymbolizationHook
)();
147 typedef void (*EndSymbolizationHook
)();
148 // May be called at most once.
149 void AddHooks(StartSymbolizationHook start_hook
,
150 EndSymbolizationHook end_hook
);
152 void RefreshModules();
153 const LoadedModule
*FindModuleForAddress(uptr address
);
155 void InvalidateModuleList();
158 // GetModuleNameAndOffsetForPC has to return a string to the caller.
159 // Since the corresponding module might get unloaded later, we should create
160 // our owned copies of the strings that we can safely return.
161 // ModuleNameOwner does not provide any synchronization, thus calls to
162 // its method should be protected by |mu_|.
163 class ModuleNameOwner
{
165 explicit ModuleNameOwner(Mutex
*synchronized_by
)
166 : last_match_(nullptr), mu_(synchronized_by
) {
167 storage_
.reserve(kInitialCapacity
);
169 const char *GetOwnedCopy(const char *str
);
172 static const uptr kInitialCapacity
= 1000;
173 InternalMmapVector
<const char*> storage_
;
174 const char *last_match_
;
179 /// Platform-specific function for creating a Symbolizer object.
180 static Symbolizer
*PlatformInit();
182 bool FindModuleNameAndOffsetForAddress(uptr address
, const char **module_name
,
184 ModuleArch
*module_arch
);
185 ListOfModules modules_
;
186 ListOfModules fallback_modules_
;
187 // If stale, need to reload the modules before looking up addresses.
190 // Platform-specific default demangler, must not return nullptr.
191 const char *PlatformDemangle(const char *name
);
193 static Symbolizer
*symbolizer_
;
194 static StaticSpinMutex init_mu_
;
196 // Mutex locked from public methods of |Symbolizer|, so that the internals
197 // (including individual symbolizer tools and platform-specific methods) are
198 // always synchronized.
201 IntrusiveList
<SymbolizerTool
> tools_
;
203 explicit Symbolizer(IntrusiveList
<SymbolizerTool
> tools
);
205 static LowLevelAllocator symbolizer_allocator_
;
207 StartSymbolizationHook start_hook_
;
208 EndSymbolizationHook end_hook_
;
209 class SymbolizerScope
{
211 explicit SymbolizerScope(const Symbolizer
*sym
);
214 const Symbolizer
*sym_
;
218 #ifdef SANITIZER_WINDOWS
219 void InitializeDbgHelpIfNeeded();
222 } // namespace __sanitizer
224 #endif // SANITIZER_SYMBOLIZER_H