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 size_t
112 ModuleList::Remove (ModuleList &module_list)
113 {
114     Mutex::Locker locker(m_modules_mutex);
115     size_t num_removed = 0;
116     collection::iterator pos, end = module_list.m_modules.end();
117     for (pos = module_list.m_modules.begin(); pos != end; ++pos)
118     {
119         if (Remove (*pos))
120             ++num_removed;
121     }
122     return num_removed;
123 }
124 
125 
126 
127 void
128 ModuleList::Clear()
129 {
130     Mutex::Locker locker(m_modules_mutex);
131     m_modules.clear();
132 }
133 
134 Module*
135 ModuleList::GetModulePointerAtIndex (uint32_t idx) const
136 {
137     Mutex::Locker locker(m_modules_mutex);
138     if (idx < m_modules.size())
139         return m_modules[idx].get();
140     return NULL;
141 }
142 
143 ModuleSP
144 ModuleList::GetModuleAtIndex(uint32_t idx)
145 {
146     Mutex::Locker locker(m_modules_mutex);
147     ModuleSP module_sp;
148     if (idx < m_modules.size())
149         module_sp = m_modules[idx];
150     return module_sp;
151 }
152 
153 size_t
154 ModuleList::FindFunctions (const ConstString &name,
155                            uint32_t name_type_mask,
156                            bool include_symbols,
157                            bool append,
158                            SymbolContextList &sc_list)
159 {
160     if (!append)
161         sc_list.Clear();
162 
163     Mutex::Locker locker(m_modules_mutex);
164     collection::const_iterator pos, end = m_modules.end();
165     for (pos = m_modules.begin(); pos != end; ++pos)
166     {
167         (*pos)->FindFunctions (name, name_type_mask, include_symbols, true, sc_list);
168     }
169 
170     return sc_list.GetSize();
171 }
172 
173 uint32_t
174 ModuleList::FindGlobalVariables (const ConstString &name,
175                                  bool append,
176                                  uint32_t max_matches,
177                                  VariableList& variable_list)
178 {
179     size_t initial_size = variable_list.GetSize();
180     Mutex::Locker locker(m_modules_mutex);
181     collection::iterator pos, end = m_modules.end();
182     for (pos = m_modules.begin(); pos != end; ++pos)
183     {
184         (*pos)->FindGlobalVariables (name, append, max_matches, variable_list);
185     }
186     return variable_list.GetSize() - initial_size;
187 }
188 
189 
190 uint32_t
191 ModuleList::FindGlobalVariables (const RegularExpression& regex,
192                                  bool append,
193                                  uint32_t max_matches,
194                                  VariableList& variable_list)
195 {
196     size_t initial_size = variable_list.GetSize();
197     Mutex::Locker locker(m_modules_mutex);
198     collection::iterator pos, end = m_modules.end();
199     for (pos = m_modules.begin(); pos != end; ++pos)
200     {
201         (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
202     }
203     return variable_list.GetSize() - initial_size;
204 }
205 
206 
207 size_t
208 ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
209                                         SymbolType symbol_type,
210                                         SymbolContextList &sc_list)
211 {
212     Mutex::Locker locker(m_modules_mutex);
213     sc_list.Clear();
214     collection::iterator pos, end = m_modules.end();
215     for (pos = m_modules.begin(); pos != end; ++pos)
216         (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
217     return sc_list.GetSize();
218 }
219 
220 class ModuleMatches
221 {
222 public:
223     //--------------------------------------------------------------
224     /// Construct with the user ID to look for.
225     //--------------------------------------------------------------
226     ModuleMatches (const FileSpec *file_spec_ptr,
227                    const ArchSpec *arch_ptr,
228                    const lldb_private::UUID *uuid_ptr,
229                    const ConstString *object_name,
230                    bool file_spec_is_platform) :
231         m_file_spec_ptr (file_spec_ptr),
232         m_arch_ptr (arch_ptr),
233         m_uuid_ptr (uuid_ptr),
234         m_object_name (object_name),
235         m_file_spec_compare_basename_only (false),
236         m_file_spec_is_platform (file_spec_is_platform)
237     {
238         if (file_spec_ptr)
239             m_file_spec_compare_basename_only = file_spec_ptr->GetDirectory();
240     }
241 
242 
243     //--------------------------------------------------------------
244     /// Unary predicate function object callback.
245     //--------------------------------------------------------------
246     bool
247     operator () (const ModuleSP& module_sp) const
248     {
249         if (m_file_spec_ptr)
250         {
251             if (m_file_spec_is_platform)
252             {
253                 if (!FileSpec::Equal (*m_file_spec_ptr,
254                                       module_sp->GetPlatformFileSpec(),
255                                       m_file_spec_compare_basename_only))
256                     return false;
257 
258             }
259             else
260             {
261                 if (!FileSpec::Equal (*m_file_spec_ptr,
262                                       module_sp->GetFileSpec(),
263                                       m_file_spec_compare_basename_only))
264                     return false;
265             }
266         }
267 
268         if (m_arch_ptr && m_arch_ptr->IsValid())
269         {
270             if (module_sp->GetArchitecture() != *m_arch_ptr)
271                 return false;
272         }
273 
274         if (m_uuid_ptr && m_uuid_ptr->IsValid())
275         {
276             if (module_sp->GetUUID() != *m_uuid_ptr)
277                 return false;
278         }
279 
280         if (m_object_name)
281         {
282             if (module_sp->GetObjectName() != *m_object_name)
283                 return false;
284         }
285         return true;
286     }
287 
288 private:
289     //--------------------------------------------------------------
290     // Member variables.
291     //--------------------------------------------------------------
292     const FileSpec *            m_file_spec_ptr;
293     const ArchSpec *            m_arch_ptr;
294     const lldb_private::UUID *  m_uuid_ptr;
295     const ConstString *         m_object_name;
296     bool                        m_file_spec_compare_basename_only;
297     bool                        m_file_spec_is_platform;
298 };
299 
300 size_t
301 ModuleList::FindModules
302 (
303     const FileSpec *file_spec_ptr,
304     const ArchSpec *arch_ptr,
305     const lldb_private::UUID *uuid_ptr,
306     const ConstString *object_name,
307     ModuleList& matching_module_list
308 ) const
309 {
310     size_t existing_matches = matching_module_list.GetSize();
311     ModuleMatches matcher (file_spec_ptr, arch_ptr, uuid_ptr, object_name, false);
312 
313     Mutex::Locker locker(m_modules_mutex);
314     collection::const_iterator end = m_modules.end();
315     collection::const_iterator pos;
316 
317     for (pos = std::find_if (m_modules.begin(), end, matcher);
318          pos != end;
319          pos = std::find_if (++pos, end, matcher))
320     {
321         ModuleSP module_sp(*pos);
322         matching_module_list.Append(module_sp);
323     }
324     return matching_module_list.GetSize() - existing_matches;
325 }
326 
327 ModuleSP
328 ModuleList::FindModule (const Module *module_ptr)
329 {
330     ModuleSP module_sp;
331 
332     // Scope for "locker"
333     {
334         Mutex::Locker locker(m_modules_mutex);
335         collection::const_iterator pos, end = m_modules.end();
336 
337         for (pos = m_modules.begin(); pos != end; ++pos)
338         {
339             if ((*pos).get() == module_ptr)
340             {
341                 module_sp = (*pos);
342                 break;
343             }
344         }
345     }
346     return module_sp;
347 
348 }
349 
350 ModuleSP
351 ModuleList::FindModule (const UUID &uuid)
352 {
353     ModuleSP module_sp;
354 
355     if (uuid.IsValid())
356     {
357         Mutex::Locker locker(m_modules_mutex);
358         collection::const_iterator pos, end = m_modules.end();
359 
360         for (pos = m_modules.begin(); pos != end; ++pos)
361         {
362             if ((*pos)->GetUUID() == uuid)
363             {
364                 module_sp = (*pos);
365                 break;
366             }
367         }
368     }
369     return module_sp;
370 }
371 
372 
373 uint32_t
374 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types)
375 {
376     Mutex::Locker locker(m_modules_mutex);
377 
378     if (!append)
379         types.Clear();
380 
381     uint32_t total_matches = 0;
382     collection::const_iterator pos, end = m_modules.end();
383     for (pos = m_modules.begin(); pos != end; ++pos)
384     {
385         if (sc.module_sp.get() == NULL || sc.module_sp.get() == (*pos).get())
386             total_matches += (*pos)->FindTypes (sc, name, true, max_matches, types);
387 
388         if (total_matches >= max_matches)
389             break;
390     }
391     return total_matches;
392 }
393 
394 
395 ModuleSP
396 ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec,
397                                         const ArchSpec *arch_ptr,
398                                         const ConstString *object_name)
399 {
400     ModuleSP module_sp;
401     ModuleMatches matcher (&file_spec,
402                            arch_ptr,
403                            NULL,
404                            object_name,
405                            false);
406 
407     // Scope for "locker"
408     {
409         Mutex::Locker locker(m_modules_mutex);
410         collection::const_iterator end = m_modules.end();
411         collection::const_iterator pos = m_modules.begin();
412 
413         pos = std::find_if (pos, end, matcher);
414         if (pos != end)
415             module_sp = (*pos);
416     }
417     return module_sp;
418 
419 }
420 
421 ModuleSP
422 ModuleList::FindFirstModuleForPlatormFileSpec (const FileSpec &file_spec,
423                                                const ArchSpec *arch_ptr,
424                                                const ConstString *object_name)
425 {
426     ModuleSP module_sp;
427     ModuleMatches matcher (&file_spec,
428                            arch_ptr,
429                            NULL,
430                            object_name,
431                            true);
432 
433     // Scope for "locker"
434     {
435         Mutex::Locker locker(m_modules_mutex);
436         collection::const_iterator end = m_modules.end();
437         collection::const_iterator pos = m_modules.begin();
438 
439         pos = std::find_if (pos, end, matcher);
440         if (pos != end)
441             module_sp = (*pos);
442     }
443     return module_sp;
444 
445 }
446 
447 
448 size_t
449 ModuleList::GetSize() const
450 {
451     size_t size = 0;
452     {
453         Mutex::Locker locker(m_modules_mutex);
454         size = m_modules.size();
455     }
456     return size;
457 }
458 
459 
460 void
461 ModuleList::Dump(Stream *s) const
462 {
463 //  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
464 //  s.Indent();
465 //  s << "ModuleList\n";
466 
467     Mutex::Locker locker(m_modules_mutex);
468     collection::const_iterator pos, end = m_modules.end();
469     for (pos = m_modules.begin(); pos != end; ++pos)
470     {
471         (*pos)->Dump(s);
472     }
473 }
474 
475 void
476 ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr)
477 {
478     if (log_sp)
479     {
480         Mutex::Locker locker(m_modules_mutex);
481         char uuid_cstr[256];
482         collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
483         for (pos = begin; pos != end; ++pos)
484         {
485             Module *module = pos->get();
486             module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr));
487             const FileSpec &module_file_spec = module->GetFileSpec();
488             log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"",
489                             prefix_cstr ? prefix_cstr : "",
490                             (uint32_t)std::distance (begin, pos),
491                             uuid_cstr,
492                             module->GetArchitecture().GetArchitectureName(),
493                             module_file_spec.GetDirectory().GetCString(),
494                             module_file_spec.GetFilename().GetCString());
495         }
496     }
497 }
498 
499 bool
500 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
501 {
502     Mutex::Locker locker(m_modules_mutex);
503     collection::const_iterator pos, end = m_modules.end();
504     for (pos = m_modules.begin(); pos != end; ++pos)
505     {
506         if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
507             return true;
508     }
509 
510     return false;
511 }
512 
513 uint32_t
514 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
515 {
516     // The address is already section offset so it has a module
517     uint32_t resolved_flags = 0;
518     Module *module = so_addr.GetModule();
519     if (module)
520     {
521         resolved_flags = module->ResolveSymbolContextForAddress (so_addr,
522                                                                  resolve_scope,
523                                                                  sc);
524     }
525     else
526     {
527         Mutex::Locker locker(m_modules_mutex);
528         collection::const_iterator pos, end = m_modules.end();
529         for (pos = m_modules.begin(); pos != end; ++pos)
530         {
531             resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
532                                                                      resolve_scope,
533                                                                      sc);
534             if (resolved_flags != 0)
535                 break;
536         }
537     }
538 
539     return resolved_flags;
540 }
541 
542 uint32_t
543 ModuleList::ResolveSymbolContextForFilePath
544 (
545     const char *file_path,
546     uint32_t line,
547     bool check_inlines,
548     uint32_t resolve_scope,
549     SymbolContextList& sc_list
550 )
551 {
552     FileSpec file_spec(file_path, false);
553     return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
554 }
555 
556 uint32_t
557 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
558 {
559     Mutex::Locker locker(m_modules_mutex);
560     collection::const_iterator pos, end = m_modules.end();
561     for (pos = m_modules.begin(); pos != end; ++pos)
562     {
563         (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
564     }
565 
566     return sc_list.GetSize();
567 }
568 
569 uint32_t
570 ModuleList::GetIndexForModule (const Module *module) const
571 {
572     if (module)
573     {
574         Mutex::Locker locker(m_modules_mutex);
575         collection::const_iterator pos;
576         collection::const_iterator begin = m_modules.begin();
577         collection::const_iterator end = m_modules.end();
578         for (pos = begin; pos != end; ++pos)
579         {
580             if ((*pos).get() == module)
581                 return std::distance (begin, pos);
582         }
583     }
584     return LLDB_INVALID_INDEX32;
585 }
586 
587 static ModuleList &
588 GetSharedModuleList ()
589 {
590     static ModuleList g_shared_module_list;
591     return g_shared_module_list;
592 }
593 
594 const lldb::ModuleSP
595 ModuleList::GetModuleSP (const Module *module_ptr)
596 {
597     lldb::ModuleSP module_sp;
598     if (module_ptr)
599     {
600         ModuleList &shared_module_list = GetSharedModuleList ();
601         module_sp = shared_module_list.FindModule (module_ptr);
602         if (module_sp.get() == NULL)
603         {
604             char uuid_cstr[256];
605             const_cast<Module *>(module_ptr)->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr));
606             const FileSpec &module_file_spec = module_ptr->GetFileSpec();
607             fprintf (stderr, "warning: module not in shared module list: %s (%s) \"%s/%s\"\n",
608                      uuid_cstr,
609                      module_ptr->GetArchitecture().GetArchitectureName(),
610                      module_file_spec.GetDirectory().GetCString(),
611                      module_file_spec.GetFilename().GetCString());
612         }
613     }
614     return module_sp;
615 }
616 
617 size_t
618 ModuleList::FindSharedModules
619 (
620     const FileSpec& in_file_spec,
621     const ArchSpec& arch,
622     const lldb_private::UUID *uuid_ptr,
623     const ConstString *object_name_ptr,
624     ModuleList &matching_module_list
625 )
626 {
627     ModuleList &shared_module_list = GetSharedModuleList ();
628     return shared_module_list.FindModules (&in_file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list);
629 }
630 
631 Error
632 ModuleList::GetSharedModule
633 (
634     const FileSpec& in_file_spec,
635     const ArchSpec& arch,
636     const lldb_private::UUID *uuid_ptr,
637     const ConstString *object_name_ptr,
638     off_t object_offset,
639     ModuleSP &module_sp,
640     ModuleSP *old_module_sp_ptr,
641     bool *did_create_ptr,
642     bool always_create
643 )
644 {
645     ModuleList &shared_module_list = GetSharedModuleList ();
646     Mutex::Locker locker(shared_module_list.m_modules_mutex);
647     char path[PATH_MAX];
648     char uuid_cstr[64];
649 
650     Error error;
651 
652     module_sp.reset();
653 
654     if (did_create_ptr)
655         *did_create_ptr = false;
656     if (old_module_sp_ptr)
657         old_module_sp_ptr->reset();
658 
659 
660     // First just try and get the file where it purports to be (path in
661     // in_file_spec), then check and uuid.
662 
663     if (in_file_spec)
664     {
665         // Make sure no one else can try and get or create a module while this
666         // function is actively working on it by doing an extra lock on the
667         // global mutex list.
668         if (always_create == false)
669         {
670             ModuleList matching_module_list;
671             const size_t num_matching_modules = shared_module_list.FindModules (&in_file_spec, &arch, NULL, object_name_ptr, matching_module_list);
672             if (num_matching_modules > 0)
673             {
674                 for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
675                 {
676                     module_sp = matching_module_list.GetModuleAtIndex(module_idx);
677                     if (uuid_ptr && uuid_ptr->IsValid())
678                     {
679                         // We found the module we were looking for.
680                         if (module_sp->GetUUID() == *uuid_ptr)
681                             return error;
682                     }
683                     else
684                     {
685                         // If we didn't have a UUID in mind when looking for the object file,
686                         // then we should make sure the modification time hasn't changed!
687                         TimeValue file_spec_mod_time(in_file_spec.GetModificationTime());
688                         if (file_spec_mod_time.IsValid())
689                         {
690                             if (file_spec_mod_time == module_sp->GetModificationTime())
691                                 return error;
692                         }
693                     }
694                     if (old_module_sp_ptr && !old_module_sp_ptr->get())
695                         *old_module_sp_ptr = module_sp;
696                     shared_module_list.Remove (module_sp);
697                     module_sp.reset();
698                 }
699             }
700         }
701 
702         if (module_sp)
703             return error;
704         else
705         {
706             module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset));
707             if (module_sp)
708             {
709                 // If we get in here we got the correct arch, now we just need
710                 // to verify the UUID if one was given
711                 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
712                     module_sp.reset();
713                 else
714                 {
715                     if (did_create_ptr)
716                         *did_create_ptr = true;
717 
718                     shared_module_list.Append(module_sp);
719                     return error;
720                 }
721             }
722         }
723     }
724 
725     // Either the file didn't exist where at the path, or no path was given, so
726     // we now have to use more extreme measures to try and find the appropriate
727     // module.
728 
729     // Fixup the incoming path in case the path points to a valid file, yet
730     // the arch or UUID (if one was passed in) don't match.
731     FileSpec file_spec = Symbols::LocateExecutableObjectFile (&in_file_spec, arch.IsValid() ? &arch : NULL, uuid_ptr);
732 
733     // Don't look for the file if it appears to be the same one we already
734     // checked for above...
735     if (file_spec != in_file_spec)
736     {
737         if (!file_spec.Exists())
738         {
739             file_spec.GetPath(path, sizeof(path));
740             if (file_spec.Exists())
741             {
742                 if (uuid_ptr && uuid_ptr->IsValid())
743                     uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
744                 else
745                     uuid_cstr[0] = '\0';
746 
747 
748                 if (arch.IsValid())
749                 {
750                     if (uuid_cstr[0])
751                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s.\n", path, arch.GetArchitectureName(), uuid_cstr[0]);
752                     else
753                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.\n", path, arch.GetArchitectureName());
754                 }
755             }
756             else
757             {
758                 error.SetErrorStringWithFormat("'%s' does not exist.\n", path);
759             }
760             return error;
761         }
762 
763 
764         // Make sure no one else can try and get or create a module while this
765         // function is actively working on it by doing an extra lock on the
766         // global mutex list.
767         ModuleList matching_module_list;
768         if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0)
769         {
770             module_sp = matching_module_list.GetModuleAtIndex(0);
771 
772             // If we didn't have a UUID in mind when looking for the object file,
773             // then we should make sure the modification time hasn't changed!
774             if (uuid_ptr == NULL)
775             {
776                 TimeValue file_spec_mod_time(file_spec.GetModificationTime());
777                 if (file_spec_mod_time.IsValid())
778                 {
779                     if (file_spec_mod_time != module_sp->GetModificationTime())
780                     {
781                         if (old_module_sp_ptr)
782                             *old_module_sp_ptr = module_sp;
783                         shared_module_list.Remove (module_sp);
784                         module_sp.reset();
785                     }
786                 }
787             }
788         }
789 
790         if (module_sp.get() == NULL)
791         {
792             module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset));
793             if (module_sp)
794             {
795                 if (did_create_ptr)
796                     *did_create_ptr = true;
797 
798                 shared_module_list.Append(module_sp);
799             }
800             else
801             {
802                 file_spec.GetPath(path, sizeof(path));
803 
804                 if (file_spec)
805                 {
806                     if (arch.IsValid())
807                         error.SetErrorStringWithFormat("Unable to open %s architecture in '%s'.\n", arch.GetArchitectureName(), path);
808                     else
809                         error.SetErrorStringWithFormat("Unable to open '%s'.\n", path);
810                 }
811                 else
812                 {
813                     if (uuid_ptr && uuid_ptr->IsValid())
814                         uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
815                     else
816                         uuid_cstr[0] = '\0';
817 
818                     if (uuid_cstr[0])
819                         error.SetErrorStringWithFormat("Cannot locate a module for UUID '%s'.\n", uuid_cstr[0]);
820                     else
821                         error.SetErrorStringWithFormat("Cannot locate a module.\n", path, arch.GetArchitectureName());
822                 }
823             }
824         }
825     }
826 
827     return error;
828 }
829 
830 bool
831 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
832 {
833     return GetSharedModuleList ().Remove (module_sp);
834 }
835 
836 
837