1 //===-- sanitizer_symbolizer_libcdep.cc -----------------------------------===//
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 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 //===----------------------------------------------------------------------===//
13
14 #include "sanitizer_allocator_internal.h"
15 #include "sanitizer_internal_defs.h"
16 #include "sanitizer_symbolizer_internal.h"
17
18 namespace __sanitizer {
19
ExtractToken(const char * str,const char * delims,char ** result)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++;
27 return prefix_end;
28 }
29
ExtractInt(const char * str,const char * delims,int * result)30 const char *ExtractInt(const char *str, const char *delims, int *result) {
31 char *buff;
32 const char *ret = ExtractToken(str, delims, &buff);
33 if (buff != 0) {
34 *result = (int)internal_atoll(buff);
35 }
36 InternalFree(buff);
37 return ret;
38 }
39
ExtractUptr(const char * str,const char * delims,uptr * result)40 const char *ExtractUptr(const char *str, const char *delims, uptr *result) {
41 char *buff;
42 const char *ret = ExtractToken(str, delims, &buff);
43 if (buff != 0) {
44 *result = (uptr)internal_atoll(buff);
45 }
46 InternalFree(buff);
47 return ret;
48 }
49
ExtractTokenUpToDelimiter(const char * str,const char * delimiter,char ** result)50 const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
51 char **result) {
52 const char *found_delimiter = internal_strstr(str, delimiter);
53 uptr prefix_len =
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);
60 return prefix_end;
61 }
62
SymbolizePC(uptr addr)63 SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
64 BlockingMutexLock l(&mu_);
65 const char *module_name;
66 uptr module_offset;
67 SymbolizedStack *res = SymbolizedStack::New(addr);
68 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
69 return res;
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)) {
76 return res;
77 }
78 }
79 return res;
80 }
81
SymbolizeData(uptr addr,DataInfo * info)82 bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
83 BlockingMutexLock l(&mu_);
84 const char *module_name;
85 uptr module_offset;
86 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
87 return false;
88 info->Clear();
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)) {
95 return true;
96 }
97 }
98 return true;
99 }
100
GetModuleNameAndOffsetForPC(uptr pc,const char ** module_name,uptr * module_address)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,
106 module_address))
107 return false;
108
109 if (module_name)
110 *module_name = module_names_.GetOwnedCopy(internal_module_name);
111 return true;
112 }
113
Flush()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);
119 tool->Flush();
120 }
121 }
122
Demangle(const char * name)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))
129 return demangled;
130 }
131 return PlatformDemangle(name);
132 }
133
PrepareForSandboxing()134 void Symbolizer::PrepareForSandboxing() {
135 BlockingMutexLock l(&mu_);
136 PlatformPrepareForSandboxing();
137 }
138
FindModuleNameAndOffsetForAddress(uptr address,const char ** module_name,uptr * module_offset)139 bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,
140 const char **module_name,
141 uptr *module_offset) {
142 LoadedModule *module = FindModuleForAddress(address);
143 if (module == 0)
144 return false;
145 *module_name = module->full_name();
146 *module_offset = address - module->base_address();
147 return true;
148 }
149
FindModuleForAddress(uptr 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++)
154 modules_[i].clear();
155 n_modules_ =
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;
161 }
162 for (uptr i = 0; i < n_modules_; i++) {
163 if (modules_[i].containsAddress(address)) {
164 return &modules_[i];
165 }
166 }
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);
174 }
175 return 0;
176 }
177
GetOrInit()178 Symbolizer *Symbolizer::GetOrInit() {
179 SpinMutexLock l(&init_mu_);
180 if (symbolizer_)
181 return symbolizer_;
182 symbolizer_ = PlatformInit();
183 CHECK(symbolizer_);
184 return symbolizer_;
185 }
186
187 } // namespace __sanitizer
188