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 (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 ModuleSP
458 ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec,
459                                         const ArchSpec *arch_ptr,
460                                         const ConstString *object_name)
461 {
462     ModuleSP module_sp;
463     ModuleMatches matcher (&file_spec,
464                            arch_ptr,
465                            NULL,
466                            object_name,
467                            false);
468 
469     // Scope for "locker"
470     {
471         Mutex::Locker locker(m_modules_mutex);
472         collection::const_iterator end = m_modules.end();
473         collection::const_iterator pos = m_modules.begin();
474 
475         pos = std::find_if (pos, end, matcher);
476         if (pos != end)
477             module_sp = (*pos);
478     }
479     return module_sp;
480 
481 }
482 
483 ModuleSP
484 ModuleList::FindFirstModuleForPlatormFileSpec (const FileSpec &file_spec,
485                                                const ArchSpec *arch_ptr,
486                                                const ConstString *object_name)
487 {
488     ModuleSP module_sp;
489     ModuleMatches matcher (&file_spec,
490                            arch_ptr,
491                            NULL,
492                            object_name,
493                            true);
494 
495     // Scope for "locker"
496     {
497         Mutex::Locker locker(m_modules_mutex);
498         collection::const_iterator end = m_modules.end();
499         collection::const_iterator pos = m_modules.begin();
500 
501         pos = std::find_if (pos, end, matcher);
502         if (pos != end)
503             module_sp = (*pos);
504     }
505     return module_sp;
506 
507 }
508 
509 
510 size_t
511 ModuleList::GetSize() const
512 {
513     size_t size = 0;
514     {
515         Mutex::Locker locker(m_modules_mutex);
516         size = m_modules.size();
517     }
518     return size;
519 }
520 
521 
522 void
523 ModuleList::Dump(Stream *s) const
524 {
525 //  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
526 //  s.Indent();
527 //  s << "ModuleList\n";
528 
529     Mutex::Locker locker(m_modules_mutex);
530     collection::const_iterator pos, end = m_modules.end();
531     for (pos = m_modules.begin(); pos != end; ++pos)
532     {
533         (*pos)->Dump(s);
534     }
535 }
536 
537 void
538 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr)
539 {
540     if (log_sp)
541     {
542         Mutex::Locker locker(m_modules_mutex);
543         char uuid_cstr[256];
544         collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
545         for (pos = begin; pos != end; ++pos)
546         {
547             Module *module = pos->get();
548             module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr));
549             const FileSpec &module_file_spec = module->GetFileSpec();
550             log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"",
551                             prefix_cstr ? prefix_cstr : "",
552                             (uint32_t)std::distance (begin, pos),
553                             uuid_cstr,
554                             module->GetArchitecture().GetArchitectureName(),
555                             module_file_spec.GetDirectory().GetCString(),
556                             module_file_spec.GetFilename().GetCString());
557         }
558     }
559 }
560 
561 bool
562 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
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         if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
569             return true;
570     }
571 
572     return false;
573 }
574 
575 uint32_t
576 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
577 {
578     // The address is already section offset so it has a module
579     uint32_t resolved_flags = 0;
580     Module *module = so_addr.GetModule();
581     if (module)
582     {
583         resolved_flags = module->ResolveSymbolContextForAddress (so_addr,
584                                                                  resolve_scope,
585                                                                  sc);
586     }
587     else
588     {
589         Mutex::Locker locker(m_modules_mutex);
590         collection::const_iterator pos, end = m_modules.end();
591         for (pos = m_modules.begin(); pos != end; ++pos)
592         {
593             resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
594                                                                      resolve_scope,
595                                                                      sc);
596             if (resolved_flags != 0)
597                 break;
598         }
599     }
600 
601     return resolved_flags;
602 }
603 
604 uint32_t
605 ModuleList::ResolveSymbolContextForFilePath
606 (
607     const char *file_path,
608     uint32_t line,
609     bool check_inlines,
610     uint32_t resolve_scope,
611     SymbolContextList& sc_list
612 )
613 {
614     FileSpec file_spec(file_path, false);
615     return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
616 }
617 
618 uint32_t
619 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
620 {
621     Mutex::Locker locker(m_modules_mutex);
622     collection::const_iterator pos, end = m_modules.end();
623     for (pos = m_modules.begin(); pos != end; ++pos)
624     {
625         (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
626     }
627 
628     return sc_list.GetSize();
629 }
630 
631 uint32_t
632 ModuleList::GetIndexForModule (const Module *module) const
633 {
634     if (module)
635     {
636         Mutex::Locker locker(m_modules_mutex);
637         collection::const_iterator pos;
638         collection::const_iterator begin = m_modules.begin();
639         collection::const_iterator end = m_modules.end();
640         for (pos = begin; pos != end; ++pos)
641         {
642             if ((*pos).get() == module)
643                 return std::distance (begin, pos);
644         }
645     }
646     return LLDB_INVALID_INDEX32;
647 }
648 
649 static ModuleList &
650 GetSharedModuleList ()
651 {
652     static ModuleList g_shared_module_list;
653     return g_shared_module_list;
654 }
655 
656 const lldb::ModuleSP
657 ModuleList::GetModuleSP (const Module *module_ptr)
658 {
659     lldb::ModuleSP module_sp;
660     if (module_ptr)
661     {
662         ModuleList &shared_module_list = GetSharedModuleList ();
663         module_sp = shared_module_list.FindModule (module_ptr);
664         if (module_sp.get() == NULL)
665         {
666             char uuid_cstr[256];
667             const_cast<Module *>(module_ptr)->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr));
668             const FileSpec &module_file_spec = module_ptr->GetFileSpec();
669             Host::SystemLog (Host::eSystemLogWarning,
670                              "warning: module not in shared module list: %s (%s) \"%s/%s\"\n",
671                              uuid_cstr,
672                              module_ptr->GetArchitecture().GetArchitectureName(),
673                              module_file_spec.GetDirectory().GetCString(),
674                              module_file_spec.GetFilename().GetCString());
675         }
676     }
677     return module_sp;
678 }
679 
680 size_t
681 ModuleList::FindSharedModules
682 (
683     const FileSpec& in_file_spec,
684     const ArchSpec& arch,
685     const lldb_private::UUID *uuid_ptr,
686     const ConstString *object_name_ptr,
687     ModuleList &matching_module_list
688 )
689 {
690     ModuleList &shared_module_list = GetSharedModuleList ();
691     return shared_module_list.FindModules (&in_file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list);
692 }
693 
694 uint32_t
695 ModuleList::RemoveOrphanSharedModules ()
696 {
697     return GetSharedModuleList ().RemoveOrphans();
698 }
699 //#define ENABLE_MODULE_SP_LOGGING
700 #if defined (ENABLE_MODULE_SP_LOGGING)
701 #include "lldb/Core/StreamFile.h"
702 #include "lldb/Host/Host.h"
703 static void
704 ModuleSharedPtrLogger(void* p, const ModuleSP& sp, bool will_decrement)
705 {
706     if (sp.get())
707     {
708         const char *module_basename = sp->GetFileSpec().GetFilename().GetCString();
709         // If "p" is set, then it is the basename of a module to watch for. This
710         // basename MUST be uniqued first by getting it from a ConstString or this
711         // won't work.
712         if (p && p != module_basename)
713         {
714             return;
715         }
716         long use_count = sp.use_count();
717         if (will_decrement)
718             --use_count;
719 
720         printf("\nModuleSP(%p): %c %p {%lu} %s/%s\n", &sp, will_decrement ? '-' : '+', sp.get(), use_count, sp->GetFileSpec().GetDirectory().GetCString(), module_basename);
721         StreamFile stdout_strm(stdout, false);
722         Host::Backtrace (stdout_strm, 512);
723     }
724 }
725 #endif
726 
727 Error
728 ModuleList::GetSharedModule
729 (
730     const FileSpec& in_file_spec,
731     const ArchSpec& arch,
732     const lldb_private::UUID *uuid_ptr,
733     const ConstString *object_name_ptr,
734     off_t object_offset,
735     ModuleSP &module_sp,
736     ModuleSP *old_module_sp_ptr,
737     bool *did_create_ptr,
738     bool always_create
739 )
740 {
741     ModuleList &shared_module_list = GetSharedModuleList ();
742     Mutex::Locker locker(shared_module_list.m_modules_mutex);
743     char path[PATH_MAX];
744     char uuid_cstr[64];
745 
746     Error error;
747 
748     module_sp.reset();
749 
750     if (did_create_ptr)
751         *did_create_ptr = false;
752     if (old_module_sp_ptr)
753         old_module_sp_ptr->reset();
754 
755 
756     // First just try and get the file where it purports to be (path in
757     // in_file_spec), then check and uuid.
758 
759     if (in_file_spec)
760     {
761         // Make sure no one else can try and get or create a module while this
762         // function is actively working on it by doing an extra lock on the
763         // global mutex list.
764         if (always_create == false)
765         {
766             ModuleList matching_module_list;
767             const size_t num_matching_modules = shared_module_list.FindModules (&in_file_spec, &arch, NULL, object_name_ptr, matching_module_list);
768             if (num_matching_modules > 0)
769             {
770                 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
771                 {
772                     module_sp = matching_module_list.GetModuleAtIndex(module_idx);
773                     if (uuid_ptr && uuid_ptr->IsValid())
774                     {
775                         // We found the module we were looking for.
776                         if (module_sp->GetUUID() == *uuid_ptr)
777                             return error;
778                     }
779                     else
780                     {
781                         // If we didn't have a UUID in mind when looking for the object file,
782                         // then we should make sure the modification time hasn't changed!
783                         TimeValue file_spec_mod_time(in_file_spec.GetModificationTime());
784                         if (file_spec_mod_time.IsValid())
785                         {
786                             if (file_spec_mod_time == module_sp->GetModificationTime())
787                                 return error;
788                         }
789                     }
790                     if (old_module_sp_ptr && !old_module_sp_ptr->get())
791                         *old_module_sp_ptr = module_sp;
792                     shared_module_list.Remove (module_sp);
793                     module_sp.reset();
794                 }
795             }
796         }
797 
798         if (module_sp)
799             return error;
800         else
801         {
802 #if defined ENABLE_MODULE_SP_LOGGING
803             ModuleSP logging_module_sp (new Module (in_file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, (void *)ConstString("a.out").GetCString());
804             module_sp = logging_module_sp;
805 #else
806             module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset));
807 #endif
808             // Make sure there are a module and an object file since we can specify
809             // a valid file path with an architecture that might not be in that file.
810             // By getting the object file we can guarantee that the architecture matches
811             if (module_sp && module_sp->GetObjectFile())
812             {
813                 // If we get in here we got the correct arch, now we just need
814                 // to verify the UUID if one was given
815                 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
816                     module_sp.reset();
817                 else
818                 {
819                     if (did_create_ptr)
820                         *did_create_ptr = true;
821 
822                     shared_module_list.Append(module_sp);
823                     return error;
824                 }
825             }
826         }
827     }
828 
829     // Either the file didn't exist where at the path, or no path was given, so
830     // we now have to use more extreme measures to try and find the appropriate
831     // module.
832 
833     // Fixup the incoming path in case the path points to a valid file, yet
834     // the arch or UUID (if one was passed in) don't match.
835     FileSpec file_spec = Symbols::LocateExecutableObjectFile (in_file_spec ? &in_file_spec : NULL,
836                                                               arch.IsValid() ? &arch : NULL,
837                                                               uuid_ptr);
838 
839     // Don't look for the file if it appears to be the same one we already
840     // checked for above...
841     if (file_spec != in_file_spec)
842     {
843         if (!file_spec.Exists())
844         {
845             file_spec.GetPath(path, sizeof(path));
846             if (path[0] == '\0')
847                 in_file_spec.GetPath(path, sizeof(path));
848             if (file_spec.Exists())
849             {
850                 if (uuid_ptr && uuid_ptr->IsValid())
851                     uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
852                 else
853                     uuid_cstr[0] = '\0';
854 
855 
856                 if (arch.IsValid())
857                 {
858                     if (uuid_cstr[0])
859                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr);
860                     else
861                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
862                 }
863             }
864             else
865             {
866                 error.SetErrorStringWithFormat("'%s' does not exist", path);
867             }
868             return error;
869         }
870 
871 
872         // Make sure no one else can try and get or create a module while this
873         // function is actively working on it by doing an extra lock on the
874         // global mutex list.
875         ModuleList matching_module_list;
876         if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0)
877         {
878             module_sp = matching_module_list.GetModuleAtIndex(0);
879 
880             // If we didn't have a UUID in mind when looking for the object file,
881             // then we should make sure the modification time hasn't changed!
882             if (uuid_ptr == NULL)
883             {
884                 TimeValue file_spec_mod_time(file_spec.GetModificationTime());
885                 if (file_spec_mod_time.IsValid())
886                 {
887                     if (file_spec_mod_time != module_sp->GetModificationTime())
888                     {
889                         if (old_module_sp_ptr)
890                             *old_module_sp_ptr = module_sp;
891                         shared_module_list.Remove (module_sp);
892                         module_sp.reset();
893                     }
894                 }
895             }
896         }
897 
898         if (module_sp.get() == NULL)
899         {
900 #if defined ENABLE_MODULE_SP_LOGGING
901             ModuleSP logging_module_sp (new Module (file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, 0);
902             module_sp = logging_module_sp;
903 #else
904             module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset));
905 #endif
906             // Make sure there are a module and an object file since we can specify
907             // a valid file path with an architecture that might not be in that file.
908             // By getting the object file we can guarantee that the architecture matches
909             if (module_sp && module_sp->GetObjectFile())
910             {
911                 if (did_create_ptr)
912                     *did_create_ptr = true;
913 
914                 shared_module_list.Append(module_sp);
915             }
916             else
917             {
918                 file_spec.GetPath(path, sizeof(path));
919 
920                 if (file_spec)
921                 {
922                     if (arch.IsValid())
923                         error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
924                     else
925                         error.SetErrorStringWithFormat("unable to open '%s'", path);
926                 }
927                 else
928                 {
929                     if (uuid_ptr && uuid_ptr->IsValid())
930                         uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
931                     else
932                         uuid_cstr[0] = '\0';
933 
934                     if (uuid_cstr[0])
935                         error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr);
936                     else
937                         error.SetErrorStringWithFormat("cannot locate a module");
938                 }
939             }
940         }
941     }
942 
943     return error;
944 }
945 
946 bool
947 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
948 {
949     return GetSharedModuleList ().Remove (module_sp);
950 }
951 
952 
953