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