Home | History | Annotate | Download | only in Core
      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/Core/ModuleSpec.h"
     19 #include "lldb/Host/Host.h"
     20 #include "lldb/Host/Symbols.h"
     21 #include "lldb/Symbol/ClangNamespaceDecl.h"
     22 #include "lldb/Symbol/ObjectFile.h"
     23 #include "lldb/Symbol/VariableList.h"
     24 
     25 using namespace lldb;
     26 using namespace lldb_private;
     27 
     28 //----------------------------------------------------------------------
     29 // ModuleList constructor
     30 //----------------------------------------------------------------------
     31 ModuleList::ModuleList() :
     32     m_modules(),
     33     m_modules_mutex (Mutex::eMutexTypeRecursive),
     34     m_notifier(NULL)
     35 {
     36 }
     37 
     38 //----------------------------------------------------------------------
     39 // Copy constructor
     40 //----------------------------------------------------------------------
     41 ModuleList::ModuleList(const ModuleList& rhs) :
     42     m_modules(),
     43     m_modules_mutex (Mutex::eMutexTypeRecursive)
     44 {
     45     Mutex::Locker lhs_locker(m_modules_mutex);
     46     Mutex::Locker rhs_locker(rhs.m_modules_mutex);
     47     m_modules = rhs.m_modules;
     48 }
     49 
     50 ModuleList::ModuleList (ModuleList::Notifier* notifier) :
     51     m_modules(),
     52     m_modules_mutex (Mutex::eMutexTypeRecursive),
     53     m_notifier(notifier)
     54 {
     55 }
     56 
     57 //----------------------------------------------------------------------
     58 // Assignment operator
     59 //----------------------------------------------------------------------
     60 const ModuleList&
     61 ModuleList::operator= (const ModuleList& rhs)
     62 {
     63     if (this != &rhs)
     64     {
     65         Mutex::Locker lhs_locker(m_modules_mutex);
     66         Mutex::Locker rhs_locker(rhs.m_modules_mutex);
     67         m_modules = rhs.m_modules;
     68     }
     69     return *this;
     70 }
     71 
     72 //----------------------------------------------------------------------
     73 // Destructor
     74 //----------------------------------------------------------------------
     75 ModuleList::~ModuleList()
     76 {
     77 }
     78 
     79 void
     80 ModuleList::AppendImpl (const ModuleSP &module_sp, bool use_notifier)
     81 {
     82     if (module_sp)
     83     {
     84         Mutex::Locker locker(m_modules_mutex);
     85         m_modules.push_back(module_sp);
     86         if (use_notifier && m_notifier)
     87             m_notifier->ModuleAdded(*this, module_sp);
     88     }
     89 }
     90 
     91 void
     92 ModuleList::Append (const ModuleSP &module_sp)
     93 {
     94     AppendImpl (module_sp);
     95 }
     96 
     97 void
     98 ModuleList::ReplaceEquivalent (const ModuleSP &module_sp)
     99 {
    100     if (module_sp)
    101     {
    102         Mutex::Locker locker(m_modules_mutex);
    103 
    104         // First remove any equivalent modules. Equivalent modules are modules
    105         // whose path, platform path and architecture match.
    106         ModuleSpec equivalent_module_spec (module_sp->GetFileSpec(), module_sp->GetArchitecture());
    107         equivalent_module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
    108 
    109         size_t idx = 0;
    110         while (idx < m_modules.size())
    111         {
    112             ModuleSP module_sp (m_modules[idx]);
    113             if (module_sp->MatchesModuleSpec (equivalent_module_spec))
    114                 RemoveImpl(m_modules.begin() + idx);
    115             else
    116                 ++idx;
    117         }
    118         // Now add the new module to the list
    119         Append(module_sp);
    120     }
    121 }
    122 
    123 bool
    124 ModuleList::AppendIfNeeded (const ModuleSP &module_sp)
    125 {
    126     if (module_sp)
    127     {
    128         Mutex::Locker locker(m_modules_mutex);
    129         collection::iterator pos, end = m_modules.end();
    130         for (pos = m_modules.begin(); pos != end; ++pos)
    131         {
    132             if (pos->get() == module_sp.get())
    133                 return false; // Already in the list
    134         }
    135         // Only push module_sp on the list if it wasn't already in there.
    136         Append(module_sp);
    137         return true;
    138     }
    139     return false;
    140 }
    141 
    142 void
    143 ModuleList::Append (const ModuleList& module_list)
    144 {
    145     for (auto pos : module_list.m_modules)
    146         Append(pos);
    147 }
    148 
    149 bool
    150 ModuleList::AppendIfNeeded (const ModuleList& module_list)
    151 {
    152     bool any_in = false;
    153     for (auto pos : module_list.m_modules)
    154         any_in = AppendIfNeeded(pos) | any_in;
    155     return any_in;
    156 }
    157 
    158 bool
    159 ModuleList::RemoveImpl (const ModuleSP &module_sp, bool use_notifier)
    160 {
    161     if (module_sp)
    162     {
    163         Mutex::Locker locker(m_modules_mutex);
    164         collection::iterator pos, end = m_modules.end();
    165         for (pos = m_modules.begin(); pos != end; ++pos)
    166         {
    167             if (pos->get() == module_sp.get())
    168             {
    169                 m_modules.erase (pos);
    170                 if (use_notifier && m_notifier)
    171                     m_notifier->ModuleRemoved(*this, module_sp);
    172                 return true;
    173             }
    174         }
    175     }
    176     return false;
    177 }
    178 
    179 ModuleList::collection::iterator
    180 ModuleList::RemoveImpl (ModuleList::collection::iterator pos, bool use_notifier)
    181 {
    182     ModuleSP module_sp(*pos);
    183     collection::iterator retval = m_modules.erase(pos);
    184     if (use_notifier && m_notifier)
    185         m_notifier->ModuleRemoved(*this, module_sp);
    186     return retval;
    187 }
    188 
    189 bool
    190 ModuleList::Remove (const ModuleSP &module_sp)
    191 {
    192     return RemoveImpl (module_sp);
    193 }
    194 
    195 bool
    196 ModuleList::ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)
    197 {
    198     if (!RemoveImpl(old_module_sp, false))
    199         return false;
    200     AppendImpl (new_module_sp, false);
    201     if (m_notifier)
    202         m_notifier->ModuleUpdated(*this, old_module_sp,new_module_sp);
    203     return true;
    204 }
    205 
    206 bool
    207 ModuleList::RemoveIfOrphaned (const Module *module_ptr)
    208 {
    209     if (module_ptr)
    210     {
    211         Mutex::Locker locker(m_modules_mutex);
    212         collection::iterator pos, end = m_modules.end();
    213         for (pos = m_modules.begin(); pos != end; ++pos)
    214         {
    215             if (pos->get() == module_ptr)
    216             {
    217                 if (pos->unique())
    218                 {
    219                     pos = RemoveImpl(pos);
    220                     return true;
    221                 }
    222                 else
    223                     return false;
    224             }
    225         }
    226     }
    227     return false;
    228 }
    229 
    230 size_t
    231 ModuleList::RemoveOrphans (bool mandatory)
    232 {
    233     Mutex::Locker locker;
    234 
    235     if (mandatory)
    236     {
    237         locker.Lock (m_modules_mutex);
    238     }
    239     else
    240     {
    241         // Not mandatory, remove orphans if we can get the mutex
    242         if (!locker.TryLock(m_modules_mutex))
    243             return 0;
    244     }
    245     collection::iterator pos = m_modules.begin();
    246     size_t remove_count = 0;
    247     while (pos != m_modules.end())
    248     {
    249         if (pos->unique())
    250         {
    251             pos = RemoveImpl(pos);
    252             ++remove_count;
    253         }
    254         else
    255         {
    256             ++pos;
    257         }
    258     }
    259     return remove_count;
    260 }
    261 
    262 size_t
    263 ModuleList::Remove (ModuleList &module_list)
    264 {
    265     Mutex::Locker locker(m_modules_mutex);
    266     size_t num_removed = 0;
    267     collection::iterator pos, end = module_list.m_modules.end();
    268     for (pos = module_list.m_modules.begin(); pos != end; ++pos)
    269     {
    270         if (Remove (*pos))
    271             ++num_removed;
    272     }
    273     return num_removed;
    274 }
    275 
    276 
    277 void
    278 ModuleList::Clear()
    279 {
    280     ClearImpl();
    281 }
    282 
    283 void
    284 ModuleList::Destroy()
    285 {
    286     ClearImpl();
    287 }
    288 
    289 void
    290 ModuleList::ClearImpl (bool use_notifier)
    291 {
    292     Mutex::Locker locker(m_modules_mutex);
    293     if (use_notifier && m_notifier)
    294         m_notifier->WillClearList(*this);
    295     m_modules.clear();
    296 }
    297 
    298 Module*
    299 ModuleList::GetModulePointerAtIndex (size_t idx) const
    300 {
    301     Mutex::Locker locker(m_modules_mutex);
    302     return GetModulePointerAtIndexUnlocked(idx);
    303 }
    304 
    305 Module*
    306 ModuleList::GetModulePointerAtIndexUnlocked (size_t idx) const
    307 {
    308     if (idx < m_modules.size())
    309         return m_modules[idx].get();
    310     return NULL;
    311 }
    312 
    313 ModuleSP
    314 ModuleList::GetModuleAtIndex(size_t idx) const
    315 {
    316     Mutex::Locker locker(m_modules_mutex);
    317     return GetModuleAtIndexUnlocked(idx);
    318 }
    319 
    320 ModuleSP
    321 ModuleList::GetModuleAtIndexUnlocked(size_t idx) const
    322 {
    323     ModuleSP module_sp;
    324     if (idx < m_modules.size())
    325         module_sp = m_modules[idx];
    326     return module_sp;
    327 }
    328 
    329 size_t
    330 ModuleList::FindFunctions (const ConstString &name,
    331                            uint32_t name_type_mask,
    332                            bool include_symbols,
    333                            bool include_inlines,
    334                            bool append,
    335                            SymbolContextList &sc_list) const
    336 {
    337     if (!append)
    338         sc_list.Clear();
    339 
    340     const size_t old_size = sc_list.GetSize();
    341 
    342     if (name_type_mask & eFunctionNameTypeAuto)
    343     {
    344         ConstString lookup_name;
    345         uint32_t lookup_name_type_mask = 0;
    346         bool match_name_after_lookup = false;
    347         Module::PrepareForFunctionNameLookup (name, name_type_mask,
    348                                               lookup_name,
    349                                               lookup_name_type_mask,
    350                                               match_name_after_lookup);
    351 
    352         Mutex::Locker locker(m_modules_mutex);
    353         collection::const_iterator pos, end = m_modules.end();
    354         for (pos = m_modules.begin(); pos != end; ++pos)
    355         {
    356             (*pos)->FindFunctions (lookup_name,
    357                                    NULL,
    358                                    lookup_name_type_mask,
    359                                    include_symbols,
    360                                    include_inlines,
    361                                    true,
    362                                    sc_list);
    363         }
    364 
    365         if (match_name_after_lookup)
    366         {
    367             SymbolContext sc;
    368             size_t i = old_size;
    369             while (i<sc_list.GetSize())
    370             {
    371                 if (sc_list.GetContextAtIndex(i, sc))
    372                 {
    373                     const char *func_name = sc.GetFunctionName().GetCString();
    374                     if (func_name && strstr (func_name, name.GetCString()) == NULL)
    375                     {
    376                         // Remove the current context
    377                         sc_list.RemoveContextAtIndex(i);
    378                         // Don't increment i and continue in the loop
    379                         continue;
    380                     }
    381                 }
    382                 ++i;
    383             }
    384         }
    385 
    386     }
    387     else
    388     {
    389         Mutex::Locker locker(m_modules_mutex);
    390         collection::const_iterator pos, end = m_modules.end();
    391         for (pos = m_modules.begin(); pos != end; ++pos)
    392         {
    393             (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
    394         }
    395     }
    396     return sc_list.GetSize() - old_size;
    397 }
    398 
    399 size_t
    400 ModuleList::FindFunctionSymbols (const ConstString &name,
    401                                  uint32_t name_type_mask,
    402                                  SymbolContextList& sc_list)
    403 {
    404     const size_t old_size = sc_list.GetSize();
    405 
    406     if (name_type_mask & eFunctionNameTypeAuto)
    407     {
    408         ConstString lookup_name;
    409         uint32_t lookup_name_type_mask = 0;
    410         bool match_name_after_lookup = false;
    411         Module::PrepareForFunctionNameLookup (name, name_type_mask,
    412                                               lookup_name,
    413                                               lookup_name_type_mask,
    414                                               match_name_after_lookup);
    415 
    416         Mutex::Locker locker(m_modules_mutex);
    417         collection::const_iterator pos, end = m_modules.end();
    418         for (pos = m_modules.begin(); pos != end; ++pos)
    419         {
    420             (*pos)->FindFunctionSymbols (lookup_name,
    421                                    lookup_name_type_mask,
    422                                    sc_list);
    423         }
    424 
    425         if (match_name_after_lookup)
    426         {
    427             SymbolContext sc;
    428             size_t i = old_size;
    429             while (i<sc_list.GetSize())
    430             {
    431                 if (sc_list.GetContextAtIndex(i, sc))
    432                 {
    433                     const char *func_name = sc.GetFunctionName().GetCString();
    434                     if (func_name && strstr (func_name, name.GetCString()) == NULL)
    435                     {
    436                         // Remove the current context
    437                         sc_list.RemoveContextAtIndex(i);
    438                         // Don't increment i and continue in the loop
    439                         continue;
    440                     }
    441                 }
    442                 ++i;
    443             }
    444         }
    445 
    446     }
    447     else
    448     {
    449         Mutex::Locker locker(m_modules_mutex);
    450         collection::const_iterator pos, end = m_modules.end();
    451         for (pos = m_modules.begin(); pos != end; ++pos)
    452         {
    453             (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list);
    454         }
    455     }
    456 
    457     return sc_list.GetSize() - old_size;
    458 }
    459 
    460 size_t
    461 ModuleList::FindCompileUnits (const FileSpec &path,
    462                               bool append,
    463                               SymbolContextList &sc_list) const
    464 {
    465     if (!append)
    466         sc_list.Clear();
    467 
    468     Mutex::Locker locker(m_modules_mutex);
    469     collection::const_iterator pos, end = m_modules.end();
    470     for (pos = m_modules.begin(); pos != end; ++pos)
    471     {
    472         (*pos)->FindCompileUnits (path, true, sc_list);
    473     }
    474 
    475     return sc_list.GetSize();
    476 }
    477 
    478 size_t
    479 ModuleList::FindGlobalVariables (const ConstString &name,
    480                                  bool append,
    481                                  size_t max_matches,
    482                                  VariableList& variable_list) const
    483 {
    484     size_t initial_size = variable_list.GetSize();
    485     Mutex::Locker locker(m_modules_mutex);
    486     collection::const_iterator pos, end = m_modules.end();
    487     for (pos = m_modules.begin(); pos != end; ++pos)
    488     {
    489         (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list);
    490     }
    491     return variable_list.GetSize() - initial_size;
    492 }
    493 
    494 
    495 size_t
    496 ModuleList::FindGlobalVariables (const RegularExpression& regex,
    497                                  bool append,
    498                                  size_t max_matches,
    499                                  VariableList& variable_list) const
    500 {
    501     size_t initial_size = variable_list.GetSize();
    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         (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
    507     }
    508     return variable_list.GetSize() - initial_size;
    509 }
    510 
    511 
    512 size_t
    513 ModuleList::FindSymbolsWithNameAndType (const ConstString &name,
    514                                         SymbolType symbol_type,
    515                                         SymbolContextList &sc_list,
    516                                         bool append) const
    517 {
    518     Mutex::Locker locker(m_modules_mutex);
    519     if (!append)
    520         sc_list.Clear();
    521     size_t initial_size = sc_list.GetSize();
    522 
    523     collection::const_iterator pos, end = m_modules.end();
    524     for (pos = m_modules.begin(); pos != end; ++pos)
    525         (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
    526     return sc_list.GetSize() - initial_size;
    527 }
    528 
    529 size_t
    530 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex,
    531                                              lldb::SymbolType symbol_type,
    532                                              SymbolContextList &sc_list,
    533                                              bool append) const
    534 {
    535     Mutex::Locker locker(m_modules_mutex);
    536     if (!append)
    537         sc_list.Clear();
    538     size_t initial_size = sc_list.GetSize();
    539 
    540     collection::const_iterator pos, end = m_modules.end();
    541     for (pos = m_modules.begin(); pos != end; ++pos)
    542         (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
    543     return sc_list.GetSize() - initial_size;
    544 }
    545 
    546 size_t
    547 ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const
    548 {
    549     size_t existing_matches = matching_module_list.GetSize();
    550 
    551     Mutex::Locker locker(m_modules_mutex);
    552     collection::const_iterator pos, end = m_modules.end();
    553     for (pos = m_modules.begin(); pos != end; ++pos)
    554     {
    555         ModuleSP module_sp(*pos);
    556         if (module_sp->MatchesModuleSpec (module_spec))
    557             matching_module_list.Append(module_sp);
    558     }
    559     return matching_module_list.GetSize() - existing_matches;
    560 }
    561 
    562 ModuleSP
    563 ModuleList::FindModule (const Module *module_ptr) const
    564 {
    565     ModuleSP module_sp;
    566 
    567     // Scope for "locker"
    568     {
    569         Mutex::Locker locker(m_modules_mutex);
    570         collection::const_iterator pos, end = m_modules.end();
    571 
    572         for (pos = m_modules.begin(); pos != end; ++pos)
    573         {
    574             if ((*pos).get() == module_ptr)
    575             {
    576                 module_sp = (*pos);
    577                 break;
    578             }
    579         }
    580     }
    581     return module_sp;
    582 
    583 }
    584 
    585 ModuleSP
    586 ModuleList::FindModule (const UUID &uuid) const
    587 {
    588     ModuleSP module_sp;
    589 
    590     if (uuid.IsValid())
    591     {
    592         Mutex::Locker locker(m_modules_mutex);
    593         collection::const_iterator pos, end = m_modules.end();
    594 
    595         for (pos = m_modules.begin(); pos != end; ++pos)
    596         {
    597             if ((*pos)->GetUUID() == uuid)
    598             {
    599                 module_sp = (*pos);
    600                 break;
    601             }
    602         }
    603     }
    604     return module_sp;
    605 }
    606 
    607 
    608 size_t
    609 ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, size_t max_matches, TypeList& types) const
    610 {
    611     Mutex::Locker locker(m_modules_mutex);
    612 
    613     size_t total_matches = 0;
    614     collection::const_iterator pos, end = m_modules.end();
    615     if (sc.module_sp)
    616     {
    617         // The symbol context "sc" contains a module so we want to search that
    618         // one first if it is in our list...
    619         for (pos = m_modules.begin(); pos != end; ++pos)
    620         {
    621             if (sc.module_sp.get() == (*pos).get())
    622             {
    623                 total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, types);
    624 
    625                 if (total_matches >= max_matches)
    626                     break;
    627             }
    628         }
    629     }
    630 
    631     if (total_matches < max_matches)
    632     {
    633         SymbolContext world_sc;
    634         for (pos = m_modules.begin(); pos != end; ++pos)
    635         {
    636             // Search the module if the module is not equal to the one in the symbol
    637             // context "sc". If "sc" contains a empty module shared pointer, then
    638             // the comparisong will always be true (valid_module_ptr != NULL).
    639             if (sc.module_sp.get() != (*pos).get())
    640                 total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, types);
    641 
    642             if (total_matches >= max_matches)
    643                 break;
    644         }
    645     }
    646 
    647     return total_matches;
    648 }
    649 
    650 bool
    651 ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const
    652 {
    653     Mutex::Locker locker(m_modules_mutex);
    654     collection::const_iterator pos, end = m_modules.end();
    655     for (pos = m_modules.begin(); pos != end; ++pos)
    656     {
    657         if ((*pos)->FindSourceFile (orig_spec, new_spec))
    658             return true;
    659     }
    660     return false;
    661 }
    662 
    663 
    664 
    665 ModuleSP
    666 ModuleList::FindFirstModule (const ModuleSpec &module_spec) const
    667 {
    668     ModuleSP module_sp;
    669     Mutex::Locker locker(m_modules_mutex);
    670     collection::const_iterator pos, end = m_modules.end();
    671     for (pos = m_modules.begin(); pos != end; ++pos)
    672     {
    673         ModuleSP module_sp(*pos);
    674         if (module_sp->MatchesModuleSpec (module_spec))
    675             return module_sp;
    676     }
    677     return module_sp;
    678 
    679 }
    680 
    681 size_t
    682 ModuleList::GetSize() const
    683 {
    684     size_t size = 0;
    685     {
    686         Mutex::Locker locker(m_modules_mutex);
    687         size = m_modules.size();
    688     }
    689     return size;
    690 }
    691 
    692 
    693 void
    694 ModuleList::Dump(Stream *s) const
    695 {
    696 //  s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
    697 //  s.Indent();
    698 //  s << "ModuleList\n";
    699 
    700     Mutex::Locker locker(m_modules_mutex);
    701     collection::const_iterator pos, end = m_modules.end();
    702     for (pos = m_modules.begin(); pos != end; ++pos)
    703     {
    704         (*pos)->Dump(s);
    705     }
    706 }
    707 
    708 void
    709 ModuleList::LogUUIDAndPaths (Log *log, const char *prefix_cstr)
    710 {
    711     if (log)
    712     {
    713         Mutex::Locker locker(m_modules_mutex);
    714         collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end();
    715         for (pos = begin; pos != end; ++pos)
    716         {
    717             Module *module = pos->get();
    718             const FileSpec &module_file_spec = module->GetFileSpec();
    719             log->Printf ("%s[%u] %s (%s) \"%s\"",
    720                          prefix_cstr ? prefix_cstr : "",
    721                          (uint32_t)std::distance (begin, pos),
    722                          module->GetUUID().GetAsString().c_str(),
    723                          module->GetArchitecture().GetArchitectureName(),
    724                          module_file_spec.GetPath().c_str());
    725         }
    726     }
    727 }
    728 
    729 bool
    730 ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) const
    731 {
    732     Mutex::Locker locker(m_modules_mutex);
    733     collection::const_iterator pos, end = m_modules.end();
    734     for (pos = m_modules.begin(); pos != end; ++pos)
    735     {
    736         if ((*pos)->ResolveFileAddress (vm_addr, so_addr))
    737             return true;
    738     }
    739 
    740     return false;
    741 }
    742 
    743 uint32_t
    744 ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) const
    745 {
    746     // The address is already section offset so it has a module
    747     uint32_t resolved_flags = 0;
    748     ModuleSP module_sp (so_addr.GetModule());
    749     if (module_sp)
    750     {
    751         resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr,
    752                                                                     resolve_scope,
    753                                                                     sc);
    754     }
    755     else
    756     {
    757         Mutex::Locker locker(m_modules_mutex);
    758         collection::const_iterator pos, end = m_modules.end();
    759         for (pos = m_modules.begin(); pos != end; ++pos)
    760         {
    761             resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr,
    762                                                                      resolve_scope,
    763                                                                      sc);
    764             if (resolved_flags != 0)
    765                 break;
    766         }
    767     }
    768 
    769     return resolved_flags;
    770 }
    771 
    772 uint32_t
    773 ModuleList::ResolveSymbolContextForFilePath
    774 (
    775     const char *file_path,
    776     uint32_t line,
    777     bool check_inlines,
    778     uint32_t resolve_scope,
    779     SymbolContextList& sc_list
    780 )  const
    781 {
    782     FileSpec file_spec(file_path, false);
    783     return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
    784 }
    785 
    786 uint32_t
    787 ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const
    788 {
    789     Mutex::Locker locker(m_modules_mutex);
    790     collection::const_iterator pos, end = m_modules.end();
    791     for (pos = m_modules.begin(); pos != end; ++pos)
    792     {
    793         (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
    794     }
    795 
    796     return sc_list.GetSize();
    797 }
    798 
    799 size_t
    800 ModuleList::GetIndexForModule (const Module *module) const
    801 {
    802     if (module)
    803     {
    804         Mutex::Locker locker(m_modules_mutex);
    805         collection::const_iterator pos;
    806         collection::const_iterator begin = m_modules.begin();
    807         collection::const_iterator end = m_modules.end();
    808         for (pos = begin; pos != end; ++pos)
    809         {
    810             if ((*pos).get() == module)
    811                 return std::distance (begin, pos);
    812         }
    813     }
    814     return LLDB_INVALID_INDEX32;
    815 }
    816 
    817 static ModuleList &
    818 GetSharedModuleList ()
    819 {
    820     // NOTE: Intentionally leak the module list so a program doesn't have to
    821     // cleanup all modules and object files as it exits. This just wastes time
    822     // doing a bunch of cleanup that isn't required.
    823     static ModuleList *g_shared_module_list = NULL;
    824     if (g_shared_module_list == NULL)
    825         g_shared_module_list = new ModuleList(); // <--- Intentional leak!!!
    826 
    827     return *g_shared_module_list;
    828 }
    829 
    830 bool
    831 ModuleList::ModuleIsInCache (const Module *module_ptr)
    832 {
    833     if (module_ptr)
    834     {
    835         ModuleList &shared_module_list = GetSharedModuleList ();
    836         return shared_module_list.FindModule (module_ptr).get() != NULL;
    837     }
    838     return false;
    839 }
    840 
    841 size_t
    842 ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list)
    843 {
    844     return GetSharedModuleList ().FindModules (module_spec, matching_module_list);
    845 }
    846 
    847 size_t
    848 ModuleList::RemoveOrphanSharedModules (bool mandatory)
    849 {
    850     return GetSharedModuleList ().RemoveOrphans(mandatory);
    851 }
    852 
    853 Error
    854 ModuleList::GetSharedModule
    855 (
    856     const ModuleSpec &module_spec,
    857     ModuleSP &module_sp,
    858     const FileSpecList *module_search_paths_ptr,
    859     ModuleSP *old_module_sp_ptr,
    860     bool *did_create_ptr,
    861     bool always_create
    862 )
    863 {
    864     ModuleList &shared_module_list = GetSharedModuleList ();
    865     Mutex::Locker locker(shared_module_list.m_modules_mutex);
    866     char path[PATH_MAX];
    867 
    868     Error error;
    869 
    870     module_sp.reset();
    871 
    872     if (did_create_ptr)
    873         *did_create_ptr = false;
    874     if (old_module_sp_ptr)
    875         old_module_sp_ptr->reset();
    876 
    877     const UUID *uuid_ptr = module_spec.GetUUIDPtr();
    878     const FileSpec &module_file_spec = module_spec.GetFileSpec();
    879     const ArchSpec &arch = module_spec.GetArchitecture();
    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     if (always_create == false)
    885     {
    886         ModuleList matching_module_list;
    887         const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list);
    888         if (num_matching_modules > 0)
    889         {
    890             for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
    891             {
    892                 module_sp = matching_module_list.GetModuleAtIndex(module_idx);
    893 
    894                 // Make sure the file for the module hasn't been modified
    895                 if (module_sp->FileHasChanged())
    896                 {
    897                     if (old_module_sp_ptr && !old_module_sp_ptr->get())
    898                         *old_module_sp_ptr = module_sp;
    899 
    900                     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES));
    901                     if (log)
    902                         log->Printf("module changed: %p, removing from global module list", module_sp.get());
    903 
    904                     shared_module_list.Remove (module_sp);
    905                     module_sp.reset();
    906                 }
    907                 else
    908                 {
    909                     // The module matches and the module was not modified from
    910                     // when it was last loaded.
    911                     return error;
    912                 }
    913             }
    914         }
    915     }
    916 
    917     if (module_sp)
    918         return error;
    919     else
    920     {
    921         module_sp.reset (new Module (module_spec));
    922         // Make sure there are a module and an object file since we can specify
    923         // a valid file path with an architecture that might not be in that file.
    924         // By getting the object file we can guarantee that the architecture matches
    925         if (module_sp)
    926         {
    927             if (module_sp->GetObjectFile())
    928             {
    929                 // If we get in here we got the correct arch, now we just need
    930                 // to verify the UUID if one was given
    931                 if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
    932                     module_sp.reset();
    933                 else
    934                 {
    935                     if (did_create_ptr)
    936                         *did_create_ptr = true;
    937 
    938                     shared_module_list.ReplaceEquivalent(module_sp);
    939                     return error;
    940                 }
    941             }
    942             else
    943                 module_sp.reset();
    944         }
    945     }
    946 
    947     // Either the file didn't exist where at the path, or no path was given, so
    948     // we now have to use more extreme measures to try and find the appropriate
    949     // module.
    950 
    951     // Fixup the incoming path in case the path points to a valid file, yet
    952     // the arch or UUID (if one was passed in) don't match.
    953     FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec);
    954 
    955     // Don't look for the file if it appears to be the same one we already
    956     // checked for above...
    957     if (file_spec != module_file_spec)
    958     {
    959         if (!file_spec.Exists())
    960         {
    961             file_spec.GetPath(path, sizeof(path));
    962             if (path[0] == '\0')
    963                 module_file_spec.GetPath(path, sizeof(path));
    964             if (file_spec.Exists())
    965             {
    966                 std::string uuid_str;
    967                 if (uuid_ptr && uuid_ptr->IsValid())
    968                     uuid_str = uuid_ptr->GetAsString();
    969 
    970                 if (arch.IsValid())
    971                 {
    972                     if (!uuid_str.empty())
    973                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str());
    974                     else
    975                         error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
    976                 }
    977             }
    978             else
    979             {
    980                 error.SetErrorStringWithFormat("'%s' does not exist", path);
    981             }
    982             if (error.Fail())
    983                 module_sp.reset();
    984             return error;
    985         }
    986 
    987 
    988         // Make sure no one else can try and get or create a module while this
    989         // function is actively working on it by doing an extra lock on the
    990         // global mutex list.
    991         ModuleSpec platform_module_spec(module_spec);
    992         platform_module_spec.GetFileSpec() = file_spec;
    993         platform_module_spec.GetPlatformFileSpec() = file_spec;
    994         ModuleList matching_module_list;
    995         if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
    996         {
    997             module_sp = matching_module_list.GetModuleAtIndex(0);
    998 
    999             // If we didn't have a UUID in mind when looking for the object file,
   1000             // then we should make sure the modification time hasn't changed!
   1001             if (platform_module_spec.GetUUIDPtr() == NULL)
   1002             {
   1003                 TimeValue file_spec_mod_time(file_spec.GetModificationTime());
   1004                 if (file_spec_mod_time.IsValid())
   1005                 {
   1006                     if (file_spec_mod_time != module_sp->GetModificationTime())
   1007                     {
   1008                         if (old_module_sp_ptr)
   1009                             *old_module_sp_ptr = module_sp;
   1010                         shared_module_list.Remove (module_sp);
   1011                         module_sp.reset();
   1012                     }
   1013                 }
   1014             }
   1015         }
   1016 
   1017         if (module_sp.get() == NULL)
   1018         {
   1019             module_sp.reset (new Module (platform_module_spec));
   1020             // Make sure there are a module and an object file since we can specify
   1021             // a valid file path with an architecture that might not be in that file.
   1022             // By getting the object file we can guarantee that the architecture matches
   1023             if (module_sp && module_sp->GetObjectFile())
   1024             {
   1025                 if (did_create_ptr)
   1026                     *did_create_ptr = true;
   1027 
   1028                 shared_module_list.ReplaceEquivalent(module_sp);
   1029             }
   1030             else
   1031             {
   1032                 file_spec.GetPath(path, sizeof(path));
   1033 
   1034                 if (file_spec)
   1035                 {
   1036                     if (arch.IsValid())
   1037                         error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
   1038                     else
   1039                         error.SetErrorStringWithFormat("unable to open '%s'", path);
   1040                 }
   1041                 else
   1042                 {
   1043                     std::string uuid_str;
   1044                     if (uuid_ptr && uuid_ptr->IsValid())
   1045                         uuid_str = uuid_ptr->GetAsString();
   1046 
   1047                     if (!uuid_str.empty())
   1048                         error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str());
   1049                     else
   1050                         error.SetErrorStringWithFormat("cannot locate a module");
   1051                 }
   1052             }
   1053         }
   1054     }
   1055 
   1056     return error;
   1057 }
   1058 
   1059 bool
   1060 ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp)
   1061 {
   1062     return GetSharedModuleList ().Remove (module_sp);
   1063 }
   1064 
   1065 bool
   1066 ModuleList::RemoveSharedModuleIfOrphaned (const Module *module_ptr)
   1067 {
   1068     return GetSharedModuleList ().RemoveIfOrphaned (module_ptr);
   1069 }
   1070 
   1071 bool
   1072 ModuleList::LoadScriptingResourcesInTarget (Target *target,
   1073                                             std::list<Error>& errors,
   1074                                             Stream *feedback_stream,
   1075                                             bool continue_on_error)
   1076 {
   1077     if (!target)
   1078         return false;
   1079     Mutex::Locker locker(m_modules_mutex);
   1080     for (auto module : m_modules)
   1081     {
   1082         Error error;
   1083         if (module)
   1084         {
   1085             if (!module->LoadScriptingResourceInTarget(target, error, feedback_stream))
   1086             {
   1087                 if (error.Fail() && error.AsCString())
   1088                 {
   1089                     error.SetErrorStringWithFormat("unable to load scripting data for module %s - error reported was %s",
   1090                                                    module->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
   1091                                                    error.AsCString());
   1092                     errors.push_back(error);
   1093                 }
   1094                 if (!continue_on_error)
   1095                     return false;
   1096             }
   1097         }
   1098     }
   1099     return errors.size() == 0;
   1100 }
   1101