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