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 ()
116 {
117     Mutex::Locker locker(m_modules_mutex);
118     collection::iterator pos = m_modules.begin();
119     size_t remove_count = 0;
120     while (pos != m_modules.end())
121     {
122         if (pos->unique())
123         {
124             pos = m_modules.erase (pos);
125             ++remove_count;
126         }
127         else
128         {
129             ++pos;
130         }
131     }
132     return remove_count;
133 }
134 
135 size_t
136 ModuleList::Remove (ModuleList &module_list)
137 {
138     Mutex::Locker locker(m_modules_mutex);
139     size_t num_removed = 0;
140     collection::iterator pos, end = module_list.m_modules.end();
141     for (pos = module_list.m_modules.begin(); pos != end; ++pos)
142     {
143         if (Remove (*pos))
144             ++num_removed;
145     }
146     return num_removed;
147 }
148 
149 
150 
151 void
152 ModuleList::Clear()
153 {
154     Mutex::Locker locker(m_modules_mutex);
155     m_modules.clear();
156 }
157 
158 void
159 ModuleList::Destroy()
160 {
161     Mutex::Locker locker(m_modules_mutex);
162     collection empty;
163     m_modules.swap(empty);
164 }
165 
166 Module*
167 ModuleList::GetModulePointerAtIndex (uint32_t idx) const
168 {
169     Mutex::Locker locker(m_modules_mutex);
170     if (idx < m_modules.size())
171         return m_modules[idx].get();
172     return NULL;
173 }
174 
175 ModuleSP
176 ModuleList::GetModuleAtIndex(uint32_t idx)
177 {
178     Mutex::Locker locker(m_modules_mutex);
179     ModuleSP module_sp;
180     if (idx < m_modules.size())
181         module_sp = m_modules[idx];
182     return module_sp;
183 }
184 
185 uint32_t
186 ModuleList::FindFunctions (const ConstString &name,
187                            uint32_t name_type_mask,
188                            bool include_symbols,
189                            bool include_inlines,
190                            bool append,
191                            SymbolContextList &sc_list)
192 {
193     if (!append)
194         sc_list.Clear();
195 
196     Mutex::Locker locker(m_modules_mutex);
197     collection::const_iterator pos, end = m_modules.end();
198     for (pos = m_modules.begin(); pos != end; ++pos)
199     {
200         (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
201     }
202 
203     return sc_list.GetSize();
204 }
205 
206 uint32_t
207 ModuleList::FindCompileUnits (const FileSpec &path,
208                               bool append,
209                               SymbolContextList &sc_list)
210 {
211     if (!append)
212         sc_list.Clear();
213 
214     Mutex::Locker locker(m_modules_mutex);
215     collection::const_iterator pos, end = m_modules.end();
216     for (pos = m_modules.begin(); pos != end; ++pos)
217     {
218         (*pos)->FindCompileUnits (path, true, sc_list);
219     }
220 
221     return sc_list.GetSize();
222 }
223 
224 uint32_t
225 ModuleList::FindGlobalVariables (const ConstString &name,
226                                  bool append,
227                                  uint32_t max_matches,
228                                  VariableList& variable_list)
229 {
230     size_t initial_size = variable_list.GetSize();
231     Mutex::Locker locker(m_modules_mutex);
232     collection::iterator pos, end = m_modules.end();
233     for (pos = m_modules.begin(); pos != end; ++pos)
234     {
235         (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list);
236     }
237     return variable_list.GetSize() - initial_size;
238 }
239 
240 
241 uint32_t
242 ModuleList::FindGlobalVariables (const RegularExpression& regex,
243                                  bool append,
244                                  uint32_t max_matches,
245                                  VariableList& variable_list)
246 {
247     size_t initial_size = variable_list.GetSize();
248     Mutex::Locker locker(m_modules_mutex);
249     collection::iterator pos, end = m_modules.end();
250     for (pos = m_modules.begin(); pos != end; ++pos)
251     {
252         (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
253     }
254     return variable_list.GetSize() - initial_size;
255 }
256 
257 
258 size_t
259 ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
260                                         SymbolType symbol_type,
261                                         SymbolContextList &sc_list,
262                                         bool append)
263 {
264     Mutex::Locker locker(m_modules_mutex);
265     if (!append)
266         sc_list.Clear();
267     size_t initial_size = sc_list.GetSize();
268 
269     collection::iterator pos, end = m_modules.end();
270     for (pos = m_modules.begin(); pos != end; ++pos)
271         (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
272     return sc_list.GetSize() - initial_size;
273 }
274 
275     size_t
276 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex,
277                                              lldb::SymbolType symbol_type,
278                                              SymbolContextList &sc_list,
279                                              bool append)
280 {
281     Mutex::Locker locker(m_modules_mutex);
282     if (!append)
283         sc_list.Clear();
284     size_t initial_size = sc_list.GetSize();
285 
286     collection::iterator pos, end = m_modules.end();
287     for (pos = m_modules.begin(); pos != end; ++pos)
288         (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
289     return sc_list.GetSize() - initial_size;
290 }
291 
292 class ModuleMatches
293 {
294 public:
295     //--------------------------------------------------------------
296     /// Construct with the user ID to look for.
297     //--------------------------------------------------------------
298     ModuleMatches (const FileSpec *file_spec_ptr,
299                    const ArchSpec *arch_ptr,
300                    const lldb_private::UUID *uuid_ptr,
301                    const ConstString *object_name,
302                    bool file_spec_is_platform) :
303         m_file_spec_ptr (file_spec_ptr),
304         m_arch_ptr (arch_ptr),
305         m_uuid_ptr (uuid_ptr),
306         m_object_name (object_name),
307         m_file_spec_compare_basename_only (false),
308         m_file_spec_is_platform (file_spec_is_platform)
309     {
310         if (file_spec_ptr)
311             m_file_spec_compare_basename_only = file_spec_ptr->GetDirectory();
312     }
313 
314 
315     //--------------------------------------------------------------
316     /// Unary predicate function object callback.
317     //--------------------------------------------------------------
318     bool
319     operator () (const ModuleSP& module_sp) const
320     {
321         if (m_file_spec_ptr)
322         {
323             if (m_file_spec_is_platform)
324             {
325                 if (!FileSpec::Equal (*m_file_spec_ptr,
326                                       module_sp->GetPlatformFileSpec(),
327                                       m_file_spec_compare_basename_only))
328                     return false;
329 
330             }
331             else
332             {
333                 if (!FileSpec::Equal (*m_file_spec_ptr,
334                                       module_sp->GetFileSpec(),
335                                       m_file_spec_compare_basename_only))
336                     return false;
337             }
338         }
339 
340         if (m_arch_ptr && m_arch_ptr->IsValid())
341         {
342             if (module_sp->GetArchitecture() != *m_arch_ptr)
343                 return false;
344         }
345 
346         if (m_uuid_ptr && m_uuid_ptr->IsValid())
347         {
348             if (module_sp->GetUUID() != *m_uuid_ptr)
349                 return false;
350         }
351 
352         if (m_object_name)
353         {
354             if (module_sp->GetObjectName() != *m_object_name)
355                 return false;
356         }
357         return true;
358     }
359 
360 private:
361     //--------------------------------------------------------------
362     // Member variables.
363     //--------------------------------------------------------------
364     const FileSpec *            m_file_spec_ptr;
365     const ArchSpec *            m_arch_ptr;
366     const lldb_private::UUID *  m_uuid_ptr;
367     const ConstString *         m_object_name;
368     bool                        m_file_spec_compare_basename_only;
369     bool                        m_file_spec_is_platform;
370 };
371 
372 size_t
373 ModuleList::FindModules
374 (
375     const FileSpec *file_spec_ptr,
376     const ArchSpec *arch_ptr,
377     const lldb_private::UUID *uuid_ptr,
378     const ConstString *object_name,
379     ModuleList& matching_module_list
380 ) const
381 {
382     size_t existing_matches = matching_module_list.GetSize();
383     ModuleMatches matcher (file_spec_ptr, arch_ptr, uuid_ptr, object_name, false);
384 
385     Mutex::Locker locker(m_modules_mutex);
386     collection::const_iterator end = m_modules.end();
387     collection::const_iterator pos;
388 
389     for (pos = std::find_if (m_modules.begin(), end, matcher);
390          pos != end;
391          pos = std::find_if (++pos, end, matcher))
392     {
393         ModuleSP module_sp(*pos);
394         matching_module_list.Append(module_sp);
395     }
396     return matching_module_list.GetSize() - existing_matches;
397 }
398 
399 ModuleSP
400 ModuleList::FindModule (const Module *module_ptr)
401 {
402     ModuleSP module_sp;
403 
404     // Scope for "locker"
405     {
406         Mutex::Locker locker(m_modules_mutex);
407         collection::const_iterator pos, end = m_modules.end();
408 
409         for (pos = m_modules.begin(); pos != end; ++pos)
410         {
411             if ((*pos).get() == module_ptr)
412             {
413                 module_sp = (*pos);
414                 break;
415             }
416         }
417     }
418     return module_sp;
419 
420 }
421 
422 ModuleSP
423 ModuleList::FindModule (const UUID &uuid)
424 {
425     ModuleSP module_sp;
426 
427     if (uuid.IsValid())
428     {
429         Mutex::Locker locker(m_modules_mutex);
430         collection::const_iterator pos, end = m_modules.end();
431 
432         for (pos = m_modules.begin(); pos != end; ++pos)
433         {
434             if ((*pos)->GetUUID() == uuid)
435             {
436                 module_sp = (*pos);
437                 break;
438             }
439         }
440     }
441     return module_sp;
442 }
443 
444 
445 uint32_t
446 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types)
447 {
448     Mutex::Locker locker(m_modules_mutex);
449 
450     if (!append)
451         types.Clear();
452 
453     uint32_t total_matches = 0;
454     collection::const_iterator pos, end = m_modules.end();
455     for (pos = m_modules.begin(); pos != end; ++pos)
456     {
457         if (sc.module_sp.get() == NULL || sc.module_sp.get() == (*pos).get())
458             total_matches += (*pos)->FindTypes (sc, name, NULL, true, max_matches, types);
459 
460         if (total_matches >= max_matches)
461             break;
462     }
463     return total_matches;
464 }
465 
466 ModuleSP
467 ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec,
468                                         const ArchSpec *arch_ptr,
469                                         const ConstString *object_name)
470 {
471     ModuleSP module_sp;
472     ModuleMatches matcher (&file_spec,
473                            arch_ptr,
474                            NULL,
475                            object_name,
476                            false);
477 
478     // Scope for "locker"
479     {
480         Mutex::Locker locker(m_modules_mutex);
481         collection::const_iterator end = m_modules.end();
482         collection::const_iterator pos = m_modules.begin();
483 
484         pos = std::find_if (pos, end, matcher);
485         if (pos != end)
486             module_sp = (*pos);
487     }
488     return module_sp;
489 
490 }
491 
492 ModuleSP
493 ModuleList::FindFirstModuleForPlatormFileSpec (const FileSpec &file_spec,
494                                                const ArchSpec *arch_ptr,
495                                                const ConstString *object_name)
496 {
497     ModuleSP module_sp;
498     ModuleMatches matcher (&file_spec,
499                            arch_ptr,
500                            NULL,
501                            object_name,
502                            true);
503 
504     // Scope for "locker"
505     {
506         Mutex::Locker locker(m_modules_mutex);
507         collection::const_iterator end = m_modules.end();
508         collection::const_iterator pos = m_modules.begin();
509 
510         pos = std::find_if (pos, end, matcher);
511         if (pos != end)
512             module_sp = (*pos);
513     }
514     return module_sp;
515 
516 }
517 
518 
519 size_t
520 ModuleList::GetSize() const
521 {
522     size_t size = 0;
523     {
524         Mutex::Locker locker(m_modules_mutex);
525         size = m_modules.size();
526     }
527     return size;
528 }
529 
530 
531 void
532 ModuleList::Dump(Stream *s) const
533 {
534 //  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
535 //  s.Indent();
536 //  s << "ModuleList\n";
537 
538     Mutex::Locker locker(m_modules_mutex);
539     collection::const_iterator pos, end = m_modules.end();
540     for (pos = m_modules.begin(); pos != end; ++pos)
541     {
542         (*pos)->Dump(s);
543     }
544 }
545 
546 void
547 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr)
548 {
549     if (log_sp)
550     {
551         Mutex::Locker locker(m_modules_mutex);
552         char uuid_cstr[256];
553         collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
554         for (pos = begin; pos != end; ++pos)
555         {
556             Module *module = pos->get();
557             module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr));
558             const FileSpec &module_file_spec = module->GetFileSpec();
559             log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"",
560                             prefix_cstr ? prefix_cstr : "",
561                             (uint32_t)std::distance (begin, pos),
562                             uuid_cstr,
563                             module->GetArchitecture().GetArchitectureName(),
564                             module_file_spec.GetDirectory().GetCString(),
565                             module_file_spec.GetFilename().GetCString());
566         }
567     }
568 }
569 
570 bool
571 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
572 {
573     Mutex::Locker locker(m_modules_mutex);
574     collection::const_iterator pos, end = m_modules.end();
575     for (pos = m_modules.begin(); pos != end; ++pos)
576     {
577         if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
578             return true;
579     }
580 
581     return false;
582 }
583 
584 uint32_t
585 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
586 {
587     // The address is already section offset so it has a module
588     uint32_t resolved_flags = 0;
589     Module *module = so_addr.GetModulePtr();
590     if (module)
591     {
592         resolved_flags = module->ResolveSymbolContextForAddress (so_addr,
593                                                                  resolve_scope,
594                                                                  sc);
595     }
596     else
597     {
598         Mutex::Locker locker(m_modules_mutex);
599         collection::const_iterator pos, end = m_modules.end();
600         for (pos = m_modules.begin(); pos != end; ++pos)
601         {
602             resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
603                                                                      resolve_scope,
604                                                                      sc);
605             if (resolved_flags != 0)
606                 break;
607         }
608     }
609 
610     return resolved_flags;
611 }
612 
613 uint32_t
614 ModuleList::ResolveSymbolContextForFilePath
615 (
616     const char *file_path,
617     uint32_t line,
618     bool check_inlines,
619     uint32_t resolve_scope,
620     SymbolContextList& sc_list
621 )
622 {
623     FileSpec file_spec(file_path, false);
624     return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
625 }
626 
627 uint32_t
628 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
629 {
630     Mutex::Locker locker(m_modules_mutex);
631     collection::const_iterator pos, end = m_modules.end();
632     for (pos = m_modules.begin(); pos != end; ++pos)
633     {
634         (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
635     }
636 
637     return sc_list.GetSize();
638 }
639 
640 uint32_t
641 ModuleList::GetIndexForModule (const Module *module) const
642 {
643     if (module)
644     {
645         Mutex::Locker locker(m_modules_mutex);
646         collection::const_iterator pos;
647         collection::const_iterator begin = m_modules.begin();
648         collection::const_iterator end = m_modules.end();
649         for (pos = begin; pos != end; ++pos)
650         {
651             if ((*pos).get() == module)
652                 return std::distance (begin, pos);
653         }
654     }
655     return LLDB_INVALID_INDEX32;
656 }
657 
658 static ModuleList &
659 GetSharedModuleList ()
660 {
661     static ModuleList g_shared_module_list;
662     return g_shared_module_list;
663 }
664 
665 bool
666 ModuleList::ModuleIsInCache (const Module *module_ptr)
667 {
668     if (module_ptr)
669     {
670         ModuleList &shared_module_list = GetSharedModuleList ();
671         return shared_module_list.FindModule (module_ptr).get() != NULL;
672     }
673     return false;
674 }
675 
676 size_t
677 ModuleList::FindSharedModules
678 (
679     const FileSpec& in_file_spec,
680     const ArchSpec& arch,
681     const lldb_private::UUID *uuid_ptr,
682     const ConstString *object_name_ptr,
683     ModuleList &matching_module_list
684 )
685 {
686     ModuleList &shared_module_list = GetSharedModuleList ();
687     return shared_module_list.FindModules (&in_file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list);
688 }
689 
690 uint32_t
691 ModuleList::RemoveOrphanSharedModules ()
692 {
693     return GetSharedModuleList ().RemoveOrphans();
694 }
695 //#define ENABLE_MODULE_SP_LOGGING
696 #if defined (ENABLE_MODULE_SP_LOGGING)
697 #include "lldb/Core/StreamFile.h"
698 #include "lldb/Host/Host.h"
699 static void
700 ModuleSharedPtrLogger(void* p, const ModuleSP& sp, bool will_decrement)
701 {
702     if (sp.get())
703     {
704         const char *module_basename = sp->GetFileSpec().GetFilename().GetCString();
705         // If "p" is set, then it is the basename of a module to watch for. This
706         // basename MUST be uniqued first by getting it from a ConstString or this
707         // won't work.
708         if (p && p != module_basename)
709         {
710             return;
711         }
712         long use_count = sp.use_count();
713         if (will_decrement)
714             --use_count;
715 
716         printf("\nModuleSP(%p): %c %p {%lu} %s/%s\n", &sp, will_decrement ? '-' : '+', sp.get(), use_count, sp->GetFileSpec().GetDirectory().GetCString(), module_basename);
717         StreamFile stdout_strm(stdout, false);
718         Host::Backtrace (stdout_strm, 512);
719     }
720 }
721 #endif
722 
723 Error
724 ModuleList::GetSharedModule
725 (
726     const FileSpec& in_file_spec,
727     const ArchSpec& arch,
728     const lldb_private::UUID *uuid_ptr,
729     const ConstString *object_name_ptr,
730     off_t object_offset,
731     ModuleSP &module_sp,
732     const FileSpecList *module_search_paths_ptr,
733     ModuleSP *old_module_sp_ptr,
734     bool *did_create_ptr,
735     bool always_create
736 )
737 {
738     ModuleList &shared_module_list = GetSharedModuleList ();
739     Mutex::Locker locker(shared_module_list.m_modules_mutex);
740     char path[PATH_MAX];
741     char uuid_cstr[64];
742 
743     Error error;
744 
745     module_sp.reset();
746 
747     if (did_create_ptr)
748         *did_create_ptr = false;
749     if (old_module_sp_ptr)
750         old_module_sp_ptr->reset();
751 
752 
753     // First just try and get the file where it purports to be (path in
754     // in_file_spec), then check and uuid.
755 
756     if (in_file_spec)
757     {
758         // Make sure no one else can try and get or create a module while this
759         // function is actively working on it by doing an extra lock on the
760         // global mutex list.
761         if (always_create == false)
762         {
763             ModuleList matching_module_list;
764             const size_t num_matching_modules = shared_module_list.FindModules (&in_file_spec, &arch, NULL, object_name_ptr, matching_module_list);
765             if (num_matching_modules > 0)
766             {
767                 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
768                 {
769                     module_sp = matching_module_list.GetModuleAtIndex(module_idx);
770                     if (uuid_ptr && uuid_ptr->IsValid())
771                     {
772                         // We found the module we were looking for.
773                         if (module_sp->GetUUID() == *uuid_ptr)
774                             return error;
775                     }
776                     else
777                     {
778                         // If we didn't have a UUID in mind when looking for the object file,
779                         // then we should make sure the modification time hasn't changed!
780                         TimeValue file_spec_mod_time(in_file_spec.GetModificationTime());
781                         if (file_spec_mod_time.IsValid())
782                         {
783                             if (file_spec_mod_time == module_sp->GetModificationTime())
784                                 return error;
785                         }
786                     }
787                     if (old_module_sp_ptr && !old_module_sp_ptr->get())
788                         *old_module_sp_ptr = module_sp;
789                     shared_module_list.Remove (module_sp);
790                     module_sp.reset();
791                 }
792             }
793         }
794 
795         if (module_sp)
796             return error;
797         else
798         {
799 #if defined ENABLE_MODULE_SP_LOGGING
800             ModuleSP logging_module_sp (new Module (in_file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, (void *)ConstString("a.out").GetCString());
801             module_sp = logging_module_sp;
802 #else
803             module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset));
804 #endif
805             // Make sure there are a module and an object file since we can specify
806             // a valid file path with an architecture that might not be in that file.
807             // By getting the object file we can guarantee that the architecture matches
808             if (module_sp)
809             {
810                 if (module_sp->GetObjectFile())
811                 {
812                     // If we get in here we got the correct arch, now we just need
813                     // to verify the UUID if one was given
814                     if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
815                         module_sp.reset();
816                     else
817                     {
818                         if (did_create_ptr)
819                             *did_create_ptr = true;
820 
821                         shared_module_list.Append(module_sp);
822                         return error;
823                     }
824                 }
825                 else
826                     module_sp.reset();
827             }
828         }
829     }
830 
831     // Either the file didn't exist where at the path, or no path was given, so
832     // we now have to use more extreme measures to try and find the appropriate
833     // module.
834 
835     // Fixup the incoming path in case the path points to a valid file, yet
836     // the arch or UUID (if one was passed in) don't match.
837     FileSpec file_spec = Symbols::LocateExecutableObjectFile (in_file_spec ? &in_file_spec : NULL,
838                                                               arch.IsValid() ? &arch : NULL,
839                                                               uuid_ptr);
840 
841     // Don't look for the file if it appears to be the same one we already
842     // checked for above...
843     if (file_spec != in_file_spec)
844     {
845         if (!file_spec.Exists())
846         {
847             file_spec.GetPath(path, sizeof(path));
848             if (path[0] == '\0')
849                 in_file_spec.GetPath(path, sizeof(path));
850             if (file_spec.Exists())
851             {
852                 if (uuid_ptr && uuid_ptr->IsValid())
853                     uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
854                 else
855                     uuid_cstr[0] = '\0';
856 
857 
858                 if (arch.IsValid())
859                 {
860                     if (uuid_cstr[0])
861                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr);
862                     else
863                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
864                 }
865             }
866             else
867             {
868                 error.SetErrorStringWithFormat("'%s' does not exist", path);
869             }
870             if (error.Fail())
871                 module_sp.reset();
872             return error;
873         }
874 
875 
876         // Make sure no one else can try and get or create a module while this
877         // function is actively working on it by doing an extra lock on the
878         // global mutex list.
879         ModuleList matching_module_list;
880         if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0)
881         {
882             module_sp = matching_module_list.GetModuleAtIndex(0);
883 
884             // If we didn't have a UUID in mind when looking for the object file,
885             // then we should make sure the modification time hasn't changed!
886             if (uuid_ptr == NULL)
887             {
888                 TimeValue file_spec_mod_time(file_spec.GetModificationTime());
889                 if (file_spec_mod_time.IsValid())
890                 {
891                     if (file_spec_mod_time != module_sp->GetModificationTime())
892                     {
893                         if (old_module_sp_ptr)
894                             *old_module_sp_ptr = module_sp;
895                         shared_module_list.Remove (module_sp);
896                         module_sp.reset();
897                     }
898                 }
899             }
900         }
901 
902         if (module_sp.get() == NULL)
903         {
904 #if defined ENABLE_MODULE_SP_LOGGING
905             ModuleSP logging_module_sp (new Module (file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, 0);
906             module_sp = logging_module_sp;
907 #else
908             module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset));
909 #endif
910             // Make sure there are a module and an object file since we can specify
911             // a valid file path with an architecture that might not be in that file.
912             // By getting the object file we can guarantee that the architecture matches
913             if (module_sp && module_sp->GetObjectFile())
914             {
915                 if (did_create_ptr)
916                     *did_create_ptr = true;
917 
918                 shared_module_list.Append(module_sp);
919             }
920             else
921             {
922                 file_spec.GetPath(path, sizeof(path));
923 
924                 if (file_spec)
925                 {
926                     if (arch.IsValid())
927                         error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
928                     else
929                         error.SetErrorStringWithFormat("unable to open '%s'", path);
930                 }
931                 else
932                 {
933                     if (uuid_ptr && uuid_ptr->IsValid())
934                         uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
935                     else
936                         uuid_cstr[0] = '\0';
937 
938                     if (uuid_cstr[0])
939                         error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr);
940                     else
941                         error.SetErrorStringWithFormat("cannot locate a module");
942                 }
943             }
944         }
945     }
946 
947     return error;
948 }
949 
950 bool
951 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
952 {
953     return GetSharedModuleList ().Remove (module_sp);
954 }
955 
956 
957