]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
Merge from head
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_symbolizer_libcdep.cc
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
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
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
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
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
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
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
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
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
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
134 void Symbolizer::PrepareForSandboxing() {
135   BlockingMutexLock l(&mu_);
136   PlatformPrepareForSandboxing();
137 }
138
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
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
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