blob: 160f55d422ca190dd4435432f29dd4c03361416f [file] [log] [blame]
Peter Collingbournec1a1ed62013-10-25 23:03:29 +00001//===-- 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
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070014#include "sanitizer_allocator_internal.h"
Peter Collingbournec1a1ed62013-10-25 23:03:29 +000015#include "sanitizer_internal_defs.h"
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070016#include "sanitizer_symbolizer_internal.h"
Peter Collingbournec1a1ed62013-10-25 23:03:29 +000017
18namespace __sanitizer {
19
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070020const 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
30const 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
40const 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
50const 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
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070063SymbolizedStack *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
82bool 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
101bool 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
114void 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
123const 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
134void Symbolizer::PrepareForSandboxing() {
135 BlockingMutexLock l(&mu_);
136 PlatformPrepareForSandboxing();
137}
138
139bool 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
150LoadedModule *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
Peter Collingbournec1a1ed62013-10-25 23:03:29 +0000178Symbolizer *Symbolizer::GetOrInit() {
Alexey Samsonove00495a2013-10-30 17:05:37 +0000179 SpinMutexLock l(&init_mu_);
Stephen Hines6d186232014-11-26 17:56:19 -0800180 if (symbolizer_)
181 return symbolizer_;
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -0700182 symbolizer_ = PlatformInit();
183 CHECK(symbolizer_);
184 return symbolizer_;
Peter Collingbournec1a1ed62013-10-25 23:03:29 +0000185}
186
187} // namespace __sanitizer