Add a new system runtime plugin type - just the top level
class, not any actual plugin implementation yet.
<rdar://problem/15314068> 

llvm-svn: 194044
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 7a2d377..813cec2 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -854,6 +854,111 @@
     return NULL;
 }
 
+#pragma mark SystemRuntime
+
+
+struct SystemRuntimeInstance
+{
+    SystemRuntimeInstance() :
+        name(),
+        description(),
+        create_callback(NULL)
+    {
+    }
+
+    ConstString name;
+    std::string description;
+    SystemRuntimeCreateInstance create_callback;
+};
+
+typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances;
+
+static Mutex &
+GetSystemRuntimeMutex ()
+{
+    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+    return g_instances_mutex;
+}
+
+static SystemRuntimeInstances &
+GetSystemRuntimeInstances ()
+{
+    static SystemRuntimeInstances g_instances;
+    return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin
+(
+    const ConstString &name,
+    const char *description,
+    SystemRuntimeCreateInstance create_callback
+)
+{
+    if (create_callback)
+    {
+        SystemRuntimeInstance instance;
+        assert ((bool)name);
+        instance.name = name;
+        if (description && description[0])
+            instance.description = description;
+        instance.create_callback = create_callback;
+        Mutex::Locker locker (GetSystemRuntimeMutex ());
+        GetSystemRuntimeInstances ().push_back (instance);
+    }
+    return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (SystemRuntimeCreateInstance create_callback)
+{
+    if (create_callback)
+    {
+        Mutex::Locker locker (GetSystemRuntimeMutex ());
+        SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
+        
+        SystemRuntimeInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (pos->create_callback == create_callback)
+            {
+                instances.erase(pos);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+SystemRuntimeCreateInstance
+PluginManager::GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx)
+{
+    Mutex::Locker locker (GetSystemRuntimeMutex ());
+    SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
+    if (idx < instances.size())
+        return instances[idx].create_callback;
+    return NULL;
+}
+
+SystemRuntimeCreateInstance
+PluginManager::GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name)
+{
+    if (name)
+    {
+        Mutex::Locker locker (GetSystemRuntimeMutex ());
+        SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
+        
+        SystemRuntimeInstances::iterator pos, end = instances.end();
+        for (pos = instances.begin(); pos != end; ++ pos)
+        {
+            if (name == pos->name)
+                return pos->create_callback;
+        }
+    }
+    return NULL;
+}
+
+
 #pragma mark ObjectFile
 
 struct ObjectFileInstance
diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt
index 29f9bcd..6e211ff 100644
--- a/lldb/source/Target/CMakeLists.txt
+++ b/lldb/source/Target/CMakeLists.txt
@@ -19,6 +19,7 @@
   StackFrameList.cpp
   StackID.cpp
   StopInfo.cpp
+  SystemRuntime.cpp
   Target.cpp
   TargetList.cpp
   Thread.cpp
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index fcab7af..d5d1456 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -35,6 +35,7 @@
 #include "lldb/Target/Platform.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SystemRuntime.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/TargetList.h"
 #include "lldb/Target/Thread.h"
@@ -1143,6 +1144,7 @@
     m_dynamic_checkers_ap.reset();
     m_abi_sp.reset();
     m_os_ap.reset();
+    m_system_runtime_ap.reset();
     m_dyld_ap.reset();
     m_thread_list_real.Destroy();
     m_thread_list.Destroy();
@@ -2876,6 +2878,7 @@
     Error error;
     m_abi_sp.reset();
     m_dyld_ap.reset();
+    m_system_runtime_ap.reset();
     m_os_ap.reset();
     m_process_input_reader.reset();
 
@@ -2944,6 +2947,10 @@
                         if (dyld)
                             dyld->DidLaunch();
 
+                        SystemRuntime *system_runtime = GetSystemRuntime ();
+                        if (system_runtime)
+                            system_runtime->DidLaunch();
+
                         m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
                         // This delays passing the stopped event to listeners till DidLaunch gets
                         // a chance to complete...
@@ -2987,6 +2994,10 @@
         if (dyld)
             dyld->DidAttach();
         
+        SystemRuntime *system_runtime = GetSystemRuntime ();
+        if (system_runtime)
+            system_runtime->DidAttach();
+
         m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
         // We successfully loaded a core file, now pretend we stopped so we can
         // show all of the threads in the core file and explore the crashed
@@ -3005,6 +3016,14 @@
     return m_dyld_ap.get();
 }
 
+SystemRuntime *
+Process::GetSystemRuntime ()
+{
+    if (m_system_runtime_ap.get() == NULL)
+        m_system_runtime_ap.reset (SystemRuntime::FindPlugin(this));
+    return m_system_runtime_ap.get();
+}
+
 
 Process::NextEventAction::EventActionResult
 Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
@@ -3067,6 +3086,7 @@
     m_abi_sp.reset();
     m_process_input_reader.reset();
     m_dyld_ap.reset();
+    m_system_runtime_ap.reset();
     m_os_ap.reset();
     
     lldb::pid_t attach_pid = attach_info.GetProcessID();
@@ -3239,6 +3259,10 @@
     if (dyld)
         dyld->DidAttach();
 
+    SystemRuntime *system_runtime = GetSystemRuntime ();
+    if (system_runtime)
+        system_runtime->DidAttach();
+
     m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
     // Figure out which one is the executable, and set that in our target:
     const ModuleList &target_modules = m_target.GetImages();
@@ -5614,6 +5638,7 @@
     target.GetSectionLoadList().Clear();
     m_dynamic_checkers_ap.reset();
     m_abi_sp.reset();
+    m_system_runtime_ap.reset();
     m_os_ap.reset();
     m_dyld_ap.reset();
     m_image_tokens.clear();
diff --git a/lldb/source/Target/SystemRuntime.cpp b/lldb/source/Target/SystemRuntime.cpp
new file mode 100644
index 0000000..ceec6b6
--- /dev/null
+++ b/lldb/source/Target/SystemRuntime.cpp
@@ -0,0 +1,67 @@
+//===-- SystemRuntime.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/SystemRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SystemRuntime*
+SystemRuntime::FindPlugin (Process *process)
+{
+    SystemRuntimeCreateInstance create_callback = NULL;
+    for (uint32_t idx = 0; (create_callback = PluginManager::GetSystemRuntimeCreateCallbackAtIndex(idx)) != NULL; ++idx)
+    {
+        std::unique_ptr<SystemRuntime> instance_ap(create_callback(process));
+        if (instance_ap.get())
+            return instance_ap.release();
+    }
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// SystemRuntime constructor
+//----------------------------------------------------------------------
+SystemRuntime::SystemRuntime(Process *process) :
+    m_process (process)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SystemRuntime::~SystemRuntime()
+{
+}
+
+void
+SystemRuntime::DidAttach ()
+{
+}
+
+void
+SystemRuntime::DidLaunch()
+{
+}
+
+void
+SystemRuntime::ModulesDidLoad (ModuleList &module_list)
+{
+}
+
+uint32_t
+SystemRuntime::GetStatus (Stream &strm, ExecutionContext &exe_ctx)
+{
+    return 0;
+}
+
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index f93ae50..c512a05 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -43,6 +43,7 @@
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StackFrame.h"
+#include "lldb/Target/SystemRuntime.h"
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadSpec.h"
 
@@ -1155,6 +1156,14 @@
     if (module_list.GetSize())
     {
         m_breakpoint_list.UpdateBreakpoints (module_list, true);
+        if (m_process_sp)
+        {
+            SystemRuntime *sys_runtime = m_process_sp->GetSystemRuntime();
+            if (sys_runtime)
+            {
+                sys_runtime->ModulesDidLoad (module_list);
+            }
+        }
         // TODO: make event data that packages up the module_list
         BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
     }