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