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 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/Module.h"
18 #include "lldb/Host/Host.h"
19 #include "lldb/Host/Symbols.h"
20 #include "lldb/Symbol/ClangNamespaceDecl.h"
21 #include "lldb/Symbol/ObjectFile.h"
22 #include "lldb/Symbol/VariableList.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //----------------------------------------------------------------------
28 // ModuleList constructor
29 //----------------------------------------------------------------------
30 ModuleList::ModuleList() :
31     m_modules(),
32     m_modules_mutex (Mutex::eMutexTypeRecursive)
33 {
34 }
35 
36 //----------------------------------------------------------------------
37 // Copy constructor
38 //----------------------------------------------------------------------
39 ModuleList::ModuleList(const ModuleList& rhs) :
40     m_modules(),
41     m_modules_mutex (Mutex::eMutexTypeRecursive)
42 {
43     Mutex::Locker lhs_locker(m_modules_mutex);
44     Mutex::Locker rhs_locker(rhs.m_modules_mutex);
45     m_modules = rhs.m_modules;
46 }
47 
48 //----------------------------------------------------------------------
49 // Assignment operator
50 //----------------------------------------------------------------------
51 const ModuleList&
52 ModuleList::operator= (const ModuleList& rhs)
53 {
54     if (this != &rhs)
55     {
56         Mutex::Locker lhs_locker(m_modules_mutex);
57         Mutex::Locker rhs_locker(rhs.m_modules_mutex);
58         m_modules = rhs.m_modules;
59     }
60     return *this;
61 }
62 
63 //----------------------------------------------------------------------
64 // Destructor
65 //----------------------------------------------------------------------
66 ModuleList::~ModuleList()
67 {
68 }
69 
70 void
71 ModuleList::Append (const ModuleSP &module_sp)
72 {
73     if (module_sp)
74     {
75         Mutex::Locker locker(m_modules_mutex);
76         m_modules.push_back(module_sp);
77     }
78 }
79 
80 bool
81 ModuleList::AppendIfNeeded (const ModuleSP &module_sp)
82 {
83     if (module_sp)
84     {
85         Mutex::Locker locker(m_modules_mutex);
86         collection::iterator pos, end = m_modules.end();
87         for (pos = m_modules.begin(); pos != end; ++pos)
88         {
89             if (pos->get() == module_sp.get())
90                 return false; // Already in the list
91         }
92         // Only push module_sp on the list if it wasn't already in there.
93         m_modules.push_back(module_sp);
94         return true;
95     }
96     return false;
97 }
98 
99 bool
100 ModuleList::Remove (const ModuleSP &module_sp)
101 {
102     if (module_sp)
103     {
104         Mutex::Locker locker(m_modules_mutex);
105         collection::iterator pos, end = m_modules.end();
106         for (pos = m_modules.begin(); pos != end; ++pos)
107         {
108             if (pos->get() == module_sp.get())
109             {
110                 m_modules.erase (pos);
111                 return true;
112             }
113         }
114     }
115     return false;
116 }
117 
118 bool
119 ModuleList::RemoveIfOrphaned (const Module *module_ptr)
120 {
121     if (module_ptr)
122     {
123         Mutex::Locker locker(m_modules_mutex);
124         collection::iterator pos, end = m_modules.end();
125         for (pos = m_modules.begin(); pos != end; ++pos)
126         {
127             if (pos->get() == module_ptr)
128             {
129                 if (pos->unique())
130                 {
131                     pos = m_modules.erase (pos);
132                     return true;
133                 }
134                 else
135                     return false;
136             }
137         }
138     }
139     return false;
140 }
141 
142 size_t
143 ModuleList::RemoveOrphans (bool mandatory)
144 {
145     Mutex::Locker locker;
146 
147     if (mandatory)
148     {
149         locker.Lock (m_modules_mutex);
150     }
151     else
152     {
153         // Not mandatory, remove orphans if we can get the mutex
154         if (!locker.TryLock(m_modules_mutex))
155             return 0;
156     }
157     collection::iterator pos = m_modules.begin();
158     size_t remove_count = 0;
159     while (pos != m_modules.end())
160     {
161         if (pos->unique())
162         {
163             pos = m_modules.erase (pos);
164             ++remove_count;
165         }
166         else
167         {
168             ++pos;
169         }
170     }
171     return remove_count;
172 }
173 
174 size_t
175 ModuleList::Remove (ModuleList &module_list)
176 {
177     Mutex::Locker locker(m_modules_mutex);
178     size_t num_removed = 0;
179     collection::iterator pos, end = module_list.m_modules.end();
180     for (pos = module_list.m_modules.begin(); pos != end; ++pos)
181     {
182         if (Remove (*pos))
183             ++num_removed;
184     }
185     return num_removed;
186 }
187 
188 
189 
190 void
191 ModuleList::Clear()
192 {
193     Mutex::Locker locker(m_modules_mutex);
194     m_modules.clear();
195 }
196 
197 void
198 ModuleList::Destroy()
199 {
200     Mutex::Locker locker(m_modules_mutex);
201     collection empty;
202     m_modules.swap(empty);
203 }
204 
205 Module*
206 ModuleList::GetModulePointerAtIndex (uint32_t idx) const
207 {
208     Mutex::Locker locker(m_modules_mutex);
209     return GetModulePointerAtIndexUnlocked(idx);
210 }
211 
212 Module*
213 ModuleList::GetModulePointerAtIndexUnlocked (uint32_t idx) const
214 {
215     if (idx < m_modules.size())
216         return m_modules[idx].get();
217     return NULL;
218 }
219 
220 ModuleSP
221 ModuleList::GetModuleAtIndex(uint32_t idx)
222 {
223     Mutex::Locker locker(m_modules_mutex);
224     return GetModuleAtIndexUnlocked(idx);
225 }
226 
227 ModuleSP
228 ModuleList::GetModuleAtIndexUnlocked(uint32_t idx)
229 {
230     ModuleSP module_sp;
231     if (idx < m_modules.size())
232         module_sp = m_modules[idx];
233     return module_sp;
234 }
235 
236 uint32_t
237 ModuleList::FindFunctions (const ConstString &name,
238                            uint32_t name_type_mask,
239                            bool include_symbols,
240                            bool include_inlines,
241                            bool append,
242                            SymbolContextList &sc_list)
243 {
244     if (!append)
245         sc_list.Clear();
246 
247     Mutex::Locker locker(m_modules_mutex);
248     collection::const_iterator pos, end = m_modules.end();
249     for (pos = m_modules.begin(); pos != end; ++pos)
250     {
251         (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
252     }
253 
254     return sc_list.GetSize();
255 }
256 
257 uint32_t
258 ModuleList::FindCompileUnits (const FileSpec &path,
259                               bool append,
260                               SymbolContextList &sc_list)
261 {
262     if (!append)
263         sc_list.Clear();
264 
265     Mutex::Locker locker(m_modules_mutex);
266     collection::const_iterator pos, end = m_modules.end();
267     for (pos = m_modules.begin(); pos != end; ++pos)
268     {
269         (*pos)->FindCompileUnits (path, true, sc_list);
270     }
271 
272     return sc_list.GetSize();
273 }
274 
275 uint32_t
276 ModuleList::FindGlobalVariables (const ConstString &name,
277                                  bool append,
278                                  uint32_t max_matches,
279                                  VariableList& variable_list)
280 {
281     size_t initial_size = variable_list.GetSize();
282     Mutex::Locker locker(m_modules_mutex);
283     collection::iterator pos, end = m_modules.end();
284     for (pos = m_modules.begin(); pos != end; ++pos)
285     {
286         (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list);
287     }
288     return variable_list.GetSize() - initial_size;
289 }
290 
291 
292 uint32_t
293 ModuleList::FindGlobalVariables (const RegularExpression& regex,
294                                  bool append,
295                                  uint32_t max_matches,
296                                  VariableList& variable_list)
297 {
298     size_t initial_size = variable_list.GetSize();
299     Mutex::Locker locker(m_modules_mutex);
300     collection::iterator pos, end = m_modules.end();
301     for (pos = m_modules.begin(); pos != end; ++pos)
302     {
303         (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
304     }
305     return variable_list.GetSize() - initial_size;
306 }
307 
308 
309 size_t
310 ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
311                                         SymbolType symbol_type,
312                                         SymbolContextList &sc_list,
313                                         bool append)
314 {
315     Mutex::Locker locker(m_modules_mutex);
316     if (!append)
317         sc_list.Clear();
318     size_t initial_size = sc_list.GetSize();
319 
320     collection::iterator pos, end = m_modules.end();
321     for (pos = m_modules.begin(); pos != end; ++pos)
322         (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
323     return sc_list.GetSize() - initial_size;
324 }
325 
326     size_t
327 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex,
328                                              lldb::SymbolType symbol_type,
329                                              SymbolContextList &sc_list,
330                                              bool append)
331 {
332     Mutex::Locker locker(m_modules_mutex);
333     if (!append)
334         sc_list.Clear();
335     size_t initial_size = sc_list.GetSize();
336 
337     collection::iterator pos, end = m_modules.end();
338     for (pos = m_modules.begin(); pos != end; ++pos)
339         (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
340     return sc_list.GetSize() - initial_size;
341 }
342 
343 size_t
344 ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const
345 {
346     size_t existing_matches = matching_module_list.GetSize();
347 
348     Mutex::Locker locker(m_modules_mutex);
349     collection::const_iterator pos, end = m_modules.end();
350     for (pos = m_modules.begin(); pos != end; ++pos)
351     {
352         ModuleSP module_sp(*pos);
353         if (module_sp->MatchesModuleSpec (module_spec))
354             matching_module_list.Append(module_sp);
355     }
356     return matching_module_list.GetSize() - existing_matches;
357 }
358 
359 ModuleSP
360 ModuleList::FindModule (const Module *module_ptr)
361 {
362     ModuleSP module_sp;
363 
364     // Scope for "locker"
365     {
366         Mutex::Locker locker(m_modules_mutex);
367         collection::const_iterator pos, end = m_modules.end();
368 
369         for (pos = m_modules.begin(); pos != end; ++pos)
370         {
371             if ((*pos).get() == module_ptr)
372             {
373                 module_sp = (*pos);
374                 break;
375             }
376         }
377     }
378     return module_sp;
379 
380 }
381 
382 ModuleSP
383 ModuleList::FindModule (const UUID &uuid)
384 {
385     ModuleSP module_sp;
386 
387     if (uuid.IsValid())
388     {
389         Mutex::Locker locker(m_modules_mutex);
390         collection::const_iterator pos, end = m_modules.end();
391 
392         for (pos = m_modules.begin(); pos != end; ++pos)
393         {
394             if ((*pos)->GetUUID() == uuid)
395             {
396                 module_sp = (*pos);
397                 break;
398             }
399         }
400     }
401     return module_sp;
402 }
403 
404 
405 uint32_t
406 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types)
407 {
408     Mutex::Locker locker(m_modules_mutex);
409 
410     uint32_t total_matches = 0;
411     collection::const_iterator pos, end = m_modules.end();
412     if (sc.module_sp)
413     {
414         // The symbol context "sc" contains a module so we want to search that
415         // one first if it is in our list...
416         for (pos = m_modules.begin(); pos != end; ++pos)
417         {
418             if (sc.module_sp.get() == (*pos).get())
419             {
420                 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types);
421 
422                 if (total_matches >= max_matches)
423                     break;
424             }
425         }
426     }
427 
428     if (total_matches < max_matches)
429     {
430         for (pos = m_modules.begin(); pos != end; ++pos)
431         {
432             // Search the module if the module is not equal to the one in the symbol
433             // context "sc". If "sc" contains a empty module shared pointer, then
434             // the comparisong will always be true (valid_module_ptr != NULL).
435             if (sc.module_sp.get() != (*pos).get())
436                 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types);
437 
438             if (total_matches >= max_matches)
439                 break;
440         }
441     }
442 
443     return total_matches;
444 }
445 
446 bool
447 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const
448 {
449     Mutex::Locker locker(m_modules_mutex);
450     collection::const_iterator pos, end = m_modules.end();
451     for (pos = m_modules.begin(); pos != end; ++pos)
452     {
453         if ((*pos)->FindSourceFile (orig_spec, new_spec))
454             return true;
455     }
456     return false;
457 }
458 
459 
460 
461 ModuleSP
462 ModuleList::FindFirstModule (const ModuleSpec &module_spec)
463 {
464     ModuleSP module_sp;
465     Mutex::Locker locker(m_modules_mutex);
466     collection::const_iterator pos, end = m_modules.end();
467     for (pos = m_modules.begin(); pos != end; ++pos)
468     {
469         ModuleSP module_sp(*pos);
470         if (module_sp->MatchesModuleSpec (module_spec))
471             return module_sp;
472     }
473     return module_sp;
474 
475 }
476 
477 size_t
478 ModuleList::GetSize() const
479 {
480     size_t size = 0;
481     {
482         Mutex::Locker locker(m_modules_mutex);
483         size = m_modules.size();
484     }
485     return size;
486 }
487 
488 
489 void
490 ModuleList::Dump(Stream *s) const
491 {
492 //  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
493 //  s.Indent();
494 //  s << "ModuleList\n";
495 
496     Mutex::Locker locker(m_modules_mutex);
497     collection::const_iterator pos, end = m_modules.end();
498     for (pos = m_modules.begin(); pos != end; ++pos)
499     {
500         (*pos)->Dump(s);
501     }
502 }
503 
504 void
505 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr)
506 {
507     if (log_sp)
508     {
509         Mutex::Locker locker(m_modules_mutex);
510         char uuid_cstr[256];
511         collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
512         for (pos = begin; pos != end; ++pos)
513         {
514             Module *module = pos->get();
515             module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr));
516             const FileSpec &module_file_spec = module->GetFileSpec();
517             log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"",
518                             prefix_cstr ? prefix_cstr : "",
519                             (uint32_t)std::distance (begin, pos),
520                             uuid_cstr,
521                             module->GetArchitecture().GetArchitectureName(),
522                             module_file_spec.GetDirectory().GetCString(),
523                             module_file_spec.GetFilename().GetCString());
524         }
525     }
526 }
527 
528 bool
529 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
530 {
531     Mutex::Locker locker(m_modules_mutex);
532     collection::const_iterator pos, end = m_modules.end();
533     for (pos = m_modules.begin(); pos != end; ++pos)
534     {
535         if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
536             return true;
537     }
538 
539     return false;
540 }
541 
542 uint32_t
543 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
544 {
545     // The address is already section offset so it has a module
546     uint32_t resolved_flags = 0;
547     ModuleSP module_sp (so_addr.GetModule());
548     if (module_sp)
549     {
550         resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr,
551                                                                     resolve_scope,
552                                                                     sc);
553     }
554     else
555     {
556         Mutex::Locker locker(m_modules_mutex);
557         collection::const_iterator pos, end = m_modules.end();
558         for (pos = m_modules.begin(); pos != end; ++pos)
559         {
560             resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
561                                                                      resolve_scope,
562                                                                      sc);
563             if (resolved_flags != 0)
564                 break;
565         }
566     }
567 
568     return resolved_flags;
569 }
570 
571 uint32_t
572 ModuleList::ResolveSymbolContextForFilePath
573 (
574     const char *file_path,
575     uint32_t line,
576     bool check_inlines,
577     uint32_t resolve_scope,
578     SymbolContextList& sc_list
579 )
580 {
581     FileSpec file_spec(file_path, false);
582     return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
583 }
584 
585 uint32_t
586 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
587 {
588     Mutex::Locker locker(m_modules_mutex);
589     collection::const_iterator pos, end = m_modules.end();
590     for (pos = m_modules.begin(); pos != end; ++pos)
591     {
592         (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
593     }
594 
595     return sc_list.GetSize();
596 }
597 
598 uint32_t
599 ModuleList::GetIndexForModule (const Module *module) const
600 {
601     if (module)
602     {
603         Mutex::Locker locker(m_modules_mutex);
604         collection::const_iterator pos;
605         collection::const_iterator begin = m_modules.begin();
606         collection::const_iterator end = m_modules.end();
607         for (pos = begin; pos != end; ++pos)
608         {
609             if ((*pos).get() == module)
610                 return std::distance (begin, pos);
611         }
612     }
613     return LLDB_INVALID_INDEX32;
614 }
615 
616 static ModuleList &
617 GetSharedModuleList ()
618 {
619     static ModuleList g_shared_module_list;
620     return g_shared_module_list;
621 }
622 
623 bool
624 ModuleList::ModuleIsInCache (const Module *module_ptr)
625 {
626     if (module_ptr)
627     {
628         ModuleList &shared_module_list = GetSharedModuleList ();
629         return shared_module_list.FindModule (module_ptr).get() != NULL;
630     }
631     return false;
632 }
633 
634 size_t
635 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list)
636 {
637     return GetSharedModuleList ().FindModules (module_spec, matching_module_list);
638 }
639 
640 uint32_t
641 ModuleList::RemoveOrphanSharedModules (bool mandatory)
642 {
643     return GetSharedModuleList ().RemoveOrphans(mandatory);
644 }
645 
646 Error
647 ModuleList::GetSharedModule
648 (
649     const ModuleSpec &module_spec,
650     ModuleSP &module_sp,
651     const FileSpecList *module_search_paths_ptr,
652     ModuleSP *old_module_sp_ptr,
653     bool *did_create_ptr,
654     bool always_create
655 )
656 {
657     ModuleList &shared_module_list = GetSharedModuleList ();
658     Mutex::Locker locker(shared_module_list.m_modules_mutex);
659     char path[PATH_MAX];
660     char uuid_cstr[64];
661 
662     Error error;
663 
664     module_sp.reset();
665 
666     if (did_create_ptr)
667         *did_create_ptr = false;
668     if (old_module_sp_ptr)
669         old_module_sp_ptr->reset();
670 
671     const UUID *uuid_ptr = module_spec.GetUUIDPtr();
672     const FileSpec &module_file_spec = module_spec.GetFileSpec();
673     const ArchSpec &arch = module_spec.GetArchitecture();
674 
675     // Make sure no one else can try and get or create a module while this
676     // function is actively working on it by doing an extra lock on the
677     // global mutex list.
678     if (always_create == false)
679     {
680         ModuleList matching_module_list;
681         const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list);
682         if (num_matching_modules > 0)
683         {
684             for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
685             {
686                 module_sp = matching_module_list.GetModuleAtIndex(module_idx);
687                 // If we had a UUID and we found a match, then that is good enough for a match
688                 if (uuid_ptr)
689                     break;
690                 if (module_file_spec)
691                 {
692                     // If we didn't have a UUID in mind when looking for the object file,
693                     // then we should make sure the modification time hasn't changed!
694                     TimeValue file_spec_mod_time(module_file_spec.GetModificationTime());
695                     if (file_spec_mod_time.IsValid())
696                     {
697                         if (file_spec_mod_time == module_sp->GetModificationTime())
698                             return error;
699                     }
700                 }
701                 if (old_module_sp_ptr && !old_module_sp_ptr->get())
702                     *old_module_sp_ptr = module_sp;
703                 shared_module_list.Remove (module_sp);
704                 module_sp.reset();
705             }
706         }
707     }
708 
709     if (module_sp)
710         return error;
711     else
712     {
713         module_sp.reset (new Module (module_spec));
714         // Make sure there are a module and an object file since we can specify
715         // a valid file path with an architecture that might not be in that file.
716         // By getting the object file we can guarantee that the architecture matches
717         if (module_sp)
718         {
719             if (module_sp->GetObjectFile())
720             {
721                 // If we get in here we got the correct arch, now we just need
722                 // to verify the UUID if one was given
723                 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
724                     module_sp.reset();
725                 else
726                 {
727                     if (did_create_ptr)
728                         *did_create_ptr = true;
729 
730                     shared_module_list.Append(module_sp);
731                     return error;
732                 }
733             }
734             else
735                 module_sp.reset();
736         }
737     }
738 
739     // Either the file didn't exist where at the path, or no path was given, so
740     // we now have to use more extreme measures to try and find the appropriate
741     // module.
742 
743     // Fixup the incoming path in case the path points to a valid file, yet
744     // the arch or UUID (if one was passed in) don't match.
745     FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec);
746 
747     // Don't look for the file if it appears to be the same one we already
748     // checked for above...
749     if (file_spec != module_file_spec)
750     {
751         if (!file_spec.Exists())
752         {
753             file_spec.GetPath(path, sizeof(path));
754             if (path[0] == '\0')
755                 module_file_spec.GetPath(path, sizeof(path));
756             if (file_spec.Exists())
757             {
758                 if (uuid_ptr && uuid_ptr->IsValid())
759                     uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
760                 else
761                     uuid_cstr[0] = '\0';
762 
763 
764                 if (arch.IsValid())
765                 {
766                     if (uuid_cstr[0])
767                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr);
768                     else
769                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
770                 }
771             }
772             else
773             {
774                 error.SetErrorStringWithFormat("'%s' does not exist", path);
775             }
776             if (error.Fail())
777                 module_sp.reset();
778             return error;
779         }
780 
781 
782         // Make sure no one else can try and get or create a module while this
783         // function is actively working on it by doing an extra lock on the
784         // global mutex list.
785         ModuleSpec platform_module_spec(module_spec);
786         platform_module_spec.GetFileSpec() = file_spec;
787         platform_module_spec.GetPlatformFileSpec() = file_spec;
788         ModuleList matching_module_list;
789         if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
790         {
791             module_sp = matching_module_list.GetModuleAtIndex(0);
792 
793             // If we didn't have a UUID in mind when looking for the object file,
794             // then we should make sure the modification time hasn't changed!
795             if (platform_module_spec.GetUUIDPtr() == NULL)
796             {
797                 TimeValue file_spec_mod_time(file_spec.GetModificationTime());
798                 if (file_spec_mod_time.IsValid())
799                 {
800                     if (file_spec_mod_time != module_sp->GetModificationTime())
801                     {
802                         if (old_module_sp_ptr)
803                             *old_module_sp_ptr = module_sp;
804                         shared_module_list.Remove (module_sp);
805                         module_sp.reset();
806                     }
807                 }
808             }
809         }
810 
811         if (module_sp.get() == NULL)
812         {
813             module_sp.reset (new Module (platform_module_spec));
814             // Make sure there are a module and an object file since we can specify
815             // a valid file path with an architecture that might not be in that file.
816             // By getting the object file we can guarantee that the architecture matches
817             if (module_sp && module_sp->GetObjectFile())
818             {
819                 if (did_create_ptr)
820                     *did_create_ptr = true;
821 
822                 shared_module_list.Append(module_sp);
823             }
824             else
825             {
826                 file_spec.GetPath(path, sizeof(path));
827 
828                 if (file_spec)
829                 {
830                     if (arch.IsValid())
831                         error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
832                     else
833                         error.SetErrorStringWithFormat("unable to open '%s'", path);
834                 }
835                 else
836                 {
837                     if (uuid_ptr && uuid_ptr->IsValid())
838                         uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
839                     else
840                         uuid_cstr[0] = '\0';
841 
842                     if (uuid_cstr[0])
843                         error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr);
844                     else
845                         error.SetErrorStringWithFormat("cannot locate a module");
846                 }
847             }
848         }
849     }
850 
851     return error;
852 }
853 
854 bool
855 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
856 {
857     return GetSharedModuleList ().Remove (module_sp);
858 }
859 
860 bool
861 ModuleList::RemoveSharedModuleIfOrphaned (const Module *module_ptr)
862 {
863     return GetSharedModuleList ().RemoveIfOrphaned (module_ptr);
864 }
865 
866 
867