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