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