<rdar://problem/12586350>

This commit does three things:
(a) introduces a new notification model for adding/removing/changing modules to a ModuleList, and applies it to the Target's ModuleList, so that we make sure to always trigger the right set of actions
whenever modules come and go in a target. Certain spots in the code still need to "manually" notify the Target for several reasons, so this is a work in progress
(b) adds a new capability to the Platforms: locating a scripting resources associated to a module. A scripting resource is a Python file that can load commands, formatters, ... and any other action
of interest corresponding to the loading of a module. At the moment, this is only implemented on Mac OS X and only for files inside .dSYM bundles - the next step is going to be letting
the frameworks themselves hold their scripting resources. Implementors of platforms for other systems are free to implement "the right thing" for their own worlds
(c) hooking up items (a) and (b) so that targets auto-load the scripting resources as the corresponding modules get loaded in a target. This has a few caveats at the moment:
 - the user needs to manually add the .py file to the dSYM (soon, it will also work in the framework itself)
 - if two modules with the same name show up during the lifetime of an LLDB session, the second one won't be able to load its scripting resource, but will otherwise work just fine

llvm-svn: 167569
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 08f826e..e349d63 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lldb/Core/Error.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/DataBuffer.h"
 #include "lldb/Core/DataBufferHeap.h"
@@ -18,6 +19,9 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
 #include "lldb/lldb-private-log.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/ObjectFile.h"
@@ -1132,7 +1136,48 @@
     }
     return false;
 }
-bool 
+
+bool
+Module::LoadScriptingResourceInTarget (Target *target, Error& error)
+{
+    if (!target)
+    {
+        error.SetErrorString("invalid destination Target");
+        return false;
+    }
+    
+    PlatformSP platform_sp(target->GetPlatform());
+    
+    if (!platform_sp)
+    {
+        error.SetErrorString("invalid Platform");
+        return false;
+    }
+
+    ModuleSpec module_spec(GetFileSpec());
+    FileSpec scripting_fspec = platform_sp->LocateExecutableScriptingResource(module_spec);
+    Debugger &debugger(target->GetDebugger());
+    if (scripting_fspec && scripting_fspec.Exists())
+    {
+        ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+        if (script_interpreter)
+        {
+            StreamString scripting_stream;
+            scripting_fspec.Dump(&scripting_stream);
+            bool did_load = script_interpreter->LoadScriptingModule(scripting_stream.GetData(), false, true, error);
+            if (!did_load)
+                return false;
+        }
+        else
+        {
+            error.SetErrorString("invalid ScriptInterpreter");
+            return false;
+        }
+    }
+    return true;
+}
+
+bool
 Module::SetArchitecture (const ArchSpec &new_arch)
 {
     if (!m_arch.IsValid())
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 338482b..c7f7484 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -30,7 +30,8 @@
 //----------------------------------------------------------------------
 ModuleList::ModuleList() :
     m_modules(),
-    m_modules_mutex (Mutex::eMutexTypeRecursive)
+    m_modules_mutex (Mutex::eMutexTypeRecursive),
+    m_notifier(NULL)
 {
 }
 
@@ -44,6 +45,14 @@
     Mutex::Locker lhs_locker(m_modules_mutex);
     Mutex::Locker rhs_locker(rhs.m_modules_mutex);
     m_modules = rhs.m_modules;
+    m_notifier = rhs.m_notifier;
+}
+
+ModuleList::ModuleList (ModuleList::Notifier* notifier) :
+    m_modules(),
+    m_modules_mutex (Mutex::eMutexTypeRecursive),
+    m_notifier(notifier)
+{
 }
 
 //----------------------------------------------------------------------
@@ -57,6 +66,7 @@
         Mutex::Locker lhs_locker(m_modules_mutex);
         Mutex::Locker rhs_locker(rhs.m_modules_mutex);
         m_modules = rhs.m_modules;
+        m_notifier = rhs.m_notifier;
     }
     return *this;
 }
@@ -69,16 +79,24 @@
 }
 
 void
-ModuleList::Append (const ModuleSP &module_sp)
+ModuleList::AppendImpl (const ModuleSP &module_sp, bool use_notifier)
 {
     if (module_sp)
     {
         Mutex::Locker locker(m_modules_mutex);
         m_modules.push_back(module_sp);
+        if (use_notifier && m_notifier)
+            m_notifier->ModuleAdded(module_sp);
     }
 }
 
 void
+ModuleList::Append (const ModuleSP &module_sp)
+{
+    AppendImpl (module_sp);
+}
+
+void
 ModuleList::ReplaceEquivalent (const ModuleSP &module_sp)
 {
     if (module_sp)
@@ -95,12 +113,12 @@
         {
             ModuleSP module_sp (m_modules[idx]);
             if (module_sp->MatchesModuleSpec (equivalent_module_spec))
-                m_modules.erase(m_modules.begin() + idx);
+                RemoveImpl(m_modules.begin() + idx);
             else
                 ++idx;
         }
         // Now add the new module to the list
-        m_modules.push_back(module_sp);
+        Append(module_sp);
     }
 }
 
@@ -117,14 +135,30 @@
                 return false; // Already in the list
         }
         // Only push module_sp on the list if it wasn't already in there.
-        m_modules.push_back(module_sp);
+        Append(module_sp);
         return true;
     }
     return false;
 }
 
+void
+ModuleList::Append (const ModuleList& module_list)
+{
+    for (auto pos : module_list.m_modules)
+        Append(pos);
+}
+
 bool
-ModuleList::Remove (const ModuleSP &module_sp)
+ModuleList::AppendIfNeeded (const ModuleList& module_list)
+{
+    bool any_in = false;
+    for (auto pos : module_list.m_modules)
+        any_in = AppendIfNeeded(pos) | any_in;
+    return any_in;
+}
+
+bool
+ModuleList::RemoveImpl (const ModuleSP &module_sp, bool use_notifier)
 {
     if (module_sp)
     {
@@ -135,6 +169,8 @@
             if (pos->get() == module_sp.get())
             {
                 m_modules.erase (pos);
+                if (use_notifier && m_notifier)
+                    m_notifier->ModuleRemoved(module_sp);
                 return true;
             }
         }
@@ -142,6 +178,33 @@
     return false;
 }
 
+ModuleList::collection::iterator
+ModuleList::RemoveImpl (ModuleList::collection::iterator pos, bool use_notifier)
+{
+    ModuleSP module_sp(*pos);
+    collection::iterator retval = m_modules.erase(pos);
+    if (use_notifier && m_notifier)
+        m_notifier->ModuleRemoved(module_sp);
+    return retval;
+}
+
+bool
+ModuleList::Remove (const ModuleSP &module_sp)
+{
+    return RemoveImpl (module_sp);
+}
+
+bool
+ModuleList::ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)
+{
+    if (!RemoveImpl(old_module_sp, false))
+        return false;
+    AppendImpl (new_module_sp, false);
+    if (m_notifier)
+        m_notifier->ModuleUpdated(old_module_sp,new_module_sp);
+    return true;
+}
+
 bool
 ModuleList::RemoveIfOrphaned (const Module *module_ptr)
 {
@@ -155,7 +218,7 @@
             {
                 if (pos->unique())
                 {
-                    pos = m_modules.erase (pos);
+                    pos = RemoveImpl(pos);
                     return true;
                 }
                 else
@@ -187,7 +250,7 @@
     {
         if (pos->unique())
         {
-            pos = m_modules.erase (pos);
+            pos = RemoveImpl(pos);
             ++remove_count;
         }
         else
@@ -213,20 +276,25 @@
 }
 
 
-
 void
 ModuleList::Clear()
 {
-    Mutex::Locker locker(m_modules_mutex);
-    m_modules.clear();
+    ClearImpl();
 }
 
 void
 ModuleList::Destroy()
 {
+    ClearImpl();
+}
+
+void
+ModuleList::ClearImpl (bool use_notifier)
+{
     Mutex::Locker locker(m_modules_mutex);
-    collection empty;
-    m_modules.swap(empty);
+    if (use_notifier && m_notifier)
+        m_notifier->WillClearList();
+    m_modules.clear();
 }
 
 Module*
@@ -245,14 +313,14 @@
 }
 
 ModuleSP
-ModuleList::GetModuleAtIndex(uint32_t idx)
+ModuleList::GetModuleAtIndex(uint32_t idx) const
 {
     Mutex::Locker locker(m_modules_mutex);
     return GetModuleAtIndexUnlocked(idx);
 }
 
 ModuleSP
-ModuleList::GetModuleAtIndexUnlocked(uint32_t idx)
+ModuleList::GetModuleAtIndexUnlocked(uint32_t idx) const
 {
     ModuleSP module_sp;
     if (idx < m_modules.size())
@@ -266,7 +334,7 @@
                            bool include_symbols,
                            bool include_inlines,
                            bool append, 
-                           SymbolContextList &sc_list)
+                           SymbolContextList &sc_list) const
 {
     if (!append)
         sc_list.Clear();
@@ -284,7 +352,7 @@
 uint32_t
 ModuleList::FindCompileUnits (const FileSpec &path, 
                               bool append, 
-                              SymbolContextList &sc_list)
+                              SymbolContextList &sc_list) const
 {
     if (!append)
         sc_list.Clear();
@@ -303,11 +371,11 @@
 ModuleList::FindGlobalVariables (const ConstString &name, 
                                  bool append, 
                                  uint32_t max_matches, 
-                                 VariableList& variable_list)
+                                 VariableList& variable_list) const
 {
     size_t initial_size = variable_list.GetSize();
     Mutex::Locker locker(m_modules_mutex);
-    collection::iterator pos, end = m_modules.end();
+    collection::const_iterator pos, end = m_modules.end();
     for (pos = m_modules.begin(); pos != end; ++pos)
     {
         (*pos)->FindGlobalVariables (name, NULL, append, max_matches, variable_list);
@@ -320,11 +388,11 @@
 ModuleList::FindGlobalVariables (const RegularExpression& regex, 
                                  bool append, 
                                  uint32_t max_matches, 
-                                 VariableList& variable_list)
+                                 VariableList& variable_list) const
 {
     size_t initial_size = variable_list.GetSize();
     Mutex::Locker locker(m_modules_mutex);
-    collection::iterator pos, end = m_modules.end();
+    collection::const_iterator pos, end = m_modules.end();
     for (pos = m_modules.begin(); pos != end; ++pos)
     {
         (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list);
@@ -337,14 +405,14 @@
 ModuleList::FindSymbolsWithNameAndType (const ConstString &name, 
                                         SymbolType symbol_type, 
                                         SymbolContextList &sc_list,
-                                        bool append)
+                                        bool append) const
 {
     Mutex::Locker locker(m_modules_mutex);
     if (!append)
         sc_list.Clear();
     size_t initial_size = sc_list.GetSize();
     
-    collection::iterator pos, end = m_modules.end();
+    collection::const_iterator pos, end = m_modules.end();
     for (pos = m_modules.begin(); pos != end; ++pos)
         (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list);
     return sc_list.GetSize() - initial_size;
@@ -354,14 +422,14 @@
 ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, 
                                              lldb::SymbolType symbol_type, 
                                              SymbolContextList &sc_list,
-                                             bool append)
+                                             bool append) const
 {
     Mutex::Locker locker(m_modules_mutex);
     if (!append)
         sc_list.Clear();
     size_t initial_size = sc_list.GetSize();
     
-    collection::iterator pos, end = m_modules.end();
+    collection::const_iterator pos, end = m_modules.end();
     for (pos = m_modules.begin(); pos != end; ++pos)
         (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list);
     return sc_list.GetSize() - initial_size;
@@ -384,7 +452,7 @@
 }
 
 ModuleSP
-ModuleList::FindModule (const Module *module_ptr)
+ModuleList::FindModule (const Module *module_ptr) const
 {
     ModuleSP module_sp;
 
@@ -407,7 +475,7 @@
 }
 
 ModuleSP
-ModuleList::FindModule (const UUID &uuid)
+ModuleList::FindModule (const UUID &uuid) const
 {
     ModuleSP module_sp;
     
@@ -430,7 +498,7 @@
 
 
 uint32_t
-ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types)
+ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, uint32_t max_matches, TypeList& types) const
 {
     Mutex::Locker locker(m_modules_mutex);
 
@@ -487,7 +555,7 @@
 
 
 ModuleSP
-ModuleList::FindFirstModule (const ModuleSpec &module_spec)
+ModuleList::FindFirstModule (const ModuleSpec &module_spec) const
 {
     ModuleSP module_sp;
     Mutex::Locker locker(m_modules_mutex);
@@ -554,7 +622,7 @@
 }
 
 bool
-ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
+ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) const
 {
     Mutex::Locker locker(m_modules_mutex);
     collection::const_iterator pos, end = m_modules.end();
@@ -568,7 +636,7 @@
 }
 
 uint32_t
-ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) const
 {
     // The address is already section offset so it has a module
     uint32_t resolved_flags = 0;
@@ -604,14 +672,14 @@
     bool check_inlines, 
     uint32_t resolve_scope, 
     SymbolContextList& sc_list
-)
+)  const
 {
     FileSpec file_spec(file_path, false);
     return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
 }
 
 uint32_t
-ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const
 {
     Mutex::Locker locker(m_modules_mutex);
     collection::const_iterator pos, end = m_modules.end();
diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp
index 60f7dbb..d9af19e 100644
--- a/lldb/source/Core/SearchFilter.cpp
+++ b/lldb/source/Core/SearchFilter.cpp
@@ -204,7 +204,7 @@
         }
         else
         {
-            ModuleList &target_images = m_target_sp->GetImages();
+            const ModuleList &target_images = m_target_sp->GetImages();
             Mutex::Locker modules_locker(target_images.GetMutex());
             
             size_t n_modules = target_images.GetSize();
@@ -428,7 +428,7 @@
     // filespec that passes.  Otherwise, we need to go through all modules and
     // find the ones that match the file name.
 
-    ModuleList &target_modules = m_target_sp->GetImages();
+    const ModuleList &target_modules = m_target_sp->GetImages();
     Mutex::Locker modules_locker (target_modules.GetMutex());
     
     const size_t num_modules = target_modules.GetSize ();
@@ -595,7 +595,7 @@
     // filespec that passes.  Otherwise, we need to go through all modules and
     // find the ones that match the file name.
 
-    ModuleList &target_modules = m_target_sp->GetImages();
+    const ModuleList &target_modules = m_target_sp->GetImages();
     Mutex::Locker modules_locker (target_modules.GetMutex());
     
     const size_t num_modules = target_modules.GetSize ();
@@ -768,7 +768,7 @@
     // find the ones that match the file name.
 
     ModuleList matching_modules;
-    ModuleList &target_images = m_target_sp->GetImages();
+    const ModuleList &target_images = m_target_sp->GetImages();
     Mutex::Locker modules_locker(target_images.GetMutex());
     
     const size_t num_modules = target_images.GetSize ();