1 //===-- ModuleList.cpp ------------------------------------------*- C++ -*-===//
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 #include "lldb/Core/ModuleList.h"
11
12 // C Includes
13 #include <stdint.h>
14
15 // C++ Includes
16 #include <mutex> // std::once
17
18 // Other libraries and framework includes
19 // Project includes
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/Module.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/Symbols.h"
25 #include "lldb/Symbol/ClangNamespaceDecl.h"
26 #include "lldb/Symbol/ObjectFile.h"
27 #include "lldb/Symbol/VariableList.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31
32 //----------------------------------------------------------------------
33 // ModuleList constructor
34 //----------------------------------------------------------------------
ModuleList()35 ModuleList::ModuleList() :
36 m_modules(),
37 m_modules_mutex (Mutex::eMutexTypeRecursive),
38 m_notifier(NULL)
39 {
40 }
41
42 //----------------------------------------------------------------------
43 // Copy constructor
44 //----------------------------------------------------------------------
ModuleList(const ModuleList & rhs)45 ModuleList::ModuleList(const ModuleList& rhs) :
46 m_modules(),
47 m_modules_mutex (Mutex::eMutexTypeRecursive),
48 m_notifier(NULL)
49 {
50 Mutex::Locker lhs_locker(m_modules_mutex);
51 Mutex::Locker rhs_locker(rhs.m_modules_mutex);
52 m_modules = rhs.m_modules;
53 }
54
ModuleList(ModuleList::Notifier * notifier)55 ModuleList::ModuleList (ModuleList::Notifier* notifier) :
56 m_modules(),
57 m_modules_mutex (Mutex::eMutexTypeRecursive),
58 m_notifier(notifier)
59 {
60 }
61
62 //----------------------------------------------------------------------
63 // Assignment operator
64 //----------------------------------------------------------------------
65 const ModuleList&
operator =(const ModuleList & rhs)66 ModuleList::operator= (const ModuleList& rhs)
67 {
68 if (this != &rhs)
69 {
70 // That's probably me nit-picking, but in theoretical situation:
71 //
72 // * that two threads A B and
73 // * two ModuleList's x y do opposite assignemnts ie.:
74 //
75 // in thread A: | in thread B:
76 // x = y; | y = x;
77 //
78 // This establishes correct(same) lock taking order and thus
79 // avoids priority inversion.
80 if (uintptr_t(this) > uintptr_t(&rhs))
81 {
82 Mutex::Locker lhs_locker(m_modules_mutex);
83 Mutex::Locker rhs_locker(rhs.m_modules_mutex);
84 m_modules = rhs.m_modules;
85 }
86 else
87 {
88 Mutex::Locker rhs_locker(rhs.m_modules_mutex);
89 Mutex::Locker lhs_locker(m_modules_mutex);
90 m_modules = rhs.m_modules;
91 }
92 }
93 return *this;
94 }
95
96 //----------------------------------------------------------------------
97 // Destructor
98 //----------------------------------------------------------------------
~ModuleList()99 ModuleList::~ModuleList()
100 {
101 }
102
103 void
AppendImpl(const ModuleSP & module_sp,bool use_notifier)104 ModuleList::AppendImpl (const ModuleSP &module_sp, bool use_notifier)
105 {
106 if (module_sp)
107 {
108 Mutex::Locker locker(m_modules_mutex);
109 m_modules.push_back(module_sp);
110 if (use_notifier && m_notifier)
111 m_notifier->ModuleAdded(*this, module_sp);
112 }
113 }
114
115 void
Append(const ModuleSP & module_sp)116 ModuleList::Append (const ModuleSP &module_sp)
117 {
118 AppendImpl (module_sp);
119 }
120
121 void
ReplaceEquivalent(const ModuleSP & module_sp)122 ModuleList::ReplaceEquivalent (const ModuleSP &module_sp)
123 {
124 if (module_sp)
125 {
126 Mutex::Locker locker(m_modules_mutex);
127
128 // First remove any equivalent modules. Equivalent modules are modules
129 // whose path, platform path and architecture match.
130 ModuleSpec equivalent_module_spec (module_sp->GetFileSpec(), module_sp->GetArchitecture());
131 equivalent_module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
132
133 size_t idx = 0;
134 while (idx < m_modules.size())
135 {
136 ModuleSP module_sp (m_modules[idx]);
137 if (module_sp->MatchesModuleSpec (equivalent_module_spec))
138 RemoveImpl(m_modules.begin() + idx);
139 else
140 ++idx;
141 }
142 // Now add the new module to the list
143 Append(module_sp);
144 }
145 }
146
147 bool
AppendIfNeeded(const ModuleSP & module_sp)148 ModuleList::AppendIfNeeded (const ModuleSP &module_sp)
149 {
150 if (module_sp)
151 {
152 Mutex::Locker locker(m_modules_mutex);
153 collection::iterator pos, end = m_modules.end();
154 for (pos = m_modules.begin(); pos != end; ++pos)
155 {
156 if (pos->get() == module_sp.get())
157 return false; // Already in the list
158 }
159 // Only push module_sp on the list if it wasn't already in there.
160 Append(module_sp);
161 return true;
162 }
163 return false;
164 }
165
166 void
Append(const ModuleList & module_list)167 ModuleList::Append (const ModuleList& module_list)
168 {
169 for (auto pos : module_list.m_modules)
170 Append(pos);
171 }
172
173 bool
AppendIfNeeded(const ModuleList & module_list)174 ModuleList::AppendIfNeeded (const ModuleList& module_list)
175 {
176 bool any_in = false;
177 for (auto pos : module_list.m_modules)
178 {
179 if (AppendIfNeeded(pos))
180 any_in = true;
181 }
182 return any_in;
183 }
184
185 bool
RemoveImpl(const ModuleSP & module_sp,bool use_notifier)186 ModuleList::RemoveImpl (const ModuleSP &module_sp, bool use_notifier)
187 {
188 if (module_sp)
189 {
190 Mutex::Locker locker(m_modules_mutex);
191 collection::iterator pos, end = m_modules.end();
192 for (pos = m_modules.begin(); pos != end; ++pos)
193 {
194 if (pos->get() == module_sp.get())
195 {
196 m_modules.erase (pos);
197 if (use_notifier && m_notifier)
198 m_notifier->ModuleRemoved(*this, module_sp);
199 return true;
200 }
201 }
202 }
203 return false;
204 }
205
206 ModuleList::collection::iterator
RemoveImpl(ModuleList::collection::iterator pos,bool use_notifier)207 ModuleList::RemoveImpl (ModuleList::collection::iterator pos, bool use_notifier)
208 {
209 ModuleSP module_sp(*pos);
210 collection::iterator retval = m_modules.erase(pos);
211 if (use_notifier && m_notifier)
212 m_notifier->ModuleRemoved(*this, module_sp);
213 return retval;
214 }
215
216 bool
Remove(const ModuleSP & module_sp)217 ModuleList::Remove (const ModuleSP &module_sp)
218 {
219 return RemoveImpl (module_sp);
220 }
221
222 bool
ReplaceModule(const lldb::ModuleSP & old_module_sp,const lldb::ModuleSP & new_module_sp)223 ModuleList::ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)
224 {
225 if (!RemoveImpl(old_module_sp, false))
226 return false;
227 AppendImpl (new_module_sp, false);
228 if (m_notifier)
229 m_notifier->ModuleUpdated(*this, old_module_sp,new_module_sp);
230 return true;
231 }
232
233 bool
RemoveIfOrphaned(const Module * module_ptr)234 ModuleList::RemoveIfOrphaned (const Module *module_ptr)
235 {
236 if (module_ptr)
237 {
238 Mutex::Locker locker(m_modules_mutex);
239 collection::iterator pos, end = m_modules.end();
240 for (pos = m_modules.begin(); pos != end; ++pos)
241 {
242 if (pos->get() == module_ptr)
243 {
244 if (pos->unique())
245 {
246 pos = RemoveImpl(pos);
247 return true;
248 }
249 else
250 return false;
251 }
252 }
253 }
254 return false;
255 }
256
257 size_t
RemoveOrphans(bool mandatory)258 ModuleList::RemoveOrphans (bool mandatory)
259 {
260 Mutex::Locker locker;
261
262 if (mandatory)
263 {
264 locker.Lock (m_modules_mutex);
265 }
266 else
267 {
268 // Not mandatory, remove orphans if we can get the mutex
269 if (!locker.TryLock(m_modules_mutex))
270 return 0;
271 }
272 collection::iterator pos = m_modules.begin();
273 size_t remove_count = 0;
274 while (pos != m_modules.end())
275 {
276 if (pos->unique())
277 {
278 pos = RemoveImpl(pos);
279 ++remove_count;
280 }
281 else
282 {
283 ++pos;
284 }
285 }
286 return remove_count;
287 }
288
289 size_t
Remove(ModuleList & module_list)290 ModuleList::Remove (ModuleList &module_list)
291 {
292 Mutex::Locker locker(m_modules_mutex);
293 size_t num_removed = 0;
294 collection::iterator pos, end = module_list.m_modules.end();
295 for (pos = module_list.m_modules.begin(); pos != end; ++pos)
296 {
297 if (Remove (*pos))
298 ++num_removed;
299 }
300 return num_removed;
301 }
302
303
304 void
Clear()305 ModuleList::Clear()
306 {
307 ClearImpl();
308 }
309
310 void
Destroy()311 ModuleList::Destroy()
312 {
313 ClearImpl();
314 }
315
316 void
ClearImpl(bool use_notifier)317 ModuleList::ClearImpl (bool use_notifier)
318 {
319 Mutex::Locker locker(m_modules_mutex);
320 if (use_notifier && m_notifier)
321 m_notifier->WillClearList(*this);
322 m_modules.clear();
323 }
324
325 Module*
GetModulePointerAtIndex(size_t idx) const326 ModuleList::GetModulePointerAtIndex (size_t idx) const
327 {
328 Mutex::Locker locker(m_modules_mutex);
329 return GetModulePointerAtIndexUnlocked(idx);
330 }
331
332 Module*
GetModulePointerAtIndexUnlocked(size_t idx) const333 ModuleList::GetModulePointerAtIndexUnlocked (size_t idx) const
334 {
335 if (idx < m_modules.size())
336 return m_modules[idx].get();
337 return NULL;
338 }
339
340 ModuleSP
GetModuleAtIndex(size_t idx) const341 ModuleList::GetModuleAtIndex(size_t idx) const
342 {
343 Mutex::Locker locker(m_modules_mutex);
344 return GetModuleAtIndexUnlocked(idx);
345 }
346
347 ModuleSP
GetModuleAtIndexUnlocked(size_t idx) const348 ModuleList::GetModuleAtIndexUnlocked(size_t idx) const
349 {
350 ModuleSP module_sp;
351 if (idx < m_modules.size())
352 module_sp = m_modules[idx];
353 return module_sp;
354 }
355
356 size_t
FindFunctions(const ConstString & name,uint32_t name_type_mask,bool include_symbols,bool include_inlines,bool append,SymbolContextList & sc_list) const357 ModuleList::FindFunctions (const ConstString &name,
358 uint32_t name_type_mask,
359 bool include_symbols,
360 bool include_inlines,
361 bool append,
362 SymbolContextList &sc_list) const
363 {
364 if (!append)
365 sc_list.Clear();
366
367 const size_t old_size = sc_list.GetSize();
368
369 if (name_type_mask & eFunctionNameTypeAuto)
370 {
371 ConstString lookup_name;
372 uint32_t lookup_name_type_mask = 0;
373 bool match_name_after_lookup = false;
374 Module::PrepareForFunctionNameLookup (name, name_type_mask,
375 lookup_name,
376 lookup_name_type_mask,
377 match_name_after_lookup);
378
379 Mutex::Locker locker(m_modules_mutex);
380 collection::const_iterator pos, end = m_modules.end();
381 for (pos = m_modules.begin(); pos != end; ++pos)
382 {
383 (*pos)->FindFunctions (lookup_name,
384 NULL,
385 lookup_name_type_mask,
386 include_symbols,
387 include_inlines,
388 true,
389 sc_list);
390 }
391
392 if (match_name_after_lookup)
393 {
394 SymbolContext sc;
395 size_t i = old_size;
396 while (i<sc_list.GetSize())
397 {
398 if (sc_list.GetContextAtIndex(i, sc))
399 {
400 const char *func_name = sc.GetFunctionName().GetCString();
401 if (func_name && strstr (func_name, name.GetCString()) == NULL)
402 {
403 // Remove the current context
404 sc_list.RemoveContextAtIndex(i);
405 // Don't increment i and continue in the loop
406 continue;
407 }
408 }
409 ++i;
410 }
411 }
412
413 }
414 else
415 {
416 Mutex::Locker locker(m_modules_mutex);
417 collection::const_iterator pos, end = m_modules.end();
418 for (pos = m_modules.begin(); pos != end; ++pos)
419 {
420 (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
421 }
422 }
423 return sc_list.GetSize() - old_size;
424 }
425
426 size_t
FindFunctionSymbols(const ConstString & name,uint32_t name_type_mask,SymbolContextList & sc_list)427 ModuleList::FindFunctionSymbols (const ConstString &name,
428 uint32_t name_type_mask,
429 SymbolContextList& sc_list)
430 {
431 const size_t old_size = sc_list.GetSize();
432
433 if (name_type_mask & eFunctionNameTypeAuto)
434 {
435 ConstString lookup_name;
436 uint32_t lookup_name_type_mask = 0;
437 bool match_name_after_lookup = false;
438 Module::PrepareForFunctionNameLookup (name, name_type_mask,
439 lookup_name,
440 lookup_name_type_mask,
441 match_name_after_lookup);
442
443 Mutex::Locker locker(m_modules_mutex);
444 collection::const_iterator pos, end = m_modules.end();
445 for (pos = m_modules.begin(); pos != end; ++pos)
446 {
447 (*pos)->FindFunctionSymbols (lookup_name,
448 lookup_name_type_mask,
449 sc_list);
450 }
451
452 if (match_name_after_lookup)
453 {
454 SymbolContext sc;
455 size_t i = old_size;
456 while (i<sc_list.GetSize())
457 {
458 if (sc_list.GetContextAtIndex(i, sc))
459 {
460 const char *func_name = sc.GetFunctionName().GetCString();
461 if (func_name && strstr (func_name, name.GetCString()) == NULL)
462 {
463 // Remove the current context
464 sc_list.RemoveContextAtIndex(i);
465 // Don't increment i and continue in the loop
466 continue;
467 }
468 }
469 ++i;
470 }
471 }
472
473 }
474 else
475 {
476 Mutex::Locker locker(m_modules_mutex);
477 collection::const_iterator pos, end = m_modules.end();
478 for (pos = m_modules.begin(); pos != end; ++pos)
479 {
480 (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list);
481 }
482 }
483
484 return sc_list.GetSize() - old_size;
485 }
486
487
488 size_t
FindFunctions(const RegularExpression & name,bool include_symbols,bool include_inlines,bool append,SymbolContextList & sc_list)489 ModuleList::FindFunctions(const RegularExpression &name,
490 bool include_symbols,
491 bool include_inlines,
492 bool append,
493 SymbolContextList& sc_list)
494 {
495 const size_t old_size = sc_list.GetSize();
496
497 Mutex::Locker locker(m_modules_mutex);
498 collection::const_iterator pos, end = m_modules.end();
499 for (pos = m_modules.begin(); pos != end; ++pos)
500 {
501 (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list);
502 }
503
504 return sc_list.GetSize() - old_size;
505 }
506
507 size_t
FindCompileUnits(const FileSpec & path,bool append,SymbolContextList & sc_list) const508 ModuleList::FindCompileUnits (const FileSpec &path,
509 bool append,
510 SymbolContextList &sc_list) const
511 {
512 if (!append)
513 sc_list.Clear();
514
515 Mutex::Locker locker(m_modules_mutex);
516 collection::const_iterator pos, end = m_modules.end();
517 for (pos = m_modules.begin(); pos != end; ++pos)
518 {
519 (*pos)->FindCompileUnits (path, true, sc_list);
520 }
521
522 return sc_list.GetSize();
523 }
524
525 size_t
FindGlobalVariables(const ConstString & name,bool append,size_t max_matches,VariableList & variable_list) const526 ModuleList::FindGlobalVariables (const ConstString &name,
527 bool append,
528 size_t max_matches,
529 VariableList& variable_list) const
530 {
531 size_t initial_size = variable_list.GetSize();
532 Mutex::Locker locker(m_modules_mutex);
533 collection::const_iterator pos, end = m_modules.end();
534 for (pos = m_modules.begin(); pos != end; ++pos)
535 {
536 (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list);
537 }
538 return variable_list.GetSize() - initial_size;
539 }
540
541
542 size_t
FindGlobalVariables(const RegularExpression & regex,bool append,size_t max_matches,VariableList & variable_list) const543 ModuleList::FindGlobalVariables (const RegularExpression& regex,
544 bool append,
545 size_t max_matches,
546 VariableList& variable_list) const
547 {
548 size_t initial_size = variable_list.GetSize();
549 Mutex::Locker locker(m_modules_mutex);
550 collection::const_iterator pos, end = m_modules.end();
551 for (pos = m_modules.begin(); pos != end; ++pos)
552 {
553 (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
554 }
555 return variable_list.GetSize() - initial_size;
556 }
557
558
559 size_t
FindSymbolsWithNameAndType(const ConstString & name,SymbolType symbol_type,SymbolContextList & sc_list,bool append) const560 ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
561 SymbolType symbol_type,
562 SymbolContextList &sc_list,
563 bool append) const
564 {
565 Mutex::Locker locker(m_modules_mutex);
566 if (!append)
567 sc_list.Clear();
568 size_t initial_size = sc_list.GetSize();
569
570 collection::const_iterator pos, end = m_modules.end();
571 for (pos = m_modules.begin(); pos != end; ++pos)
572 (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
573 return sc_list.GetSize() - initial_size;
574 }
575
576 size_t
FindSymbolsMatchingRegExAndType(const RegularExpression & regex,lldb::SymbolType symbol_type,SymbolContextList & sc_list,bool append) const577 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex,
578 lldb::SymbolType symbol_type,
579 SymbolContextList &sc_list,
580 bool append) const
581 {
582 Mutex::Locker locker(m_modules_mutex);
583 if (!append)
584 sc_list.Clear();
585 size_t initial_size = sc_list.GetSize();
586
587 collection::const_iterator pos, end = m_modules.end();
588 for (pos = m_modules.begin(); pos != end; ++pos)
589 (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
590 return sc_list.GetSize() - initial_size;
591 }
592
593 size_t
FindModules(const ModuleSpec & module_spec,ModuleList & matching_module_list) const594 ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const
595 {
596 size_t existing_matches = matching_module_list.GetSize();
597
598 Mutex::Locker locker(m_modules_mutex);
599 collection::const_iterator pos, end = m_modules.end();
600 for (pos = m_modules.begin(); pos != end; ++pos)
601 {
602 ModuleSP module_sp(*pos);
603 if (module_sp->MatchesModuleSpec (module_spec))
604 matching_module_list.Append(module_sp);
605 }
606 return matching_module_list.GetSize() - existing_matches;
607 }
608
609 ModuleSP
FindModule(const Module * module_ptr) const610 ModuleList::FindModule (const Module *module_ptr) const
611 {
612 ModuleSP module_sp;
613
614 // Scope for "locker"
615 {
616 Mutex::Locker locker(m_modules_mutex);
617 collection::const_iterator pos, end = m_modules.end();
618
619 for (pos = m_modules.begin(); pos != end; ++pos)
620 {
621 if ((*pos).get() == module_ptr)
622 {
623 module_sp = (*pos);
624 break;
625 }
626 }
627 }
628 return module_sp;
629
630 }
631
632 ModuleSP
FindModule(const UUID & uuid) const633 ModuleList::FindModule (const UUID &uuid) const
634 {
635 ModuleSP module_sp;
636
637 if (uuid.IsValid())
638 {
639 Mutex::Locker locker(m_modules_mutex);
640 collection::const_iterator pos, end = m_modules.end();
641
642 for (pos = m_modules.begin(); pos != end; ++pos)
643 {
644 if ((*pos)->GetUUID() == uuid)
645 {
646 module_sp = (*pos);
647 break;
648 }
649 }
650 }
651 return module_sp;
652 }
653
654
655 size_t
FindTypes(const SymbolContext & sc,const ConstString & name,bool name_is_fully_qualified,size_t max_matches,TypeList & types) const656 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, size_t max_matches, TypeList& types) const
657 {
658 Mutex::Locker locker(m_modules_mutex);
659
660 size_t total_matches = 0;
661 collection::const_iterator pos, end = m_modules.end();
662 if (sc.module_sp)
663 {
664 // The symbol context "sc" contains a module so we want to search that
665 // one first if it is in our list...
666 for (pos = m_modules.begin(); pos != end; ++pos)
667 {
668 if (sc.module_sp.get() == (*pos).get())
669 {
670 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types);
671
672 if (total_matches >= max_matches)
673 break;
674 }
675 }
676 }
677
678 if (total_matches < max_matches)
679 {
680 SymbolContext world_sc;
681 for (pos = m_modules.begin(); pos != end; ++pos)
682 {
683 // Search the module if the module is not equal to the one in the symbol
684 // context "sc". If "sc" contains a empty module shared pointer, then
685 // the comparisong will always be true (valid_module_ptr != NULL).
686 if (sc.module_sp.get() != (*pos).get())
687 total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, types);
688
689 if (total_matches >= max_matches)
690 break;
691 }
692 }
693
694 return total_matches;
695 }
696
697 bool
FindSourceFile(const FileSpec & orig_spec,FileSpec & new_spec) const698 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const
699 {
700 Mutex::Locker locker(m_modules_mutex);
701 collection::const_iterator pos, end = m_modules.end();
702 for (pos = m_modules.begin(); pos != end; ++pos)
703 {
704 if ((*pos)->FindSourceFile (orig_spec, new_spec))
705 return true;
706 }
707 return false;
708 }
709
710 void
FindAddressesForLine(const lldb::TargetSP target_sp,const FileSpec & file,uint32_t line,Function * function,std::vector<Address> & output_local,std::vector<Address> & output_extern)711 ModuleList::FindAddressesForLine (const lldb::TargetSP target_sp,
712 const FileSpec &file, uint32_t line,
713 Function *function,
714 std::vector<Address> &output_local, std::vector<Address> &output_extern)
715 {
716 Mutex::Locker locker(m_modules_mutex);
717 collection::const_iterator pos, end = m_modules.end();
718 for (pos = m_modules.begin(); pos != end; ++pos)
719 {
720 (*pos)->FindAddressesForLine(target_sp, file, line, function, output_local, output_extern);
721 }
722 }
723
724 ModuleSP
FindFirstModule(const ModuleSpec & module_spec) const725 ModuleList::FindFirstModule (const ModuleSpec &module_spec) const
726 {
727 ModuleSP module_sp;
728 Mutex::Locker locker(m_modules_mutex);
729 collection::const_iterator pos, end = m_modules.end();
730 for (pos = m_modules.begin(); pos != end; ++pos)
731 {
732 ModuleSP module_sp(*pos);
733 if (module_sp->MatchesModuleSpec (module_spec))
734 return module_sp;
735 }
736 return module_sp;
737
738 }
739
740 size_t
GetSize() const741 ModuleList::GetSize() const
742 {
743 size_t size = 0;
744 {
745 Mutex::Locker locker(m_modules_mutex);
746 size = m_modules.size();
747 }
748 return size;
749 }
750
751
752 void
Dump(Stream * s) const753 ModuleList::Dump(Stream *s) const
754 {
755 // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
756 // s.Indent();
757 // s << "ModuleList\n";
758
759 Mutex::Locker locker(m_modules_mutex);
760 collection::const_iterator pos, end = m_modules.end();
761 for (pos = m_modules.begin(); pos != end; ++pos)
762 {
763 (*pos)->Dump(s);
764 }
765 }
766
767 void
LogUUIDAndPaths(Log * log,const char * prefix_cstr)768 ModuleList::LogUUIDAndPaths (Log *log, const char *prefix_cstr)
769 {
770 if (log)
771 {
772 Mutex::Locker locker(m_modules_mutex);
773 collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
774 for (pos = begin; pos != end; ++pos)
775 {
776 Module *module = pos->get();
777 const FileSpec &module_file_spec = module->GetFileSpec();
778 log->Printf ("%s[%u] %s (%s) \"%s\"",
779 prefix_cstr ? prefix_cstr : "",
780 (uint32_t)std::distance (begin, pos),
781 module->GetUUID().GetAsString().c_str(),
782 module->GetArchitecture().GetArchitectureName(),
783 module_file_spec.GetPath().c_str());
784 }
785 }
786 }
787
788 bool
ResolveFileAddress(lldb::addr_t vm_addr,Address & so_addr) const789 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) const
790 {
791 Mutex::Locker locker(m_modules_mutex);
792 collection::const_iterator pos, end = m_modules.end();
793 for (pos = m_modules.begin(); pos != end; ++pos)
794 {
795 if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
796 return true;
797 }
798
799 return false;
800 }
801
802 uint32_t
ResolveSymbolContextForAddress(const Address & so_addr,uint32_t resolve_scope,SymbolContext & sc) const803 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) const
804 {
805 // The address is already section offset so it has a module
806 uint32_t resolved_flags = 0;
807 ModuleSP module_sp (so_addr.GetModule());
808 if (module_sp)
809 {
810 resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr,
811 resolve_scope,
812 sc);
813 }
814 else
815 {
816 Mutex::Locker locker(m_modules_mutex);
817 collection::const_iterator pos, end = m_modules.end();
818 for (pos = m_modules.begin(); pos != end; ++pos)
819 {
820 resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
821 resolve_scope,
822 sc);
823 if (resolved_flags != 0)
824 break;
825 }
826 }
827
828 return resolved_flags;
829 }
830
831 uint32_t
ResolveSymbolContextForFilePath(const char * file_path,uint32_t line,bool check_inlines,uint32_t resolve_scope,SymbolContextList & sc_list) const832 ModuleList::ResolveSymbolContextForFilePath
833 (
834 const char *file_path,
835 uint32_t line,
836 bool check_inlines,
837 uint32_t resolve_scope,
838 SymbolContextList& sc_list
839 ) const
840 {
841 FileSpec file_spec(file_path, false);
842 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
843 }
844
845 uint32_t
ResolveSymbolContextsForFileSpec(const FileSpec & file_spec,uint32_t line,bool check_inlines,uint32_t resolve_scope,SymbolContextList & sc_list) const846 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const
847 {
848 Mutex::Locker locker(m_modules_mutex);
849 collection::const_iterator pos, end = m_modules.end();
850 for (pos = m_modules.begin(); pos != end; ++pos)
851 {
852 (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
853 }
854
855 return sc_list.GetSize();
856 }
857
858 size_t
GetIndexForModule(const Module * module) const859 ModuleList::GetIndexForModule (const Module *module) const
860 {
861 if (module)
862 {
863 Mutex::Locker locker(m_modules_mutex);
864 collection::const_iterator pos;
865 collection::const_iterator begin = m_modules.begin();
866 collection::const_iterator end = m_modules.end();
867 for (pos = begin; pos != end; ++pos)
868 {
869 if ((*pos).get() == module)
870 return std::distance (begin, pos);
871 }
872 }
873 return LLDB_INVALID_INDEX32;
874 }
875
876 static ModuleList &
GetSharedModuleList()877 GetSharedModuleList ()
878 {
879 static ModuleList *g_shared_module_list = NULL;
880 static std::once_flag g_once_flag;
881 std::call_once(g_once_flag, [](){
882 // NOTE: Intentionally leak the module list so a program doesn't have to
883 // cleanup all modules and object files as it exits. This just wastes time
884 // doing a bunch of cleanup that isn't required.
885 if (g_shared_module_list == NULL)
886 g_shared_module_list = new ModuleList(); // <--- Intentional leak!!!
887 });
888 return *g_shared_module_list;
889 }
890
891 bool
ModuleIsInCache(const Module * module_ptr)892 ModuleList::ModuleIsInCache (const Module *module_ptr)
893 {
894 if (module_ptr)
895 {
896 ModuleList &shared_module_list = GetSharedModuleList ();
897 return shared_module_list.FindModule (module_ptr).get() != NULL;
898 }
899 return false;
900 }
901
902 size_t
FindSharedModules(const ModuleSpec & module_spec,ModuleList & matching_module_list)903 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list)
904 {
905 return GetSharedModuleList ().FindModules (module_spec, matching_module_list);
906 }
907
908 size_t
RemoveOrphanSharedModules(bool mandatory)909 ModuleList::RemoveOrphanSharedModules (bool mandatory)
910 {
911 return GetSharedModuleList ().RemoveOrphans(mandatory);
912 }
913
914 Error
GetSharedModule(const ModuleSpec & module_spec,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,ModuleSP * old_module_sp_ptr,bool * did_create_ptr,bool always_create)915 ModuleList::GetSharedModule
916 (
917 const ModuleSpec &module_spec,
918 ModuleSP &module_sp,
919 const FileSpecList *module_search_paths_ptr,
920 ModuleSP *old_module_sp_ptr,
921 bool *did_create_ptr,
922 bool always_create
923 )
924 {
925 ModuleList &shared_module_list = GetSharedModuleList ();
926 Mutex::Locker locker(shared_module_list.m_modules_mutex);
927 char path[PATH_MAX];
928
929 Error error;
930
931 module_sp.reset();
932
933 if (did_create_ptr)
934 *did_create_ptr = false;
935 if (old_module_sp_ptr)
936 old_module_sp_ptr->reset();
937
938 const UUID *uuid_ptr = module_spec.GetUUIDPtr();
939 const FileSpec &module_file_spec = module_spec.GetFileSpec();
940 const ArchSpec &arch = module_spec.GetArchitecture();
941
942 // Make sure no one else can try and get or create a module while this
943 // function is actively working on it by doing an extra lock on the
944 // global mutex list.
945 if (always_create == false)
946 {
947 ModuleList matching_module_list;
948 const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list);
949 if (num_matching_modules > 0)
950 {
951 for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
952 {
953 module_sp = matching_module_list.GetModuleAtIndex(module_idx);
954
955 // Make sure the file for the module hasn't been modified
956 if (module_sp->FileHasChanged())
957 {
958 if (old_module_sp_ptr && !old_module_sp_ptr->get())
959 *old_module_sp_ptr = module_sp;
960
961 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES));
962 if (log)
963 log->Printf("module changed: %p, removing from global module list",
964 static_cast<void*>(module_sp.get()));
965
966 shared_module_list.Remove (module_sp);
967 module_sp.reset();
968 }
969 else
970 {
971 // The module matches and the module was not modified from
972 // when it was last loaded.
973 return error;
974 }
975 }
976 }
977 }
978
979 if (module_sp)
980 return error;
981
982 module_sp.reset (new Module (module_spec));
983 // Make sure there are a module and an object file since we can specify
984 // a valid file path with an architecture that might not be in that file.
985 // By getting the object file we can guarantee that the architecture matches
986 if (module_sp->GetObjectFile())
987 {
988 // If we get in here we got the correct arch, now we just need
989 // to verify the UUID if one was given
990 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
991 module_sp.reset();
992 else
993 {
994 if (did_create_ptr)
995 *did_create_ptr = true;
996
997 shared_module_list.ReplaceEquivalent(module_sp);
998 return error;
999 }
1000 }
1001 else
1002 module_sp.reset();
1003
1004 if (module_search_paths_ptr)
1005 {
1006 const auto num_directories = module_search_paths_ptr->GetSize();
1007 for (size_t idx = 0; idx < num_directories; ++idx)
1008 {
1009 auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx);
1010 if (!search_path_spec.ResolvePath())
1011 continue;
1012 if (!search_path_spec.Exists() || !search_path_spec.IsDirectory())
1013 continue;
1014 search_path_spec.AppendPathComponent(module_spec.GetFileSpec().GetFilename().AsCString());
1015 if (!search_path_spec.Exists())
1016 continue;
1017
1018 auto resolved_module_spec(module_spec);
1019 resolved_module_spec.GetFileSpec() = search_path_spec;
1020 module_sp.reset (new Module (resolved_module_spec));
1021 if (module_sp->GetObjectFile())
1022 {
1023 // If we get in here we got the correct arch, now we just need
1024 // to verify the UUID if one was given
1025 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
1026 module_sp.reset();
1027 else
1028 {
1029 if (did_create_ptr)
1030 *did_create_ptr = true;
1031
1032 shared_module_list.ReplaceEquivalent(module_sp);
1033 return Error();
1034 }
1035 }
1036 else
1037 module_sp.reset();
1038 }
1039 }
1040
1041 // Either the file didn't exist where at the path, or no path was given, so
1042 // we now have to use more extreme measures to try and find the appropriate
1043 // module.
1044
1045 // Fixup the incoming path in case the path points to a valid file, yet
1046 // the arch or UUID (if one was passed in) don't match.
1047 FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec);
1048
1049 // Don't look for the file if it appears to be the same one we already
1050 // checked for above...
1051 if (file_spec != module_file_spec)
1052 {
1053 if (!file_spec.Exists())
1054 {
1055 file_spec.GetPath(path, sizeof(path));
1056 if (path[0] == '\0')
1057 module_file_spec.GetPath(path, sizeof(path));
1058 // How can this check ever be true? This branch it is false, and we haven't modified file_spec.
1059 if (file_spec.Exists())
1060 {
1061 std::string uuid_str;
1062 if (uuid_ptr && uuid_ptr->IsValid())
1063 uuid_str = uuid_ptr->GetAsString();
1064
1065 if (arch.IsValid())
1066 {
1067 if (!uuid_str.empty())
1068 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str());
1069 else
1070 error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
1071 }
1072 }
1073 else
1074 {
1075 error.SetErrorStringWithFormat("'%s' does not exist", path);
1076 }
1077 if (error.Fail())
1078 module_sp.reset();
1079 return error;
1080 }
1081
1082
1083 // Make sure no one else can try and get or create a module while this
1084 // function is actively working on it by doing an extra lock on the
1085 // global mutex list.
1086 ModuleSpec platform_module_spec(module_spec);
1087 platform_module_spec.GetFileSpec() = file_spec;
1088 platform_module_spec.GetPlatformFileSpec() = file_spec;
1089 ModuleList matching_module_list;
1090 if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
1091 {
1092 module_sp = matching_module_list.GetModuleAtIndex(0);
1093
1094 // If we didn't have a UUID in mind when looking for the object file,
1095 // then we should make sure the modification time hasn't changed!
1096 if (platform_module_spec.GetUUIDPtr() == NULL)
1097 {
1098 TimeValue file_spec_mod_time(file_spec.GetModificationTime());
1099 if (file_spec_mod_time.IsValid())
1100 {
1101 if (file_spec_mod_time != module_sp->GetModificationTime())
1102 {
1103 if (old_module_sp_ptr)
1104 *old_module_sp_ptr = module_sp;
1105 shared_module_list.Remove (module_sp);
1106 module_sp.reset();
1107 }
1108 }
1109 }
1110 }
1111
1112 if (module_sp.get() == NULL)
1113 {
1114 module_sp.reset (new Module (platform_module_spec));
1115 // Make sure there are a module and an object file since we can specify
1116 // a valid file path with an architecture that might not be in that file.
1117 // By getting the object file we can guarantee that the architecture matches
1118 if (module_sp && module_sp->GetObjectFile())
1119 {
1120 if (did_create_ptr)
1121 *did_create_ptr = true;
1122
1123 shared_module_list.ReplaceEquivalent(module_sp);
1124 }
1125 else
1126 {
1127 file_spec.GetPath(path, sizeof(path));
1128
1129 if (file_spec)
1130 {
1131 if (arch.IsValid())
1132 error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
1133 else
1134 error.SetErrorStringWithFormat("unable to open '%s'", path);
1135 }
1136 else
1137 {
1138 std::string uuid_str;
1139 if (uuid_ptr && uuid_ptr->IsValid())
1140 uuid_str = uuid_ptr->GetAsString();
1141
1142 if (!uuid_str.empty())
1143 error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str());
1144 else
1145 error.SetErrorStringWithFormat("cannot locate a module");
1146 }
1147 }
1148 }
1149 }
1150
1151 return error;
1152 }
1153
1154 bool
RemoveSharedModule(lldb::ModuleSP & module_sp)1155 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
1156 {
1157 return GetSharedModuleList ().Remove (module_sp);
1158 }
1159
1160 bool
RemoveSharedModuleIfOrphaned(const Module * module_ptr)1161 ModuleList::RemoveSharedModuleIfOrphaned (const Module *module_ptr)
1162 {
1163 return GetSharedModuleList ().RemoveIfOrphaned (module_ptr);
1164 }
1165
1166 bool
LoadScriptingResourcesInTarget(Target * target,std::list<Error> & errors,Stream * feedback_stream,bool continue_on_error)1167 ModuleList::LoadScriptingResourcesInTarget (Target *target,
1168 std::list<Error>& errors,
1169 Stream *feedback_stream,
1170 bool continue_on_error)
1171 {
1172 if (!target)
1173 return false;
1174 Mutex::Locker locker(m_modules_mutex);
1175 for (auto module : m_modules)
1176 {
1177 Error error;
1178 if (module)
1179 {
1180 if (!module->LoadScriptingResourceInTarget(target, error, feedback_stream))
1181 {
1182 if (error.Fail() && error.AsCString())
1183 {
1184 error.SetErrorStringWithFormat("unable to load scripting data for module %s - error reported was %s",
1185 module->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
1186 error.AsCString());
1187 errors.push_back(error);
1188
1189 if (!continue_on_error)
1190 return false;
1191 }
1192 }
1193 }
1194 }
1195 return errors.size() == 0;
1196 }
1197
1198 void
ForEach(std::function<bool (const ModuleSP & module_sp)> const & callback) const1199 ModuleList::ForEach (std::function <bool (const ModuleSP &module_sp)> const &callback) const
1200 {
1201 Mutex::Locker locker(m_modules_mutex);
1202 for (const auto &module : m_modules)
1203 {
1204 // If the callback returns false, then stop iterating and break out
1205 if (!callback (module))
1206 break;
1207 }
1208 }
1209