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