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