1 //===-- sanitizer_symbolizer_libcdep.cc -----------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_allocator_internal.h"
15 #include "sanitizer_internal_defs.h"
16 #include "sanitizer_symbolizer_internal.h"
18 namespace __sanitizer {
20 const char *ExtractToken(const char *str, const char *delims, char **result) {
21 uptr prefix_len = internal_strcspn(str, delims);
22 *result = (char*)InternalAlloc(prefix_len + 1);
23 internal_memcpy(*result, str, prefix_len);
24 (*result)[prefix_len] = '\0';
25 const char *prefix_end = str + prefix_len;
26 if (*prefix_end != '\0') prefix_end++;
30 const char *ExtractInt(const char *str, const char *delims, int *result) {
32 const char *ret = ExtractToken(str, delims, &buff);
34 *result = (int)internal_atoll(buff);
40 const char *ExtractUptr(const char *str, const char *delims, uptr *result) {
42 const char *ret = ExtractToken(str, delims, &buff);
44 *result = (uptr)internal_atoll(buff);
50 const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
52 const char *found_delimiter = internal_strstr(str, delimiter);
54 found_delimiter ? found_delimiter - str : internal_strlen(str);
55 *result = (char *)InternalAlloc(prefix_len + 1);
56 internal_memcpy(*result, str, prefix_len);
57 (*result)[prefix_len] = '\0';
58 const char *prefix_end = str + prefix_len;
59 if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter);
63 SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
64 BlockingMutexLock l(&mu_);
65 const char *module_name;
67 SymbolizedStack *res = SymbolizedStack::New(addr);
68 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
70 // Always fill data about module name and offset.
71 res->info.FillModuleInfo(module_name, module_offset);
72 for (auto iter = Iterator(&tools_); iter.hasNext();) {
73 auto *tool = iter.next();
74 SymbolizerScope sym_scope(this);
75 if (tool->SymbolizePC(addr, res)) {
82 bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
83 BlockingMutexLock l(&mu_);
84 const char *module_name;
86 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
89 info->module = internal_strdup(module_name);
90 info->module_offset = module_offset;
91 for (auto iter = Iterator(&tools_); iter.hasNext();) {
92 auto *tool = iter.next();
93 SymbolizerScope sym_scope(this);
94 if (tool->SymbolizeData(addr, info)) {
101 bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
102 uptr *module_address) {
103 BlockingMutexLock l(&mu_);
104 const char *internal_module_name = nullptr;
105 if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name,
110 *module_name = module_names_.GetOwnedCopy(internal_module_name);
114 void Symbolizer::Flush() {
115 BlockingMutexLock l(&mu_);
116 for (auto iter = Iterator(&tools_); iter.hasNext();) {
117 auto *tool = iter.next();
118 SymbolizerScope sym_scope(this);
123 const char *Symbolizer::Demangle(const char *name) {
124 BlockingMutexLock l(&mu_);
125 for (auto iter = Iterator(&tools_); iter.hasNext();) {
126 auto *tool = iter.next();
127 SymbolizerScope sym_scope(this);
128 if (const char *demangled = tool->Demangle(name))
131 return PlatformDemangle(name);
134 void Symbolizer::PrepareForSandboxing() {
135 BlockingMutexLock l(&mu_);
136 PlatformPrepareForSandboxing();
139 bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,
140 const char **module_name,
141 uptr *module_offset) {
142 LoadedModule *module = FindModuleForAddress(address);
145 *module_name = module->full_name();
146 *module_offset = address - module->base_address();
150 LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
151 bool modules_were_reloaded = false;
152 if (!modules_fresh_) {
153 for (uptr i = 0; i < n_modules_; i++)
156 GetListOfModules(modules_, kMaxNumberOfModules, /* filter */ nullptr);
157 CHECK_GT(n_modules_, 0);
158 CHECK_LT(n_modules_, kMaxNumberOfModules);
159 modules_fresh_ = true;
160 modules_were_reloaded = true;
162 for (uptr i = 0; i < n_modules_; i++) {
163 if (modules_[i].containsAddress(address)) {
167 // Reload the modules and look up again, if we haven't tried it yet.
168 if (!modules_were_reloaded) {
169 // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors.
170 // It's too aggressive to reload the list of modules each time we fail
171 // to find a module for a given address.
172 modules_fresh_ = false;
173 return FindModuleForAddress(address);
178 Symbolizer *Symbolizer::GetOrInit() {
179 SpinMutexLock l(&init_mu_);
182 symbolizer_ = PlatformInit();
187 } // namespace __sanitizer