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