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