/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/ModuleList.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ModuleList.cpp ----------------------------------------------------===// |
2 | | // |
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 |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "lldb/Core/ModuleList.h" |
10 | | #include "lldb/Core/Module.h" |
11 | | #include "lldb/Core/ModuleSpec.h" |
12 | | #include "lldb/Host/FileSystem.h" |
13 | | #include "lldb/Interpreter/OptionValueFileSpec.h" |
14 | | #include "lldb/Interpreter/OptionValueFileSpecList.h" |
15 | | #include "lldb/Interpreter/OptionValueProperties.h" |
16 | | #include "lldb/Interpreter/Property.h" |
17 | | #include "lldb/Symbol/LocateSymbolFile.h" |
18 | | #include "lldb/Symbol/ObjectFile.h" |
19 | | #include "lldb/Symbol/SymbolContext.h" |
20 | | #include "lldb/Symbol/TypeList.h" |
21 | | #include "lldb/Symbol/VariableList.h" |
22 | | #include "lldb/Utility/ArchSpec.h" |
23 | | #include "lldb/Utility/ConstString.h" |
24 | | #include "lldb/Utility/FileSpecList.h" |
25 | | #include "lldb/Utility/LLDBLog.h" |
26 | | #include "lldb/Utility/Log.h" |
27 | | #include "lldb/Utility/UUID.h" |
28 | | #include "lldb/lldb-defines.h" |
29 | | |
30 | | #if defined(_WIN32) |
31 | | #include "lldb/Host/windows/PosixApi.h" |
32 | | #endif |
33 | | |
34 | | #include "clang/Driver/Driver.h" |
35 | | #include "llvm/ADT/StringRef.h" |
36 | | #include "llvm/Support/FileSystem.h" |
37 | | #include "llvm/Support/Threading.h" |
38 | | #include "llvm/Support/raw_ostream.h" |
39 | | |
40 | | #include <chrono> |
41 | | #include <memory> |
42 | | #include <mutex> |
43 | | #include <string> |
44 | | #include <utility> |
45 | | |
46 | | namespace lldb_private { |
47 | | class Function; |
48 | | } |
49 | | namespace lldb_private { |
50 | | class RegularExpression; |
51 | | } |
52 | | namespace lldb_private { |
53 | | class Stream; |
54 | | } |
55 | | namespace lldb_private { |
56 | | class SymbolFile; |
57 | | } |
58 | | namespace lldb_private { |
59 | | class Target; |
60 | | } |
61 | | |
62 | | using namespace lldb; |
63 | | using namespace lldb_private; |
64 | | |
65 | | namespace { |
66 | | |
67 | | #define LLDB_PROPERTIES_modulelist |
68 | | #include "CoreProperties.inc" |
69 | | |
70 | | enum { |
71 | | #define LLDB_PROPERTIES_modulelist |
72 | | #include "CorePropertiesEnum.inc" |
73 | | }; |
74 | | |
75 | | } // namespace |
76 | | |
77 | 3.85k | ModuleListProperties::ModuleListProperties() { |
78 | 3.85k | m_collection_sp = |
79 | 3.85k | std::make_shared<OptionValueProperties>(ConstString("symbols")); |
80 | 3.85k | m_collection_sp->Initialize(g_modulelist_properties); |
81 | 3.85k | m_collection_sp->SetValueChangedCallback(ePropertySymLinkPaths, |
82 | 3.85k | [this] { UpdateSymlinkMappings(); }8 ); |
83 | | |
84 | 3.85k | llvm::SmallString<128> path; |
85 | 3.85k | if (clang::driver::Driver::getDefaultModuleCachePath(path)) { |
86 | 3.85k | lldbassert(SetClangModulesCachePath(FileSpec(path))); |
87 | 3.85k | } |
88 | | |
89 | 3.85k | path.clear(); |
90 | 3.85k | if (llvm::sys::path::cache_directory(path)) { |
91 | 3.85k | llvm::sys::path::append(path, "lldb"); |
92 | 3.85k | llvm::sys::path::append(path, "IndexCache"); |
93 | 3.85k | lldbassert(SetLLDBIndexCachePath(FileSpec(path))); |
94 | 3.85k | } |
95 | | |
96 | 3.85k | } |
97 | | |
98 | 230k | bool ModuleListProperties::GetEnableExternalLookup() const { |
99 | 230k | const uint32_t idx = ePropertyEnableExternalLookup; |
100 | 230k | return GetPropertyAtIndexAs<bool>( |
101 | 230k | idx, g_modulelist_properties[idx].default_uint_value != 0); |
102 | 230k | } |
103 | | |
104 | 109 | bool ModuleListProperties::SetEnableExternalLookup(bool new_value) { |
105 | 109 | return SetPropertyAtIndex(ePropertyEnableExternalLookup, new_value); |
106 | 109 | } |
107 | | |
108 | 5.32k | bool ModuleListProperties::GetEnableBackgroundLookup() const { |
109 | 5.32k | const uint32_t idx = ePropertyEnableBackgroundLookup; |
110 | 5.32k | return GetPropertyAtIndexAs<bool>( |
111 | 5.32k | idx, g_modulelist_properties[idx].default_uint_value != 0); |
112 | 5.32k | } |
113 | | |
114 | 1.64k | FileSpec ModuleListProperties::GetClangModulesCachePath() const { |
115 | 1.64k | const uint32_t idx = ePropertyClangModulesCachePath; |
116 | 1.64k | return GetPropertyAtIndexAs<FileSpec>(idx, {}); |
117 | 1.64k | } |
118 | | |
119 | 3.85k | bool ModuleListProperties::SetClangModulesCachePath(const FileSpec &path) { |
120 | 3.85k | const uint32_t idx = ePropertyClangModulesCachePath; |
121 | 3.85k | return SetPropertyAtIndex(idx, path); |
122 | 3.85k | } |
123 | | |
124 | 4 | FileSpec ModuleListProperties::GetLLDBIndexCachePath() const { |
125 | 4 | const uint32_t idx = ePropertyLLDBIndexCachePath; |
126 | 4 | return GetPropertyAtIndexAs<FileSpec>(idx, {}); |
127 | 4 | } |
128 | | |
129 | 3.85k | bool ModuleListProperties::SetLLDBIndexCachePath(const FileSpec &path) { |
130 | 3.85k | const uint32_t idx = ePropertyLLDBIndexCachePath; |
131 | 3.85k | return SetPropertyAtIndex(idx, path); |
132 | 3.85k | } |
133 | | |
134 | 238k | bool ModuleListProperties::GetEnableLLDBIndexCache() const { |
135 | 238k | const uint32_t idx = ePropertyEnableLLDBIndexCache; |
136 | 238k | return GetPropertyAtIndexAs<bool>( |
137 | 238k | idx, g_modulelist_properties[idx].default_uint_value != 0); |
138 | 238k | } |
139 | | |
140 | 0 | bool ModuleListProperties::SetEnableLLDBIndexCache(bool new_value) { |
141 | 0 | return SetPropertyAtIndex(ePropertyEnableLLDBIndexCache, new_value); |
142 | 0 | } |
143 | | |
144 | 4 | uint64_t ModuleListProperties::GetLLDBIndexCacheMaxByteSize() { |
145 | 4 | const uint32_t idx = ePropertyLLDBIndexCacheMaxByteSize; |
146 | 4 | return GetPropertyAtIndexAs<uint64_t>( |
147 | 4 | idx, g_modulelist_properties[idx].default_uint_value); |
148 | 4 | } |
149 | | |
150 | 4 | uint64_t ModuleListProperties::GetLLDBIndexCacheMaxPercent() { |
151 | 4 | const uint32_t idx = ePropertyLLDBIndexCacheMaxPercent; |
152 | 4 | return GetPropertyAtIndexAs<uint64_t>( |
153 | 4 | idx, g_modulelist_properties[idx].default_uint_value); |
154 | 4 | } |
155 | | |
156 | 4 | uint64_t ModuleListProperties::GetLLDBIndexCacheExpirationDays() { |
157 | 4 | const uint32_t idx = ePropertyLLDBIndexCacheExpirationDays; |
158 | 4 | return GetPropertyAtIndexAs<uint64_t>( |
159 | 4 | idx, g_modulelist_properties[idx].default_uint_value); |
160 | 4 | } |
161 | | |
162 | 8 | void ModuleListProperties::UpdateSymlinkMappings() { |
163 | 8 | FileSpecList list = |
164 | 8 | GetPropertyAtIndexAs<FileSpecList>(ePropertySymLinkPaths, {}); |
165 | 8 | llvm::sys::ScopedWriter lock(m_symlink_paths_mutex); |
166 | 8 | const bool notify = false; |
167 | 8 | m_symlink_paths.Clear(notify); |
168 | 8 | for (FileSpec symlink : list) { |
169 | 2 | FileSpec resolved; |
170 | 2 | Status status = FileSystem::Instance().Readlink(symlink, resolved); |
171 | 2 | if (status.Success()) |
172 | 2 | m_symlink_paths.Append(symlink.GetPath(), resolved.GetPath(), notify); |
173 | 2 | } |
174 | 8 | } |
175 | | |
176 | 118k | PathMappingList ModuleListProperties::GetSymlinkMappings() const { |
177 | 118k | llvm::sys::ScopedReader lock(m_symlink_paths_mutex); |
178 | 118k | return m_symlink_paths; |
179 | 118k | } |
180 | | |
181 | 115k | bool ModuleListProperties::GetLoadSymbolOnDemand() { |
182 | 115k | const uint32_t idx = ePropertyLoadSymbolOnDemand; |
183 | 115k | return GetPropertyAtIndexAs<bool>( |
184 | 115k | idx, g_modulelist_properties[idx].default_uint_value != 0); |
185 | 115k | } |
186 | | |
187 | 391k | ModuleList::ModuleList() : m_modules(), m_modules_mutex() {} |
188 | | |
189 | 16.2k | ModuleList::ModuleList(const ModuleList &rhs) : m_modules(), m_modules_mutex() { |
190 | 16.2k | std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); |
191 | 16.2k | std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); |
192 | 16.2k | m_modules = rhs.m_modules; |
193 | 16.2k | } |
194 | | |
195 | | ModuleList::ModuleList(ModuleList::Notifier *notifier) |
196 | 8.60k | : m_modules(), m_modules_mutex(), m_notifier(notifier) {} |
197 | | |
198 | 87 | const ModuleList &ModuleList::operator=(const ModuleList &rhs) { |
199 | 87 | if (this != &rhs) { |
200 | 87 | std::lock(m_modules_mutex, rhs.m_modules_mutex); |
201 | 87 | std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex, |
202 | 87 | std::adopt_lock); |
203 | 87 | std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex, |
204 | 87 | std::adopt_lock); |
205 | 87 | m_modules = rhs.m_modules; |
206 | 87 | } |
207 | 87 | return *this; |
208 | 87 | } |
209 | | |
210 | 412k | ModuleList::~ModuleList() = default; |
211 | | |
212 | 912k | void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) { |
213 | 912k | if (module_sp) { |
214 | 912k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
215 | 912k | m_modules.push_back(module_sp); |
216 | 912k | if (use_notifier && m_notifier575k ) |
217 | 7.46k | m_notifier->NotifyModuleAdded(*this, module_sp); |
218 | 912k | } |
219 | 912k | } |
220 | | |
221 | 912k | void ModuleList::Append(const ModuleSP &module_sp, bool notify) { |
222 | 912k | AppendImpl(module_sp, notify); |
223 | 912k | } |
224 | | |
225 | | void ModuleList::ReplaceEquivalent( |
226 | | const ModuleSP &module_sp, |
227 | 111k | llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) { |
228 | 111k | if (module_sp) { |
229 | 111k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
230 | | |
231 | | // First remove any equivalent modules. Equivalent modules are modules |
232 | | // whose path, platform path and architecture match. |
233 | 111k | ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(), |
234 | 111k | module_sp->GetArchitecture()); |
235 | 111k | equivalent_module_spec.GetPlatformFileSpec() = |
236 | 111k | module_sp->GetPlatformFileSpec(); |
237 | | |
238 | 111k | size_t idx = 0; |
239 | 3.74M | while (idx < m_modules.size()) { |
240 | 3.62M | ModuleSP test_module_sp(m_modules[idx]); |
241 | 3.62M | if (test_module_sp->MatchesModuleSpec(equivalent_module_spec)) { |
242 | 5 | if (old_modules) |
243 | 5 | old_modules->push_back(test_module_sp); |
244 | 5 | RemoveImpl(m_modules.begin() + idx); |
245 | 3.62M | } else { |
246 | 3.62M | ++idx; |
247 | 3.62M | } |
248 | 3.62M | } |
249 | | // Now add the new module to the list |
250 | 111k | Append(module_sp); |
251 | 111k | } |
252 | 111k | } |
253 | | |
254 | 452k | bool ModuleList::AppendIfNeeded(const ModuleSP &new_module, bool notify) { |
255 | 452k | if (new_module) { |
256 | 452k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
257 | 14.3M | for (const ModuleSP &module_sp : m_modules) { |
258 | 14.3M | if (module_sp.get() == new_module.get()) |
259 | 113k | return false; // Already in the list |
260 | 14.3M | } |
261 | | // Only push module_sp on the list if it wasn't already in there. |
262 | 339k | Append(new_module, notify); |
263 | 339k | return true; |
264 | 452k | } |
265 | 0 | return false; |
266 | 452k | } |
267 | | |
268 | 0 | void ModuleList::Append(const ModuleList &module_list) { |
269 | 0 | for (auto pos : module_list.m_modules) |
270 | 0 | Append(pos); |
271 | 0 | } |
272 | | |
273 | 3 | bool ModuleList::AppendIfNeeded(const ModuleList &module_list) { |
274 | 3 | bool any_in = false; |
275 | 3 | for (auto pos : module_list.m_modules) { |
276 | 3 | if (AppendIfNeeded(pos)) |
277 | 0 | any_in = true; |
278 | 3 | } |
279 | 3 | return any_in; |
280 | 3 | } |
281 | | |
282 | 113k | bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) { |
283 | 113k | if (module_sp) { |
284 | 113k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
285 | 113k | collection::iterator pos, end = m_modules.end(); |
286 | 407k | for (pos = m_modules.begin(); pos != end; ++pos293k ) { |
287 | 407k | if (pos->get() == module_sp.get()) { |
288 | 113k | m_modules.erase(pos); |
289 | 113k | if (use_notifier && m_notifier4.66k ) |
290 | 4.65k | m_notifier->NotifyModuleRemoved(*this, module_sp); |
291 | 113k | return true; |
292 | 113k | } |
293 | 407k | } |
294 | 113k | } |
295 | 0 | return false; |
296 | 113k | } |
297 | | |
298 | | ModuleList::collection::iterator |
299 | | ModuleList::RemoveImpl(ModuleList::collection::iterator pos, |
300 | 105k | bool use_notifier) { |
301 | 105k | ModuleSP module_sp(*pos); |
302 | 105k | collection::iterator retval = m_modules.erase(pos); |
303 | 105k | if (use_notifier && m_notifier) |
304 | 0 | m_notifier->NotifyModuleRemoved(*this, module_sp); |
305 | 105k | return retval; |
306 | 105k | } |
307 | | |
308 | 113k | bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) { |
309 | 113k | return RemoveImpl(module_sp, notify); |
310 | 113k | } |
311 | | |
312 | | bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp, |
313 | 1 | const lldb::ModuleSP &new_module_sp) { |
314 | 1 | if (!RemoveImpl(old_module_sp, false)) |
315 | 0 | return false; |
316 | 1 | AppendImpl(new_module_sp, false); |
317 | 1 | if (m_notifier) |
318 | 1 | m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp); |
319 | 1 | return true; |
320 | 1 | } |
321 | | |
322 | 1 | bool ModuleList::RemoveIfOrphaned(const Module *module_ptr) { |
323 | 1 | if (module_ptr) { |
324 | 1 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
325 | 1 | collection::iterator pos, end = m_modules.end(); |
326 | 2 | for (pos = m_modules.begin(); pos != end; ++pos1 ) { |
327 | 1 | if (pos->get() == module_ptr) { |
328 | 0 | if (pos->unique()) { |
329 | 0 | pos = RemoveImpl(pos); |
330 | 0 | return true; |
331 | 0 | } else |
332 | 0 | return false; |
333 | 0 | } |
334 | 1 | } |
335 | 1 | } |
336 | 1 | return false; |
337 | 1 | } |
338 | | |
339 | 3.02k | size_t ModuleList::RemoveOrphans(bool mandatory) { |
340 | 3.02k | std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock); |
341 | | |
342 | 3.02k | if (mandatory) { |
343 | 0 | lock.lock(); |
344 | 3.02k | } else { |
345 | | // Not mandatory, remove orphans if we can get the mutex |
346 | 3.02k | if (!lock.try_lock()) |
347 | 0 | return 0; |
348 | 3.02k | } |
349 | 3.02k | size_t remove_count = 0; |
350 | | // Modules might hold shared pointers to other modules, so removing one |
351 | | // module might make other other modules orphans. Keep removing modules until |
352 | | // there are no further modules that can be removed. |
353 | 3.02k | bool made_progress = true; |
354 | 8.25k | while (made_progress) { |
355 | | // Keep track if we make progress this iteration. |
356 | 5.23k | made_progress = false; |
357 | 5.23k | collection::iterator pos = m_modules.begin(); |
358 | 111k | while (pos != m_modules.end()) { |
359 | 105k | if (pos->unique()) { |
360 | 105k | pos = RemoveImpl(pos); |
361 | 105k | ++remove_count; |
362 | | // We did make progress. |
363 | 105k | made_progress = true; |
364 | 105k | } else { |
365 | 223 | ++pos; |
366 | 223 | } |
367 | 105k | } |
368 | 5.23k | } |
369 | 3.02k | return remove_count; |
370 | 3.02k | } |
371 | | |
372 | 2.11k | size_t ModuleList::Remove(ModuleList &module_list) { |
373 | 2.11k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
374 | 2.11k | size_t num_removed = 0; |
375 | 2.11k | collection::iterator pos, end = module_list.m_modules.end(); |
376 | 111k | for (pos = module_list.m_modules.begin(); pos != end; ++pos109k ) { |
377 | 109k | if (Remove(*pos, false /* notify */)) |
378 | 109k | ++num_removed; |
379 | 109k | } |
380 | 2.11k | if (m_notifier) |
381 | 2.11k | m_notifier->NotifyModulesRemoved(module_list); |
382 | 2.11k | return num_removed; |
383 | 2.11k | } |
384 | | |
385 | 5.21k | void ModuleList::Clear() { ClearImpl(); } |
386 | | |
387 | 0 | void ModuleList::Destroy() { ClearImpl(); } |
388 | | |
389 | 5.21k | void ModuleList::ClearImpl(bool use_notifier) { |
390 | 5.21k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
391 | 5.21k | if (use_notifier && m_notifier) |
392 | 5.20k | m_notifier->NotifyWillClearList(*this); |
393 | 5.21k | m_modules.clear(); |
394 | 5.21k | } |
395 | | |
396 | 348 | Module *ModuleList::GetModulePointerAtIndex(size_t idx) const { |
397 | 348 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
398 | 348 | if (idx < m_modules.size()) |
399 | 348 | return m_modules[idx].get(); |
400 | 0 | return nullptr; |
401 | 348 | } |
402 | | |
403 | 613k | ModuleSP ModuleList::GetModuleAtIndex(size_t idx) const { |
404 | 613k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
405 | 613k | return GetModuleAtIndexUnlocked(idx); |
406 | 613k | } |
407 | | |
408 | 614k | ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const { |
409 | 614k | ModuleSP module_sp; |
410 | 614k | if (idx < m_modules.size()) |
411 | 593k | module_sp = m_modules[idx]; |
412 | 614k | return module_sp; |
413 | 614k | } |
414 | | |
415 | | void ModuleList::FindFunctions(ConstString name, |
416 | | FunctionNameType name_type_mask, |
417 | | const ModuleFunctionSearchOptions &options, |
418 | 28.1k | SymbolContextList &sc_list) const { |
419 | 28.1k | const size_t old_size = sc_list.GetSize(); |
420 | | |
421 | 28.1k | if (name_type_mask & eFunctionNameTypeAuto) { |
422 | 17.2k | Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); |
423 | | |
424 | 17.2k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
425 | 2.10M | for (const ModuleSP &module_sp : m_modules) { |
426 | 2.10M | module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options, |
427 | 2.10M | sc_list); |
428 | 2.10M | } |
429 | | |
430 | 17.2k | const size_t new_size = sc_list.GetSize(); |
431 | | |
432 | 17.2k | if (old_size < new_size) |
433 | 17.2k | lookup_info.Prune(sc_list, old_size); |
434 | 17.2k | } else { |
435 | 10.8k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
436 | 669k | for (const ModuleSP &module_sp : m_modules) { |
437 | 669k | module_sp->FindFunctions(name, CompilerDeclContext(), name_type_mask, |
438 | 669k | options, sc_list); |
439 | 669k | } |
440 | 10.8k | } |
441 | 28.1k | } |
442 | | |
443 | | void ModuleList::FindFunctionSymbols(ConstString name, |
444 | | lldb::FunctionNameType name_type_mask, |
445 | 166 | SymbolContextList &sc_list) { |
446 | 166 | const size_t old_size = sc_list.GetSize(); |
447 | | |
448 | 166 | if (name_type_mask & eFunctionNameTypeAuto) { |
449 | 166 | Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); |
450 | | |
451 | 166 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
452 | 7.10k | for (const ModuleSP &module_sp : m_modules) { |
453 | 7.10k | module_sp->FindFunctionSymbols(lookup_info.GetLookupName(), |
454 | 7.10k | lookup_info.GetNameTypeMask(), sc_list); |
455 | 7.10k | } |
456 | | |
457 | 166 | const size_t new_size = sc_list.GetSize(); |
458 | | |
459 | 166 | if (old_size < new_size) |
460 | 166 | lookup_info.Prune(sc_list, old_size); |
461 | 166 | } else { |
462 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
463 | 0 | for (const ModuleSP &module_sp : m_modules) { |
464 | 0 | module_sp->FindFunctionSymbols(name, name_type_mask, sc_list); |
465 | 0 | } |
466 | 0 | } |
467 | 166 | } |
468 | | |
469 | | void ModuleList::FindFunctions(const RegularExpression &name, |
470 | | const ModuleFunctionSearchOptions &options, |
471 | 0 | SymbolContextList &sc_list) { |
472 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
473 | 0 | for (const ModuleSP &module_sp : m_modules) |
474 | 0 | module_sp->FindFunctions(name, options, sc_list); |
475 | 0 | } |
476 | | |
477 | | void ModuleList::FindCompileUnits(const FileSpec &path, |
478 | 12 | SymbolContextList &sc_list) const { |
479 | 12 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
480 | 12 | for (const ModuleSP &module_sp : m_modules) |
481 | 504 | module_sp->FindCompileUnits(path, sc_list); |
482 | 12 | } |
483 | | |
484 | | void ModuleList::FindGlobalVariables(ConstString name, size_t max_matches, |
485 | 3.11k | VariableList &variable_list) const { |
486 | 3.11k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
487 | 145k | for (const ModuleSP &module_sp : m_modules) { |
488 | 145k | module_sp->FindGlobalVariables(name, CompilerDeclContext(), max_matches, |
489 | 145k | variable_list); |
490 | 145k | } |
491 | 3.11k | } |
492 | | |
493 | | void ModuleList::FindGlobalVariables(const RegularExpression ®ex, |
494 | | size_t max_matches, |
495 | 0 | VariableList &variable_list) const { |
496 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
497 | 0 | for (const ModuleSP &module_sp : m_modules) |
498 | 0 | module_sp->FindGlobalVariables(regex, max_matches, variable_list); |
499 | 0 | } |
500 | | |
501 | | void ModuleList::FindSymbolsWithNameAndType(ConstString name, |
502 | | SymbolType symbol_type, |
503 | 12.1k | SymbolContextList &sc_list) const { |
504 | 12.1k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
505 | 12.1k | for (const ModuleSP &module_sp : m_modules) |
506 | 609k | module_sp->FindSymbolsWithNameAndType(name, symbol_type, sc_list); |
507 | 12.1k | } |
508 | | |
509 | | void ModuleList::FindSymbolsMatchingRegExAndType( |
510 | | const RegularExpression ®ex, lldb::SymbolType symbol_type, |
511 | 1.39k | SymbolContextList &sc_list) const { |
512 | 1.39k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
513 | 1.39k | for (const ModuleSP &module_sp : m_modules) |
514 | 1.69k | module_sp->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list); |
515 | 1.39k | } |
516 | | |
517 | | void ModuleList::FindModules(const ModuleSpec &module_spec, |
518 | 336k | ModuleList &matching_module_list) const { |
519 | 336k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
520 | 15.1M | for (const ModuleSP &module_sp : m_modules) { |
521 | 15.1M | if (module_sp->MatchesModuleSpec(module_spec)) |
522 | 115k | matching_module_list.Append(module_sp); |
523 | 15.1M | } |
524 | 336k | } |
525 | | |
526 | 0 | ModuleSP ModuleList::FindModule(const Module *module_ptr) const { |
527 | 0 | ModuleSP module_sp; |
528 | | |
529 | | // Scope for "locker" |
530 | 0 | { |
531 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
532 | 0 | collection::const_iterator pos, end = m_modules.end(); |
533 | |
|
534 | 0 | for (pos = m_modules.begin(); pos != end; ++pos) { |
535 | 0 | if ((*pos).get() == module_ptr) { |
536 | 0 | module_sp = (*pos); |
537 | 0 | break; |
538 | 0 | } |
539 | 0 | } |
540 | 0 | } |
541 | 0 | return module_sp; |
542 | 0 | } |
543 | | |
544 | 0 | ModuleSP ModuleList::FindModule(const UUID &uuid) const { |
545 | 0 | ModuleSP module_sp; |
546 | |
|
547 | 0 | if (uuid.IsValid()) { |
548 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
549 | 0 | collection::const_iterator pos, end = m_modules.end(); |
550 | |
|
551 | 0 | for (pos = m_modules.begin(); pos != end; ++pos) { |
552 | 0 | if ((*pos)->GetUUID() == uuid) { |
553 | 0 | module_sp = (*pos); |
554 | 0 | break; |
555 | 0 | } |
556 | 0 | } |
557 | 0 | } |
558 | 0 | return module_sp; |
559 | 0 | } |
560 | | |
561 | | void ModuleList::FindTypes(Module *search_first, ConstString name, |
562 | | bool name_is_fully_qualified, size_t max_matches, |
563 | | llvm::DenseSet<SymbolFile *> &searched_symbol_files, |
564 | 10.2k | TypeList &types) const { |
565 | 10.2k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
566 | | |
567 | 10.2k | collection::const_iterator pos, end = m_modules.end(); |
568 | 10.2k | if (search_first) { |
569 | 285 | for (pos = m_modules.begin(); pos != end; ++pos276 ) { |
570 | 279 | if (search_first == pos->get()) { |
571 | 9 | search_first->FindTypes(name, name_is_fully_qualified, max_matches, |
572 | 9 | searched_symbol_files, types); |
573 | | |
574 | 9 | if (types.GetSize() >= max_matches) |
575 | 3 | return; |
576 | 9 | } |
577 | 279 | } |
578 | 9 | } |
579 | | |
580 | 471k | for (pos = m_modules.begin(); 10.2k pos != end; ++pos460k ) { |
581 | | // Search the module if the module is not equal to the one in the symbol |
582 | | // context "sc". If "sc" contains a empty module shared pointer, then the |
583 | | // comparison will always be true (valid_module_ptr != nullptr). |
584 | 461k | if (search_first != pos->get()) |
585 | 461k | (*pos)->FindTypes(name, name_is_fully_qualified, max_matches, |
586 | 461k | searched_symbol_files, types); |
587 | | |
588 | 461k | if (types.GetSize() >= max_matches) |
589 | 587 | return; |
590 | 461k | } |
591 | 10.2k | } |
592 | | |
593 | | bool ModuleList::FindSourceFile(const FileSpec &orig_spec, |
594 | 34 | FileSpec &new_spec) const { |
595 | 34 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
596 | 98 | for (const ModuleSP &module_sp : m_modules) { |
597 | 98 | if (module_sp->FindSourceFile(orig_spec, new_spec)) |
598 | 0 | return true; |
599 | 98 | } |
600 | 34 | return false; |
601 | 34 | } |
602 | | |
603 | | void ModuleList::FindAddressesForLine(const lldb::TargetSP target_sp, |
604 | | const FileSpec &file, uint32_t line, |
605 | | Function *function, |
606 | | std::vector<Address> &output_local, |
607 | 20 | std::vector<Address> &output_extern) { |
608 | 20 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
609 | 904 | for (const ModuleSP &module_sp : m_modules) { |
610 | 904 | module_sp->FindAddressesForLine(target_sp, file, line, function, |
611 | 904 | output_local, output_extern); |
612 | 904 | } |
613 | 20 | } |
614 | | |
615 | 227k | ModuleSP ModuleList::FindFirstModule(const ModuleSpec &module_spec) const { |
616 | 227k | ModuleSP module_sp; |
617 | 227k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
618 | 227k | collection::const_iterator pos, end = m_modules.end(); |
619 | 7.56M | for (pos = m_modules.begin(); pos != end; ++pos7.33M ) { |
620 | 7.34M | ModuleSP module_sp(*pos); |
621 | 7.34M | if (module_sp->MatchesModuleSpec(module_spec)) |
622 | 8.21k | return module_sp; |
623 | 7.34M | } |
624 | 219k | return module_sp; |
625 | 227k | } |
626 | | |
627 | 385k | size_t ModuleList::GetSize() const { |
628 | 385k | size_t size = 0; |
629 | 385k | { |
630 | 385k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
631 | 385k | size = m_modules.size(); |
632 | 385k | } |
633 | 385k | return size; |
634 | 385k | } |
635 | | |
636 | 2 | void ModuleList::Dump(Stream *s) const { |
637 | 2 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
638 | 2 | for (const ModuleSP &module_sp : m_modules) |
639 | 84 | module_sp->Dump(s); |
640 | 2 | } |
641 | | |
642 | 0 | void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) { |
643 | 0 | if (log != nullptr) { |
644 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
645 | 0 | collection::const_iterator pos, begin = m_modules.begin(), |
646 | 0 | end = m_modules.end(); |
647 | 0 | for (pos = begin; pos != end; ++pos) { |
648 | 0 | Module *module = pos->get(); |
649 | 0 | const FileSpec &module_file_spec = module->GetFileSpec(); |
650 | 0 | LLDB_LOGF(log, "%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "", |
651 | 0 | (uint32_t)std::distance(begin, pos), |
652 | 0 | module->GetUUID().GetAsString().c_str(), |
653 | 0 | module->GetArchitecture().GetArchitectureName(), |
654 | 0 | module_file_spec.GetPath().c_str()); |
655 | 0 | } |
656 | 0 | } |
657 | 0 | } |
658 | | |
659 | | bool ModuleList::ResolveFileAddress(lldb::addr_t vm_addr, |
660 | 213 | Address &so_addr) const { |
661 | 213 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
662 | 213 | for (const ModuleSP &module_sp : m_modules) { |
663 | 181 | if (module_sp->ResolveFileAddress(vm_addr, so_addr)) |
664 | 181 | return true; |
665 | 181 | } |
666 | | |
667 | 32 | return false; |
668 | 213 | } |
669 | | |
670 | | uint32_t |
671 | | ModuleList::ResolveSymbolContextForAddress(const Address &so_addr, |
672 | | SymbolContextItem resolve_scope, |
673 | 65.3k | SymbolContext &sc) const { |
674 | | // The address is already section offset so it has a module |
675 | 65.3k | uint32_t resolved_flags = 0; |
676 | 65.3k | ModuleSP module_sp(so_addr.GetModule()); |
677 | 65.3k | if (module_sp) { |
678 | 64.7k | resolved_flags = |
679 | 64.7k | module_sp->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc); |
680 | 64.7k | } else { |
681 | 587 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
682 | 587 | collection::const_iterator pos, end = m_modules.end(); |
683 | 3.06k | for (pos = m_modules.begin(); pos != end; ++pos2.47k ) { |
684 | 2.47k | resolved_flags = |
685 | 2.47k | (*pos)->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc); |
686 | 2.47k | if (resolved_flags != 0) |
687 | 0 | break; |
688 | 2.47k | } |
689 | 587 | } |
690 | | |
691 | 65.3k | return resolved_flags; |
692 | 65.3k | } |
693 | | |
694 | | uint32_t ModuleList::ResolveSymbolContextForFilePath( |
695 | | const char *file_path, uint32_t line, bool check_inlines, |
696 | 6 | SymbolContextItem resolve_scope, SymbolContextList &sc_list) const { |
697 | 6 | FileSpec file_spec(file_path); |
698 | 6 | return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, |
699 | 6 | resolve_scope, sc_list); |
700 | 6 | } |
701 | | |
702 | | uint32_t ModuleList::ResolveSymbolContextsForFileSpec( |
703 | | const FileSpec &file_spec, uint32_t line, bool check_inlines, |
704 | 6 | SymbolContextItem resolve_scope, SymbolContextList &sc_list) const { |
705 | 6 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
706 | 129 | for (const ModuleSP &module_sp : m_modules) { |
707 | 129 | module_sp->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, |
708 | 129 | resolve_scope, sc_list); |
709 | 129 | } |
710 | | |
711 | 6 | return sc_list.GetSize(); |
712 | 6 | } |
713 | | |
714 | 30 | size_t ModuleList::GetIndexForModule(const Module *module) const { |
715 | 30 | if (module) { |
716 | 30 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
717 | 30 | collection::const_iterator pos; |
718 | 30 | collection::const_iterator begin = m_modules.begin(); |
719 | 30 | collection::const_iterator end = m_modules.end(); |
720 | 30 | for (pos = begin; pos != end; ++pos0 ) { |
721 | 25 | if ((*pos).get() == module) |
722 | 25 | return std::distance(begin, pos); |
723 | 25 | } |
724 | 30 | } |
725 | 5 | return LLDB_INVALID_INDEX32; |
726 | 30 | } |
727 | | |
728 | | namespace { |
729 | | struct SharedModuleListInfo { |
730 | | ModuleList module_list; |
731 | | ModuleListProperties module_list_properties; |
732 | | }; |
733 | | } |
734 | | static SharedModuleListInfo &GetSharedModuleListInfo() |
735 | 945k | { |
736 | 945k | static SharedModuleListInfo *g_shared_module_list_info = nullptr; |
737 | 945k | static llvm::once_flag g_once_flag; |
738 | 945k | llvm::call_once(g_once_flag, []() { |
739 | | // NOTE: Intentionally leak the module list so a program doesn't have to |
740 | | // cleanup all modules and object files as it exits. This just wastes time |
741 | | // doing a bunch of cleanup that isn't required. |
742 | 3.85k | if (g_shared_module_list_info == nullptr) |
743 | 3.85k | g_shared_module_list_info = new SharedModuleListInfo(); |
744 | 3.85k | }); |
745 | 945k | return *g_shared_module_list_info; |
746 | 945k | } |
747 | | |
748 | 230k | static ModuleList &GetSharedModuleList() { |
749 | 230k | return GetSharedModuleListInfo().module_list; |
750 | 230k | } |
751 | | |
752 | 715k | ModuleListProperties &ModuleList::GetGlobalModuleListProperties() { |
753 | 715k | return GetSharedModuleListInfo().module_list_properties; |
754 | 715k | } |
755 | | |
756 | 0 | bool ModuleList::ModuleIsInCache(const Module *module_ptr) { |
757 | 0 | if (module_ptr) { |
758 | 0 | ModuleList &shared_module_list = GetSharedModuleList(); |
759 | 0 | return shared_module_list.FindModule(module_ptr).get() != nullptr; |
760 | 0 | } |
761 | 0 | return false; |
762 | 0 | } |
763 | | |
764 | | void ModuleList::FindSharedModules(const ModuleSpec &module_spec, |
765 | 0 | ModuleList &matching_module_list) { |
766 | 0 | GetSharedModuleList().FindModules(module_spec, matching_module_list); |
767 | 0 | } |
768 | | |
769 | 0 | lldb::ModuleSP ModuleList::FindSharedModule(const UUID &uuid) { |
770 | 0 | return GetSharedModuleList().FindModule(uuid); |
771 | 0 | } |
772 | | |
773 | 3.02k | size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) { |
774 | 3.02k | return GetSharedModuleList().RemoveOrphans(mandatory); |
775 | 3.02k | } |
776 | | |
777 | | Status |
778 | | ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp, |
779 | | const FileSpecList *module_search_paths_ptr, |
780 | | llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, |
781 | 227k | bool *did_create_ptr, bool always_create) { |
782 | 227k | ModuleList &shared_module_list = GetSharedModuleList(); |
783 | 227k | std::lock_guard<std::recursive_mutex> guard( |
784 | 227k | shared_module_list.m_modules_mutex); |
785 | 227k | char path[PATH_MAX]; |
786 | | |
787 | 227k | Status error; |
788 | | |
789 | 227k | module_sp.reset(); |
790 | | |
791 | 227k | if (did_create_ptr) |
792 | 224k | *did_create_ptr = false; |
793 | | |
794 | 227k | const UUID *uuid_ptr = module_spec.GetUUIDPtr(); |
795 | 227k | const FileSpec &module_file_spec = module_spec.GetFileSpec(); |
796 | 227k | const ArchSpec &arch = module_spec.GetArchitecture(); |
797 | | |
798 | | // Make sure no one else can try and get or create a module while this |
799 | | // function is actively working on it by doing an extra lock on the global |
800 | | // mutex list. |
801 | 227k | if (!always_create227k ) { |
802 | 227k | ModuleList matching_module_list; |
803 | 227k | shared_module_list.FindModules(module_spec, matching_module_list); |
804 | 227k | const size_t num_matching_modules = matching_module_list.GetSize(); |
805 | | |
806 | 227k | if (num_matching_modules > 0) { |
807 | 115k | for (size_t module_idx = 0; module_idx < num_matching_modules; |
808 | 115k | ++module_idx4 ) { |
809 | 115k | module_sp = matching_module_list.GetModuleAtIndex(module_idx); |
810 | | |
811 | | // Make sure the file for the module hasn't been modified |
812 | 115k | if (module_sp->FileHasChanged()) { |
813 | 4 | if (old_modules) |
814 | 3 | old_modules->push_back(module_sp); |
815 | | |
816 | 4 | Log *log = GetLog(LLDBLog::Modules); |
817 | 4 | if (log != nullptr) |
818 | 0 | LLDB_LOGF( |
819 | 4 | log, "%p '%s' module changed: removing from global module list", |
820 | 4 | static_cast<void *>(module_sp.get()), |
821 | 4 | module_sp->GetFileSpec().GetFilename().GetCString()); |
822 | | |
823 | 4 | shared_module_list.Remove(module_sp); |
824 | 4 | module_sp.reset(); |
825 | 115k | } else { |
826 | | // The module matches and the module was not modified from when it |
827 | | // was last loaded. |
828 | 115k | return error; |
829 | 115k | } |
830 | 115k | } |
831 | 115k | } |
832 | 227k | } |
833 | | |
834 | 112k | if (module_sp) |
835 | 0 | return error; |
836 | | |
837 | 112k | module_sp = std::make_shared<Module>(module_spec); |
838 | | // Make sure there are a module and an object file since we can specify a |
839 | | // valid file path with an architecture that might not be in that file. By |
840 | | // getting the object file we can guarantee that the architecture matches |
841 | 112k | if (module_sp->GetObjectFile()) { |
842 | | // If we get in here we got the correct arch, now we just need to verify |
843 | | // the UUID if one was given |
844 | 111k | if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()102k ) { |
845 | 0 | module_sp.reset(); |
846 | 111k | } else { |
847 | 111k | if (module_sp->GetObjectFile() && |
848 | 111k | module_sp->GetObjectFile()->GetType() == |
849 | 111k | ObjectFile::eTypeStubLibrary) { |
850 | 0 | module_sp.reset(); |
851 | 111k | } else { |
852 | 111k | if (did_create_ptr) { |
853 | 108k | *did_create_ptr = true; |
854 | 108k | } |
855 | | |
856 | 111k | shared_module_list.ReplaceEquivalent(module_sp, old_modules); |
857 | 111k | return error; |
858 | 111k | } |
859 | 111k | } |
860 | 111k | } else { |
861 | 936 | module_sp.reset(); |
862 | 936 | } |
863 | | |
864 | 936 | if (module_search_paths_ptr) { |
865 | 858 | const auto num_directories = module_search_paths_ptr->GetSize(); |
866 | 1.17k | for (size_t idx = 0; idx < num_directories; ++idx321 ) { |
867 | 333 | auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx); |
868 | 333 | FileSystem::Instance().Resolve(search_path_spec); |
869 | 333 | namespace fs = llvm::sys::fs; |
870 | 333 | if (!FileSystem::Instance().IsDirectory(search_path_spec)) |
871 | 0 | continue; |
872 | 333 | search_path_spec.AppendPathComponent( |
873 | 333 | module_spec.GetFileSpec().GetFilename().GetStringRef()); |
874 | 333 | if (!FileSystem::Instance().Exists(search_path_spec)) |
875 | 293 | continue; |
876 | | |
877 | 40 | auto resolved_module_spec(module_spec); |
878 | 40 | resolved_module_spec.GetFileSpec() = search_path_spec; |
879 | 40 | module_sp = std::make_shared<Module>(resolved_module_spec); |
880 | 40 | if (module_sp->GetObjectFile()) { |
881 | | // If we get in here we got the correct arch, now we just need to |
882 | | // verify the UUID if one was given |
883 | 12 | if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()3 ) { |
884 | 0 | module_sp.reset(); |
885 | 12 | } else { |
886 | 12 | if (module_sp->GetObjectFile()->GetType() == |
887 | 12 | ObjectFile::eTypeStubLibrary) { |
888 | 0 | module_sp.reset(); |
889 | 12 | } else { |
890 | 12 | if (did_create_ptr) |
891 | 12 | *did_create_ptr = true; |
892 | | |
893 | 12 | shared_module_list.ReplaceEquivalent(module_sp, old_modules); |
894 | 12 | return Status(); |
895 | 12 | } |
896 | 12 | } |
897 | 28 | } else { |
898 | 28 | module_sp.reset(); |
899 | 28 | } |
900 | 40 | } |
901 | 858 | } |
902 | | |
903 | | // Either the file didn't exist where at the path, or no path was given, so |
904 | | // we now have to use more extreme measures to try and find the appropriate |
905 | | // module. |
906 | | |
907 | | // Fixup the incoming path in case the path points to a valid file, yet the |
908 | | // arch or UUID (if one was passed in) don't match. |
909 | 924 | ModuleSpec located_binary_modulespec = |
910 | 924 | Symbols::LocateExecutableObjectFile(module_spec); |
911 | | |
912 | | // Don't look for the file if it appears to be the same one we already |
913 | | // checked for above... |
914 | 924 | if (located_binary_modulespec.GetFileSpec() != module_file_spec) { |
915 | 915 | if (!FileSystem::Instance().Exists( |
916 | 915 | located_binary_modulespec.GetFileSpec())) { |
917 | 915 | located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); |
918 | 915 | if (path[0] == '\0') |
919 | 915 | module_file_spec.GetPath(path, sizeof(path)); |
920 | | // How can this check ever be true? This branch it is false, and we |
921 | | // haven't modified file_spec. |
922 | 915 | if (FileSystem::Instance().Exists( |
923 | 915 | located_binary_modulespec.GetFileSpec())) { |
924 | 0 | std::string uuid_str; |
925 | 0 | if (uuid_ptr && uuid_ptr->IsValid()) |
926 | 0 | uuid_str = uuid_ptr->GetAsString(); |
927 | |
|
928 | 0 | if (arch.IsValid()) { |
929 | 0 | if (!uuid_str.empty()) |
930 | 0 | error.SetErrorStringWithFormat( |
931 | 0 | "'%s' does not contain the %s architecture and UUID %s", path, |
932 | 0 | arch.GetArchitectureName(), uuid_str.c_str()); |
933 | 0 | else |
934 | 0 | error.SetErrorStringWithFormat( |
935 | 0 | "'%s' does not contain the %s architecture.", path, |
936 | 0 | arch.GetArchitectureName()); |
937 | 0 | } |
938 | 915 | } else { |
939 | 915 | error.SetErrorStringWithFormat("'%s' does not exist", path); |
940 | 915 | } |
941 | 915 | if (error.Fail()) |
942 | 915 | module_sp.reset(); |
943 | 915 | return error; |
944 | 915 | } |
945 | | |
946 | | // Make sure no one else can try and get or create a module while this |
947 | | // function is actively working on it by doing an extra lock on the global |
948 | | // mutex list. |
949 | 0 | ModuleSpec platform_module_spec(module_spec); |
950 | 0 | platform_module_spec.GetFileSpec() = |
951 | 0 | located_binary_modulespec.GetFileSpec(); |
952 | 0 | platform_module_spec.GetPlatformFileSpec() = |
953 | 0 | located_binary_modulespec.GetFileSpec(); |
954 | 0 | platform_module_spec.GetSymbolFileSpec() = |
955 | 0 | located_binary_modulespec.GetSymbolFileSpec(); |
956 | 0 | ModuleList matching_module_list; |
957 | 0 | shared_module_list.FindModules(platform_module_spec, matching_module_list); |
958 | 0 | if (!matching_module_list.IsEmpty()) { |
959 | 0 | module_sp = matching_module_list.GetModuleAtIndex(0); |
960 | | |
961 | | // If we didn't have a UUID in mind when looking for the object file, |
962 | | // then we should make sure the modification time hasn't changed! |
963 | 0 | if (platform_module_spec.GetUUIDPtr() == nullptr) { |
964 | 0 | auto file_spec_mod_time = FileSystem::Instance().GetModificationTime( |
965 | 0 | located_binary_modulespec.GetFileSpec()); |
966 | 0 | if (file_spec_mod_time != llvm::sys::TimePoint<>()) { |
967 | 0 | if (file_spec_mod_time != module_sp->GetModificationTime()) { |
968 | 0 | if (old_modules) |
969 | 0 | old_modules->push_back(module_sp); |
970 | 0 | shared_module_list.Remove(module_sp); |
971 | 0 | module_sp.reset(); |
972 | 0 | } |
973 | 0 | } |
974 | 0 | } |
975 | 0 | } |
976 | |
|
977 | 0 | if (!module_sp) { |
978 | 0 | module_sp = std::make_shared<Module>(platform_module_spec); |
979 | | // Make sure there are a module and an object file since we can specify a |
980 | | // valid file path with an architecture that might not be in that file. |
981 | | // By getting the object file we can guarantee that the architecture |
982 | | // matches |
983 | 0 | if (module_sp && module_sp->GetObjectFile()) { |
984 | 0 | if (module_sp->GetObjectFile()->GetType() == |
985 | 0 | ObjectFile::eTypeStubLibrary) { |
986 | 0 | module_sp.reset(); |
987 | 0 | } else { |
988 | 0 | if (did_create_ptr) |
989 | 0 | *did_create_ptr = true; |
990 | |
|
991 | 0 | shared_module_list.ReplaceEquivalent(module_sp, old_modules); |
992 | 0 | } |
993 | 0 | } else { |
994 | 0 | located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); |
995 | |
|
996 | 0 | if (located_binary_modulespec.GetFileSpec()) { |
997 | 0 | if (arch.IsValid()) |
998 | 0 | error.SetErrorStringWithFormat( |
999 | 0 | "unable to open %s architecture in '%s'", |
1000 | 0 | arch.GetArchitectureName(), path); |
1001 | 0 | else |
1002 | 0 | error.SetErrorStringWithFormat("unable to open '%s'", path); |
1003 | 0 | } else { |
1004 | 0 | std::string uuid_str; |
1005 | 0 | if (uuid_ptr && uuid_ptr->IsValid()) |
1006 | 0 | uuid_str = uuid_ptr->GetAsString(); |
1007 | |
|
1008 | 0 | if (!uuid_str.empty()) |
1009 | 0 | error.SetErrorStringWithFormat( |
1010 | 0 | "cannot locate a module for UUID '%s'", uuid_str.c_str()); |
1011 | 0 | else |
1012 | 0 | error.SetErrorString("cannot locate a module"); |
1013 | 0 | } |
1014 | 0 | } |
1015 | 0 | } |
1016 | 0 | } |
1017 | | |
1018 | 9 | return error; |
1019 | 924 | } |
1020 | | |
1021 | 0 | bool ModuleList::RemoveSharedModule(lldb::ModuleSP &module_sp) { |
1022 | 0 | return GetSharedModuleList().Remove(module_sp); |
1023 | 0 | } |
1024 | | |
1025 | 1 | bool ModuleList::RemoveSharedModuleIfOrphaned(const Module *module_ptr) { |
1026 | 1 | return GetSharedModuleList().RemoveIfOrphaned(module_ptr); |
1027 | 1 | } |
1028 | | |
1029 | | bool ModuleList::LoadScriptingResourcesInTarget(Target *target, |
1030 | | std::list<Status> &errors, |
1031 | | Stream *feedback_stream, |
1032 | 0 | bool continue_on_error) { |
1033 | 0 | if (!target) |
1034 | 0 | return false; |
1035 | 0 | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
1036 | 0 | for (auto module : m_modules) { |
1037 | 0 | Status error; |
1038 | 0 | if (module) { |
1039 | 0 | if (!module->LoadScriptingResourceInTarget(target, error, |
1040 | 0 | feedback_stream)) { |
1041 | 0 | if (error.Fail() && error.AsCString()) { |
1042 | 0 | error.SetErrorStringWithFormat("unable to load scripting data for " |
1043 | 0 | "module %s - error reported was %s", |
1044 | 0 | module->GetFileSpec() |
1045 | 0 | .GetFileNameStrippingExtension() |
1046 | 0 | .GetCString(), |
1047 | 0 | error.AsCString()); |
1048 | 0 | errors.push_back(error); |
1049 | |
|
1050 | 0 | if (!continue_on_error) |
1051 | 0 | return false; |
1052 | 0 | } |
1053 | 0 | } |
1054 | 0 | } |
1055 | 0 | } |
1056 | 0 | return errors.empty(); |
1057 | 0 | } |
1058 | | |
1059 | | void ModuleList::ForEach( |
1060 | 146k | std::function<bool(const ModuleSP &module_sp)> const &callback) const { |
1061 | 146k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
1062 | 458k | for (const auto &module_sp : m_modules) { |
1063 | 458k | assert(module_sp != nullptr); |
1064 | | // If the callback returns false, then stop iterating and break out |
1065 | 458k | if (!callback(module_sp)) |
1066 | 2 | break; |
1067 | 458k | } |
1068 | 146k | } |
1069 | | |
1070 | | bool ModuleList::AnyOf( |
1071 | | std::function<bool(lldb_private::Module &module_sp)> const &callback) |
1072 | 2.22k | const { |
1073 | 2.22k | std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); |
1074 | 109k | for (const auto &module_sp : m_modules) { |
1075 | 109k | assert(module_sp != nullptr); |
1076 | 109k | if (callback(*module_sp)) |
1077 | 4 | return true; |
1078 | 109k | } |
1079 | | |
1080 | 2.22k | return false; |
1081 | 2.22k | } |