2564 lines
		
	
	
		
			83 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			2564 lines
		
	
	
		
			83 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- PluginManager.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/Core/PluginManager.h"
 | |
| 
 | |
| #include "lldb/Core/Debugger.h"
 | |
| #include "lldb/Host/HostInfo.h"
 | |
| #include "lldb/Interpreter/OptionValueProperties.h"
 | |
| #include "lldb/Utility/ConstString.h" // for ConstString
 | |
| #include "lldb/Utility/FileSpec.h"
 | |
| #include "lldb/Utility/Status.h"
 | |
| #include "lldb/Utility/StringList.h" // for StringList
 | |
| 
 | |
| #if defined(LLVM_ON_WIN32)
 | |
| #include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
 | |
| #endif
 | |
| 
 | |
| #include "llvm/ADT/StringRef.h"
 | |
| #include "llvm/Support/DynamicLibrary.h"
 | |
| #include "llvm/Support/FileSystem.h"  // for file_type, file_...
 | |
| #include "llvm/Support/raw_ostream.h" // for fs
 | |
| 
 | |
| #include <map>    // for map<>::const_ite...
 | |
| #include <memory> // for shared_ptr
 | |
| #include <mutex>
 | |
| #include <string>
 | |
| #include <utility> // for pair
 | |
| #include <vector>
 | |
| 
 | |
| #include <assert.h> // for assert
 | |
| 
 | |
| namespace lldb_private {
 | |
| class CommandInterpreter;
 | |
| }
 | |
| 
 | |
| using namespace lldb;
 | |
| using namespace lldb_private;
 | |
| 
 | |
| enum PluginAction {
 | |
|   ePluginRegisterInstance,
 | |
|   ePluginUnregisterInstance,
 | |
|   ePluginGetInstanceAtIndex
 | |
| };
 | |
| 
 | |
| typedef bool (*PluginInitCallback)();
 | |
| typedef void (*PluginTermCallback)();
 | |
| 
 | |
| struct PluginInfo {
 | |
|   PluginInfo() : plugin_init_callback(nullptr), plugin_term_callback(nullptr) {}
 | |
| 
 | |
|   llvm::sys::DynamicLibrary library;
 | |
|   PluginInitCallback plugin_init_callback;
 | |
|   PluginTermCallback plugin_term_callback;
 | |
| };
 | |
| 
 | |
| typedef std::map<FileSpec, PluginInfo> PluginTerminateMap;
 | |
| 
 | |
| static std::recursive_mutex &GetPluginMapMutex() {
 | |
|   static std::recursive_mutex g_plugin_map_mutex;
 | |
|   return g_plugin_map_mutex;
 | |
| }
 | |
| 
 | |
| static PluginTerminateMap &GetPluginMap() {
 | |
|   static PluginTerminateMap g_plugin_map;
 | |
|   return g_plugin_map;
 | |
| }
 | |
| 
 | |
| static bool PluginIsLoaded(const FileSpec &plugin_file_spec) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex());
 | |
|   PluginTerminateMap &plugin_map = GetPluginMap();
 | |
|   return plugin_map.find(plugin_file_spec) != plugin_map.end();
 | |
| }
 | |
| 
 | |
| static void SetPluginInfo(const FileSpec &plugin_file_spec,
 | |
|                           const PluginInfo &plugin_info) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex());
 | |
|   PluginTerminateMap &plugin_map = GetPluginMap();
 | |
|   assert(plugin_map.find(plugin_file_spec) == plugin_map.end());
 | |
|   plugin_map[plugin_file_spec] = plugin_info;
 | |
| }
 | |
| 
 | |
| template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) {
 | |
|   return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr));
 | |
| }
 | |
| 
 | |
| static FileSpec::EnumerateDirectoryResult
 | |
| LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
 | |
|                    const FileSpec &file_spec) {
 | |
|   //    PluginManager *plugin_manager = (PluginManager *)baton;
 | |
|   Status error;
 | |
| 
 | |
|   namespace fs = llvm::sys::fs;
 | |
|   // If we have a regular file, a symbolic link or unknown file type, try
 | |
|   // and process the file. We must handle unknown as sometimes the directory
 | |
|   // enumeration might be enumerating a file system that doesn't have correct
 | |
|   // file type information.
 | |
|   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
 | |
|       ft == fs::file_type::type_unknown) {
 | |
|     FileSpec plugin_file_spec(file_spec);
 | |
|     plugin_file_spec.ResolvePath();
 | |
| 
 | |
|     if (PluginIsLoaded(plugin_file_spec))
 | |
|       return FileSpec::eEnumerateDirectoryResultNext;
 | |
|     else {
 | |
|       PluginInfo plugin_info;
 | |
| 
 | |
|       std::string pluginLoadError;
 | |
|       plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary(
 | |
|           plugin_file_spec.GetPath().c_str(), &pluginLoadError);
 | |
|       if (plugin_info.library.isValid()) {
 | |
|         bool success = false;
 | |
|         plugin_info.plugin_init_callback = CastToFPtr<PluginInitCallback>(
 | |
|             plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize"));
 | |
|         if (plugin_info.plugin_init_callback) {
 | |
|           // Call the plug-in "bool LLDBPluginInitialize(void)" function
 | |
|           success = plugin_info.plugin_init_callback();
 | |
|         }
 | |
| 
 | |
|         if (success) {
 | |
|           // It is ok for the "LLDBPluginTerminate" symbol to be nullptr
 | |
|           plugin_info.plugin_term_callback = CastToFPtr<PluginTermCallback>(
 | |
|               plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate"));
 | |
|         } else {
 | |
|           // The initialize function returned FALSE which means the plug-in
 | |
|           // might not be
 | |
|           // compatible, or might be too new or too old, or might not want to
 | |
|           // run on this
 | |
|           // machine.  Set it to a default-constructed instance to invalidate
 | |
|           // it.
 | |
|           plugin_info = PluginInfo();
 | |
|         }
 | |
| 
 | |
|         // Regardless of success or failure, cache the plug-in load
 | |
|         // in our plug-in info so we don't try to load it again and
 | |
|         // again.
 | |
|         SetPluginInfo(plugin_file_spec, plugin_info);
 | |
| 
 | |
|         return FileSpec::eEnumerateDirectoryResultNext;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (ft == fs::file_type::directory_file ||
 | |
|       ft == fs::file_type::symlink_file || ft == fs::file_type::type_unknown) {
 | |
|     // Try and recurse into anything that a directory or symbolic link.
 | |
|     // We must also do this for unknown as sometimes the directory enumeration
 | |
|     // might be enumerating a file system that doesn't have correct file type
 | |
|     // information.
 | |
|     return FileSpec::eEnumerateDirectoryResultEnter;
 | |
|   }
 | |
| 
 | |
|   return FileSpec::eEnumerateDirectoryResultNext;
 | |
| }
 | |
| 
 | |
| void PluginManager::Initialize() {
 | |
| #if 1
 | |
|   FileSpec dir_spec;
 | |
|   const bool find_directories = true;
 | |
|   const bool find_files = true;
 | |
|   const bool find_other = true;
 | |
|   char dir_path[PATH_MAX];
 | |
|   if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
 | |
|     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
 | |
|       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
 | |
|                                    find_other, LoadPluginCallback, nullptr);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
 | |
|     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
 | |
|       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
 | |
|                                    find_other, LoadPluginCallback, nullptr);
 | |
|     }
 | |
|   }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void PluginManager::Terminate() {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex());
 | |
|   PluginTerminateMap &plugin_map = GetPluginMap();
 | |
| 
 | |
|   PluginTerminateMap::const_iterator pos, end = plugin_map.end();
 | |
|   for (pos = plugin_map.begin(); pos != end; ++pos) {
 | |
|     // Call the plug-in "void LLDBPluginTerminate (void)" function if there
 | |
|     // is one (if the symbol was not nullptr).
 | |
|     if (pos->second.library.isValid()) {
 | |
|       if (pos->second.plugin_term_callback)
 | |
|         pos->second.plugin_term_callback();
 | |
|     }
 | |
|   }
 | |
|   plugin_map.clear();
 | |
| }
 | |
| 
 | |
| #pragma mark ABI
 | |
| 
 | |
| struct ABIInstance {
 | |
|   ABIInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   ABICreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<ABIInstance> ABIInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetABIInstancesMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static ABIInstances &GetABIInstances() {
 | |
|   static ABIInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(const ConstString &name,
 | |
|                                    const char *description,
 | |
|                                    ABICreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     ABIInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
 | |
|     GetABIInstances().push_back(instance);
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(ABICreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
 | |
|     ABIInstances &instances = GetABIInstances();
 | |
| 
 | |
|     ABIInstances::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;
 | |
| }
 | |
| 
 | |
| ABICreateInstance PluginManager::GetABICreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
 | |
|   ABIInstances &instances = GetABIInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ABICreateInstance
 | |
| PluginManager::GetABICreateCallbackForPluginName(const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex());
 | |
|     ABIInstances &instances = GetABIInstances();
 | |
| 
 | |
|     ABIInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark Disassembler
 | |
| 
 | |
| struct DisassemblerInstance {
 | |
|   DisassemblerInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   DisassemblerCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<DisassemblerInstance> DisassemblerInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetDisassemblerMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static DisassemblerInstances &GetDisassemblerInstances() {
 | |
|   static DisassemblerInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(const ConstString &name,
 | |
|                                    const char *description,
 | |
|                                    DisassemblerCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     DisassemblerInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
 | |
|     GetDisassemblerInstances().push_back(instance);
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     DisassemblerCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
 | |
|     DisassemblerInstances &instances = GetDisassemblerInstances();
 | |
| 
 | |
|     DisassemblerInstances::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;
 | |
| }
 | |
| 
 | |
| DisassemblerCreateInstance
 | |
| PluginManager::GetDisassemblerCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
 | |
|   DisassemblerInstances &instances = GetDisassemblerInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| DisassemblerCreateInstance
 | |
| PluginManager::GetDisassemblerCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex());
 | |
|     DisassemblerInstances &instances = GetDisassemblerInstances();
 | |
| 
 | |
|     DisassemblerInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark DynamicLoader
 | |
| 
 | |
| struct DynamicLoaderInstance {
 | |
|   DynamicLoaderInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   DynamicLoaderCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetDynamicLoaderMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static DynamicLoaderInstances &GetDynamicLoaderInstances() {
 | |
|   static DynamicLoaderInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     DynamicLoaderCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback) {
 | |
|   if (create_callback) {
 | |
|     DynamicLoaderInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
 | |
|     GetDynamicLoaderInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     DynamicLoaderCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
 | |
|     DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
 | |
| 
 | |
|     DynamicLoaderInstances::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;
 | |
| }
 | |
| 
 | |
| DynamicLoaderCreateInstance
 | |
| PluginManager::GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
 | |
|   DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| DynamicLoaderCreateInstance
 | |
| PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
 | |
|     DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
 | |
| 
 | |
|     DynamicLoaderInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark JITLoader
 | |
| 
 | |
| struct JITLoaderInstance {
 | |
|   JITLoaderInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   JITLoaderCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<JITLoaderInstance> JITLoaderInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetJITLoaderMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static JITLoaderInstances &GetJITLoaderInstances() {
 | |
|   static JITLoaderInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     JITLoaderCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback) {
 | |
|   if (create_callback) {
 | |
|     JITLoaderInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
 | |
|     GetJITLoaderInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(JITLoaderCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
 | |
|     JITLoaderInstances &instances = GetJITLoaderInstances();
 | |
| 
 | |
|     JITLoaderInstances::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;
 | |
| }
 | |
| 
 | |
| JITLoaderCreateInstance
 | |
| PluginManager::GetJITLoaderCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
 | |
|   JITLoaderInstances &instances = GetJITLoaderInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| JITLoaderCreateInstance PluginManager::GetJITLoaderCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
 | |
|     JITLoaderInstances &instances = GetJITLoaderInstances();
 | |
| 
 | |
|     JITLoaderInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark EmulateInstruction
 | |
| 
 | |
| struct EmulateInstructionInstance {
 | |
|   EmulateInstructionInstance()
 | |
|       : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   EmulateInstructionCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<EmulateInstructionInstance> EmulateInstructionInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetEmulateInstructionMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static EmulateInstructionInstances &GetEmulateInstructionInstances() {
 | |
|   static EmulateInstructionInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     EmulateInstructionCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     EmulateInstructionInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
 | |
|     GetEmulateInstructionInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     EmulateInstructionCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
 | |
|     EmulateInstructionInstances &instances = GetEmulateInstructionInstances();
 | |
| 
 | |
|     EmulateInstructionInstances::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;
 | |
| }
 | |
| 
 | |
| EmulateInstructionCreateInstance
 | |
| PluginManager::GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
 | |
|   EmulateInstructionInstances &instances = GetEmulateInstructionInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| EmulateInstructionCreateInstance
 | |
| PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex());
 | |
|     EmulateInstructionInstances &instances = GetEmulateInstructionInstances();
 | |
| 
 | |
|     EmulateInstructionInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark OperatingSystem
 | |
| 
 | |
| struct OperatingSystemInstance {
 | |
|   OperatingSystemInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   OperatingSystemCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<OperatingSystemInstance> OperatingSystemInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetOperatingSystemMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static OperatingSystemInstances &GetOperatingSystemInstances() {
 | |
|   static OperatingSystemInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     OperatingSystemCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback) {
 | |
|   if (create_callback) {
 | |
|     OperatingSystemInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
 | |
|     GetOperatingSystemInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     OperatingSystemCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
 | |
|     OperatingSystemInstances &instances = GetOperatingSystemInstances();
 | |
| 
 | |
|     OperatingSystemInstances::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;
 | |
| }
 | |
| 
 | |
| OperatingSystemCreateInstance
 | |
| PluginManager::GetOperatingSystemCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
 | |
|   OperatingSystemInstances &instances = GetOperatingSystemInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| OperatingSystemCreateInstance
 | |
| PluginManager::GetOperatingSystemCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
 | |
|     OperatingSystemInstances &instances = GetOperatingSystemInstances();
 | |
| 
 | |
|     OperatingSystemInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark Language
 | |
| 
 | |
| struct LanguageInstance {
 | |
|   LanguageInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   LanguageCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<LanguageInstance> LanguageInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetLanguageMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static LanguageInstances &GetLanguageInstances() {
 | |
|   static LanguageInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(const ConstString &name,
 | |
|                                    const char *description,
 | |
|                                    LanguageCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     LanguageInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
 | |
|     GetLanguageInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(LanguageCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
 | |
|     LanguageInstances &instances = GetLanguageInstances();
 | |
| 
 | |
|     LanguageInstances::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;
 | |
| }
 | |
| 
 | |
| LanguageCreateInstance
 | |
| PluginManager::GetLanguageCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
 | |
|   LanguageInstances &instances = GetLanguageInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| LanguageCreateInstance
 | |
| PluginManager::GetLanguageCreateCallbackForPluginName(const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex());
 | |
|     LanguageInstances &instances = GetLanguageInstances();
 | |
| 
 | |
|     LanguageInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark LanguageRuntime
 | |
| 
 | |
| struct LanguageRuntimeInstance {
 | |
|   LanguageRuntimeInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   LanguageRuntimeCreateInstance create_callback;
 | |
|   LanguageRuntimeGetCommandObject command_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetLanguageRuntimeMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static LanguageRuntimeInstances &GetLanguageRuntimeInstances() {
 | |
|   static LanguageRuntimeInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     LanguageRuntimeCreateInstance create_callback,
 | |
|     LanguageRuntimeGetCommandObject command_callback) {
 | |
|   if (create_callback) {
 | |
|     LanguageRuntimeInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.command_callback = command_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
 | |
|     GetLanguageRuntimeInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     LanguageRuntimeCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
 | |
|     LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
 | |
| 
 | |
|     LanguageRuntimeInstances::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;
 | |
| }
 | |
| 
 | |
| LanguageRuntimeCreateInstance
 | |
| PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
 | |
|   LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| LanguageRuntimeGetCommandObject
 | |
| PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
 | |
|   LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].command_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| LanguageRuntimeCreateInstance
 | |
| PluginManager::GetLanguageRuntimeCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
 | |
|     LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
 | |
| 
 | |
|     LanguageRuntimeInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark SystemRuntime
 | |
| 
 | |
| struct SystemRuntimeInstance {
 | |
|   SystemRuntimeInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   SystemRuntimeCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetSystemRuntimeMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   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;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex());
 | |
|     GetSystemRuntimeInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     SystemRuntimeCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(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) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex());
 | |
|   SystemRuntimeInstances &instances = GetSystemRuntimeInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| SystemRuntimeCreateInstance
 | |
| PluginManager::GetSystemRuntimeCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(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 nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark ObjectFile
 | |
| 
 | |
| struct ObjectFileInstance {
 | |
|   ObjectFileInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         create_memory_callback(nullptr), get_module_specifications(nullptr),
 | |
|         save_core(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   ObjectFileCreateInstance create_callback;
 | |
|   ObjectFileCreateMemoryInstance create_memory_callback;
 | |
|   ObjectFileGetModuleSpecifications get_module_specifications;
 | |
|   ObjectFileSaveCore save_core;
 | |
| };
 | |
| 
 | |
| typedef std::vector<ObjectFileInstance> ObjectFileInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetObjectFileMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static ObjectFileInstances &GetObjectFileInstances() {
 | |
|   static ObjectFileInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     ObjectFileCreateInstance create_callback,
 | |
|     ObjectFileCreateMemoryInstance create_memory_callback,
 | |
|     ObjectFileGetModuleSpecifications get_module_specifications,
 | |
|     ObjectFileSaveCore save_core) {
 | |
|   if (create_callback) {
 | |
|     ObjectFileInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.create_memory_callback = create_memory_callback;
 | |
|     instance.save_core = save_core;
 | |
|     instance.get_module_specifications = get_module_specifications;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|     GetObjectFileInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(ObjectFileCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|     ObjectFileInstances &instances = GetObjectFileInstances();
 | |
| 
 | |
|     ObjectFileInstances::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;
 | |
| }
 | |
| 
 | |
| ObjectFileCreateInstance
 | |
| PluginManager::GetObjectFileCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|   ObjectFileInstances &instances = GetObjectFileInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ObjectFileCreateMemoryInstance
 | |
| PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|   ObjectFileInstances &instances = GetObjectFileInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_memory_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ObjectFileGetModuleSpecifications
 | |
| PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(
 | |
|     uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|   ObjectFileInstances &instances = GetObjectFileInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].get_module_specifications;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ObjectFileCreateInstance
 | |
| PluginManager::GetObjectFileCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|     ObjectFileInstances &instances = GetObjectFileInstances();
 | |
| 
 | |
|     ObjectFileInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ObjectFileCreateMemoryInstance
 | |
| PluginManager::GetObjectFileCreateMemoryCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|     ObjectFileInstances &instances = GetObjectFileInstances();
 | |
| 
 | |
|     ObjectFileInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_memory_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
 | |
|                                const FileSpec &outfile) {
 | |
|   Status error;
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex());
 | |
|   ObjectFileInstances &instances = GetObjectFileInstances();
 | |
| 
 | |
|   ObjectFileInstances::iterator pos, end = instances.end();
 | |
|   for (pos = instances.begin(); pos != end; ++pos) {
 | |
|     if (pos->save_core && pos->save_core(process_sp, outfile, error))
 | |
|       return error;
 | |
|   }
 | |
|   error.SetErrorString(
 | |
|       "no ObjectFile plugins were able to save a core for this process");
 | |
|   return error;
 | |
| }
 | |
| 
 | |
| #pragma mark ObjectContainer
 | |
| 
 | |
| struct ObjectContainerInstance {
 | |
|   ObjectContainerInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         get_module_specifications(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   ObjectContainerCreateInstance create_callback;
 | |
|   ObjectFileGetModuleSpecifications get_module_specifications;
 | |
| };
 | |
| 
 | |
| typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetObjectContainerMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static ObjectContainerInstances &GetObjectContainerInstances() {
 | |
|   static ObjectContainerInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     ObjectContainerCreateInstance create_callback,
 | |
|     ObjectFileGetModuleSpecifications get_module_specifications) {
 | |
|   if (create_callback) {
 | |
|     ObjectContainerInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.get_module_specifications = get_module_specifications;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
 | |
|     GetObjectContainerInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     ObjectContainerCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
 | |
|     ObjectContainerInstances &instances = GetObjectContainerInstances();
 | |
| 
 | |
|     ObjectContainerInstances::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;
 | |
| }
 | |
| 
 | |
| ObjectContainerCreateInstance
 | |
| PluginManager::GetObjectContainerCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
 | |
|   ObjectContainerInstances &instances = GetObjectContainerInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ObjectContainerCreateInstance
 | |
| PluginManager::GetObjectContainerCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
 | |
|     ObjectContainerInstances &instances = GetObjectContainerInstances();
 | |
| 
 | |
|     ObjectContainerInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ObjectFileGetModuleSpecifications
 | |
| PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex(
 | |
|     uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex());
 | |
|   ObjectContainerInstances &instances = GetObjectContainerInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].get_module_specifications;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark Platform
 | |
| 
 | |
| struct PlatformInstance {
 | |
|   PlatformInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   PlatformCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<PlatformInstance> PlatformInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetPlatformInstancesMutex() {
 | |
|   static std::recursive_mutex g_platform_instances_mutex;
 | |
|   return g_platform_instances_mutex;
 | |
| }
 | |
| 
 | |
| static PlatformInstances &GetPlatformInstances() {
 | |
|   static PlatformInstances g_platform_instances;
 | |
|   return g_platform_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     PlatformCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
| 
 | |
|     PlatformInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     GetPlatformInstances().push_back(instance);
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| const char *PluginManager::GetPlatformPluginNameAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|   PlatformInstances &instances = GetPlatformInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].name.GetCString();
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| const char *PluginManager::GetPlatformPluginDescriptionAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|   PlatformInstances &instances = GetPlatformInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].description.c_str();
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|     PlatformInstances &instances = GetPlatformInstances();
 | |
| 
 | |
|     PlatformInstances::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;
 | |
| }
 | |
| 
 | |
| PlatformCreateInstance
 | |
| PluginManager::GetPlatformCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|   PlatformInstances &instances = GetPlatformInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| PlatformCreateInstance
 | |
| PluginManager::GetPlatformCreateCallbackForPluginName(const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|     PlatformInstances &instances = GetPlatformInstances();
 | |
| 
 | |
|     PlatformInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| size_t PluginManager::AutoCompletePlatformName(llvm::StringRef name,
 | |
|                                                StringList &matches) {
 | |
|   if (name.empty())
 | |
|     return matches.GetSize();
 | |
| 
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|   PlatformInstances &instances = GetPlatformInstances();
 | |
|   llvm::StringRef name_sref(name);
 | |
| 
 | |
|   PlatformInstances::iterator pos, end = instances.end();
 | |
|   for (pos = instances.begin(); pos != end; ++pos) {
 | |
|     llvm::StringRef plugin_name(pos->name.GetCString());
 | |
|     if (plugin_name.startswith(name_sref))
 | |
|       matches.AppendString(plugin_name.data());
 | |
|   }
 | |
|   return matches.GetSize();
 | |
| }
 | |
| 
 | |
| #pragma mark Process
 | |
| 
 | |
| struct ProcessInstance {
 | |
|   ProcessInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   ProcessCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<ProcessInstance> ProcessInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetProcessMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static ProcessInstances &GetProcessInstances() {
 | |
|   static ProcessInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     ProcessCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback) {
 | |
|   if (create_callback) {
 | |
|     ProcessInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|     GetProcessInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| const char *PluginManager::GetProcessPluginNameAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|   ProcessInstances &instances = GetProcessInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].name.GetCString();
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| const char *PluginManager::GetProcessPluginDescriptionAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|   ProcessInstances &instances = GetProcessInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].description.c_str();
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|     ProcessInstances &instances = GetProcessInstances();
 | |
| 
 | |
|     ProcessInstances::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;
 | |
| }
 | |
| 
 | |
| ProcessCreateInstance
 | |
| PluginManager::GetProcessCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|   ProcessInstances &instances = GetProcessInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| ProcessCreateInstance
 | |
| PluginManager::GetProcessCreateCallbackForPluginName(const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|     ProcessInstances &instances = GetProcessInstances();
 | |
| 
 | |
|     ProcessInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark ScriptInterpreter
 | |
| 
 | |
| struct ScriptInterpreterInstance {
 | |
|   ScriptInterpreterInstance()
 | |
|       : name(), language(lldb::eScriptLanguageNone), description(),
 | |
|         create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   lldb::ScriptLanguage language;
 | |
|   std::string description;
 | |
|   ScriptInterpreterCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<ScriptInterpreterInstance> ScriptInterpreterInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetScriptInterpreterMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static ScriptInterpreterInstances &GetScriptInterpreterInstances() {
 | |
|   static ScriptInterpreterInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     lldb::ScriptLanguage script_language,
 | |
|     ScriptInterpreterCreateInstance create_callback) {
 | |
|   if (!create_callback)
 | |
|     return false;
 | |
|   ScriptInterpreterInstance instance;
 | |
|   assert((bool)name);
 | |
|   instance.name = name;
 | |
|   if (description && description[0])
 | |
|     instance.description = description;
 | |
|   instance.create_callback = create_callback;
 | |
|   instance.language = script_language;
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
 | |
|   GetScriptInterpreterInstances().push_back(instance);
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     ScriptInterpreterCreateInstance create_callback) {
 | |
|   if (!create_callback)
 | |
|     return false;
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
 | |
|   ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
 | |
| 
 | |
|   ScriptInterpreterInstances::iterator pos, end = instances.end();
 | |
|   for (pos = instances.begin(); pos != end; ++pos) {
 | |
|     if (pos->create_callback != create_callback)
 | |
|       continue;
 | |
| 
 | |
|     instances.erase(pos);
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| ScriptInterpreterCreateInstance
 | |
| PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
 | |
|   ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| lldb::ScriptInterpreterSP PluginManager::GetScriptInterpreterForLanguage(
 | |
|     lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex());
 | |
|   ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
 | |
| 
 | |
|   ScriptInterpreterInstances::iterator pos, end = instances.end();
 | |
|   ScriptInterpreterCreateInstance none_instance = nullptr;
 | |
|   for (pos = instances.begin(); pos != end; ++pos) {
 | |
|     if (pos->language == lldb::eScriptLanguageNone)
 | |
|       none_instance = pos->create_callback;
 | |
| 
 | |
|     if (script_lang == pos->language)
 | |
|       return pos->create_callback(interpreter);
 | |
|   }
 | |
| 
 | |
|   // If we didn't find one, return the ScriptInterpreter for the null language.
 | |
|   assert(none_instance != nullptr);
 | |
|   return none_instance(interpreter);
 | |
| }
 | |
| 
 | |
| #pragma mark -
 | |
| #pragma mark StructuredDataPlugin
 | |
| 
 | |
| // -----------------------------------------------------------------------------
 | |
| // StructuredDataPlugin
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| struct StructuredDataPluginInstance {
 | |
|   StructuredDataPluginInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr), filter_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   StructuredDataPluginCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
|   StructuredDataFilterLaunchInfo filter_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<StructuredDataPluginInstance> StructuredDataPluginInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetStructuredDataPluginMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static StructuredDataPluginInstances &GetStructuredDataPluginInstances() {
 | |
|   static StructuredDataPluginInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     StructuredDataPluginCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback,
 | |
|     StructuredDataFilterLaunchInfo filter_callback) {
 | |
|   if (create_callback) {
 | |
|     StructuredDataPluginInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     instance.filter_callback = filter_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
 | |
|     GetStructuredDataPluginInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     StructuredDataPluginCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
 | |
|     StructuredDataPluginInstances &instances =
 | |
|         GetStructuredDataPluginInstances();
 | |
| 
 | |
|     StructuredDataPluginInstances::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;
 | |
| }
 | |
| 
 | |
| StructuredDataPluginCreateInstance
 | |
| PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
 | |
|   StructuredDataPluginInstances &instances = GetStructuredDataPluginInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| StructuredDataPluginCreateInstance
 | |
| PluginManager::GetStructuredDataPluginCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
 | |
|     StructuredDataPluginInstances &instances =
 | |
|         GetStructuredDataPluginInstances();
 | |
| 
 | |
|     StructuredDataPluginInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| StructuredDataFilterLaunchInfo
 | |
| PluginManager::GetStructuredDataFilterCallbackAtIndex(
 | |
|     uint32_t idx, bool &iteration_complete) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
 | |
|   StructuredDataPluginInstances &instances = GetStructuredDataPluginInstances();
 | |
|   if (idx < instances.size()) {
 | |
|     iteration_complete = false;
 | |
|     return instances[idx].filter_callback;
 | |
|   } else {
 | |
|     iteration_complete = true;
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark SymbolFile
 | |
| 
 | |
| struct SymbolFileInstance {
 | |
|   SymbolFileInstance()
 | |
|       : name(), description(), create_callback(nullptr),
 | |
|         debugger_init_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   SymbolFileCreateInstance create_callback;
 | |
|   DebuggerInitializeCallback debugger_init_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<SymbolFileInstance> SymbolFileInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetSymbolFileMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static SymbolFileInstances &GetSymbolFileInstances() {
 | |
|   static SymbolFileInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     SymbolFileCreateInstance create_callback,
 | |
|     DebuggerInitializeCallback debugger_init_callback) {
 | |
|   if (create_callback) {
 | |
|     SymbolFileInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.debugger_init_callback = debugger_init_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
 | |
|     GetSymbolFileInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(SymbolFileCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
 | |
|     SymbolFileInstances &instances = GetSymbolFileInstances();
 | |
| 
 | |
|     SymbolFileInstances::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;
 | |
| }
 | |
| 
 | |
| SymbolFileCreateInstance
 | |
| PluginManager::GetSymbolFileCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
 | |
|   SymbolFileInstances &instances = GetSymbolFileInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| SymbolFileCreateInstance
 | |
| PluginManager::GetSymbolFileCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
 | |
|     SymbolFileInstances &instances = GetSymbolFileInstances();
 | |
| 
 | |
|     SymbolFileInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark SymbolVendor
 | |
| 
 | |
| struct SymbolVendorInstance {
 | |
|   SymbolVendorInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   SymbolVendorCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetSymbolVendorMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static SymbolVendorInstances &GetSymbolVendorInstances() {
 | |
|   static SymbolVendorInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(const ConstString &name,
 | |
|                                    const char *description,
 | |
|                                    SymbolVendorCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     SymbolVendorInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
 | |
|     GetSymbolVendorInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     SymbolVendorCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
 | |
|     SymbolVendorInstances &instances = GetSymbolVendorInstances();
 | |
| 
 | |
|     SymbolVendorInstances::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;
 | |
| }
 | |
| 
 | |
| SymbolVendorCreateInstance
 | |
| PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
 | |
|   SymbolVendorInstances &instances = GetSymbolVendorInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| SymbolVendorCreateInstance
 | |
| PluginManager::GetSymbolVendorCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex());
 | |
|     SymbolVendorInstances &instances = GetSymbolVendorInstances();
 | |
| 
 | |
|     SymbolVendorInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark UnwindAssembly
 | |
| 
 | |
| struct UnwindAssemblyInstance {
 | |
|   UnwindAssemblyInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   UnwindAssemblyCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetUnwindAssemblyMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static UnwindAssemblyInstances &GetUnwindAssemblyInstances() {
 | |
|   static UnwindAssemblyInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     UnwindAssemblyCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     UnwindAssemblyInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
 | |
|     GetUnwindAssemblyInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     UnwindAssemblyCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
 | |
|     UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances();
 | |
| 
 | |
|     UnwindAssemblyInstances::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;
 | |
| }
 | |
| 
 | |
| UnwindAssemblyCreateInstance
 | |
| PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
 | |
|   UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| UnwindAssemblyCreateInstance
 | |
| PluginManager::GetUnwindAssemblyCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex());
 | |
|     UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances();
 | |
| 
 | |
|     UnwindAssemblyInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark MemoryHistory
 | |
| 
 | |
| struct MemoryHistoryInstance {
 | |
|   MemoryHistoryInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   MemoryHistoryCreateInstance create_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetMemoryHistoryMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static MemoryHistoryInstances &GetMemoryHistoryInstances() {
 | |
|   static MemoryHistoryInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     MemoryHistoryCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     MemoryHistoryInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
 | |
|     GetMemoryHistoryInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     MemoryHistoryCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
 | |
|     MemoryHistoryInstances &instances = GetMemoryHistoryInstances();
 | |
| 
 | |
|     MemoryHistoryInstances::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;
 | |
| }
 | |
| 
 | |
| MemoryHistoryCreateInstance
 | |
| PluginManager::GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
 | |
|   MemoryHistoryInstances &instances = GetMemoryHistoryInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| MemoryHistoryCreateInstance
 | |
| PluginManager::GetMemoryHistoryCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex());
 | |
|     MemoryHistoryInstances &instances = GetMemoryHistoryInstances();
 | |
| 
 | |
|     MemoryHistoryInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark InstrumentationRuntime
 | |
| 
 | |
| struct InstrumentationRuntimeInstance {
 | |
|   InstrumentationRuntimeInstance()
 | |
|       : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   InstrumentationRuntimeCreateInstance create_callback;
 | |
|   InstrumentationRuntimeGetType get_type_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<InstrumentationRuntimeInstance>
 | |
|     InstrumentationRuntimeInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetInstrumentationRuntimeMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static InstrumentationRuntimeInstances &GetInstrumentationRuntimeInstances() {
 | |
|   static InstrumentationRuntimeInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     InstrumentationRuntimeCreateInstance create_callback,
 | |
|     InstrumentationRuntimeGetType get_type_callback) {
 | |
|   if (create_callback) {
 | |
|     InstrumentationRuntimeInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.get_type_callback = get_type_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(
 | |
|         GetInstrumentationRuntimeMutex());
 | |
|     GetInstrumentationRuntimeInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(
 | |
|     InstrumentationRuntimeCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(
 | |
|         GetInstrumentationRuntimeMutex());
 | |
|     InstrumentationRuntimeInstances &instances =
 | |
|         GetInstrumentationRuntimeInstances();
 | |
| 
 | |
|     InstrumentationRuntimeInstances::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;
 | |
| }
 | |
| 
 | |
| InstrumentationRuntimeGetType
 | |
| PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex());
 | |
|   InstrumentationRuntimeInstances &instances =
 | |
|       GetInstrumentationRuntimeInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].get_type_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| InstrumentationRuntimeCreateInstance
 | |
| PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex());
 | |
|   InstrumentationRuntimeInstances &instances =
 | |
|       GetInstrumentationRuntimeInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| InstrumentationRuntimeCreateInstance
 | |
| PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(
 | |
|         GetInstrumentationRuntimeMutex());
 | |
|     InstrumentationRuntimeInstances &instances =
 | |
|         GetInstrumentationRuntimeInstances();
 | |
| 
 | |
|     InstrumentationRuntimeInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark TypeSystem
 | |
| 
 | |
| struct TypeSystemInstance {
 | |
|   TypeSystemInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   TypeSystemCreateInstance create_callback;
 | |
|   TypeSystemEnumerateSupportedLanguages enumerate_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<TypeSystemInstance> TypeSystemInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetTypeSystemMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static TypeSystemInstances &GetTypeSystemInstances() {
 | |
|   static TypeSystemInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(const ConstString &name,
 | |
|                                    const char *description,
 | |
|                                    TypeSystemCreateInstance create_callback,
 | |
|                                    TypeSystemEnumerateSupportedLanguages
 | |
|                                        enumerate_supported_languages_callback) {
 | |
|   if (create_callback) {
 | |
|     TypeSystemInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.enumerate_callback = enumerate_supported_languages_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
 | |
|     GetTypeSystemInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(TypeSystemCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
 | |
|     TypeSystemInstances &instances = GetTypeSystemInstances();
 | |
| 
 | |
|     TypeSystemInstances::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;
 | |
| }
 | |
| 
 | |
| TypeSystemCreateInstance
 | |
| PluginManager::GetTypeSystemCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
 | |
|   TypeSystemInstances &instances = GetTypeSystemInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| TypeSystemCreateInstance
 | |
| PluginManager::GetTypeSystemCreateCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
 | |
|     TypeSystemInstances &instances = GetTypeSystemInstances();
 | |
| 
 | |
|     TypeSystemInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| TypeSystemEnumerateSupportedLanguages
 | |
| PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(
 | |
|     uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
 | |
|   TypeSystemInstances &instances = GetTypeSystemInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].enumerate_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| TypeSystemEnumerateSupportedLanguages
 | |
| PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex());
 | |
|     TypeSystemInstances &instances = GetTypeSystemInstances();
 | |
| 
 | |
|     TypeSystemInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->enumerate_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark REPL
 | |
| 
 | |
| struct REPLInstance {
 | |
|   REPLInstance() : name(), description(), create_callback(nullptr) {}
 | |
| 
 | |
|   ConstString name;
 | |
|   std::string description;
 | |
|   REPLCreateInstance create_callback;
 | |
|   REPLEnumerateSupportedLanguages enumerate_languages_callback;
 | |
| };
 | |
| 
 | |
| typedef std::vector<REPLInstance> REPLInstances;
 | |
| 
 | |
| static std::recursive_mutex &GetREPLMutex() {
 | |
|   static std::recursive_mutex g_instances_mutex;
 | |
|   return g_instances_mutex;
 | |
| }
 | |
| 
 | |
| static REPLInstances &GetREPLInstances() {
 | |
|   static REPLInstances g_instances;
 | |
|   return g_instances;
 | |
| }
 | |
| 
 | |
| bool PluginManager::RegisterPlugin(
 | |
|     const ConstString &name, const char *description,
 | |
|     REPLCreateInstance create_callback,
 | |
|     REPLEnumerateSupportedLanguages enumerate_languages_callback) {
 | |
|   if (create_callback) {
 | |
|     REPLInstance instance;
 | |
|     assert((bool)name);
 | |
|     instance.name = name;
 | |
|     if (description && description[0])
 | |
|       instance.description = description;
 | |
|     instance.create_callback = create_callback;
 | |
|     instance.enumerate_languages_callback = enumerate_languages_callback;
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
 | |
|     GetREPLInstances().push_back(instance);
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PluginManager::UnregisterPlugin(REPLCreateInstance create_callback) {
 | |
|   if (create_callback) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
 | |
|     REPLInstances &instances = GetREPLInstances();
 | |
| 
 | |
|     REPLInstances::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;
 | |
| }
 | |
| 
 | |
| REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
 | |
|   REPLInstances &instances = GetREPLInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].create_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| REPLCreateInstance
 | |
| PluginManager::GetREPLCreateCallbackForPluginName(const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
 | |
|     REPLInstances &instances = GetREPLInstances();
 | |
| 
 | |
|     REPLInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->create_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| REPLEnumerateSupportedLanguages
 | |
| PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(uint32_t idx) {
 | |
|   std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
 | |
|   REPLInstances &instances = GetREPLInstances();
 | |
|   if (idx < instances.size())
 | |
|     return instances[idx].enumerate_languages_callback;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| REPLEnumerateSupportedLanguages
 | |
| PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName(
 | |
|     const ConstString &name) {
 | |
|   if (name) {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetREPLMutex());
 | |
|     REPLInstances &instances = GetREPLInstances();
 | |
| 
 | |
|     REPLInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (name == pos->name)
 | |
|         return pos->enumerate_languages_callback;
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| #pragma mark PluginManager
 | |
| 
 | |
| void PluginManager::DebuggerInitialize(Debugger &debugger) {
 | |
|   // Initialize the DynamicLoader plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex());
 | |
|     DynamicLoaderInstances &instances = GetDynamicLoaderInstances();
 | |
| 
 | |
|     DynamicLoaderInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (pos->debugger_init_callback)
 | |
|         pos->debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Initialize the JITLoader plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex());
 | |
|     JITLoaderInstances &instances = GetJITLoaderInstances();
 | |
| 
 | |
|     JITLoaderInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (pos->debugger_init_callback)
 | |
|         pos->debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Initialize the Platform plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex());
 | |
|     PlatformInstances &instances = GetPlatformInstances();
 | |
| 
 | |
|     PlatformInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (pos->debugger_init_callback)
 | |
|         pos->debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Initialize the Process plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetProcessMutex());
 | |
|     ProcessInstances &instances = GetProcessInstances();
 | |
| 
 | |
|     ProcessInstances::iterator pos, end = instances.end();
 | |
|     for (pos = instances.begin(); pos != end; ++pos) {
 | |
|       if (pos->debugger_init_callback)
 | |
|         pos->debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Initialize the SymbolFile plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex());
 | |
|     for (auto &sym_file : GetSymbolFileInstances()) {
 | |
|       if (sym_file.debugger_init_callback)
 | |
|         sym_file.debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Initialize the OperatingSystem plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex());
 | |
|     for (auto &os : GetOperatingSystemInstances()) {
 | |
|       if (os.debugger_init_callback)
 | |
|         os.debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Initialize the StructuredDataPlugin plugins
 | |
|   {
 | |
|     std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex());
 | |
|     for (auto &plugin : GetStructuredDataPluginInstances()) {
 | |
|       if (plugin.debugger_init_callback)
 | |
|         plugin.debugger_init_callback(debugger);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| // This is the preferred new way to register plugin specific settings.  e.g.
 | |
| // This will put a plugin's settings under e.g.
 | |
| // "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME".
 | |
| static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPlugins(
 | |
|     Debugger &debugger, const ConstString &plugin_type_name,
 | |
|     const ConstString &plugin_type_desc, bool can_create) {
 | |
|   lldb::OptionValuePropertiesSP parent_properties_sp(
 | |
|       debugger.GetValueProperties());
 | |
|   if (parent_properties_sp) {
 | |
|     static ConstString g_property_name("plugin");
 | |
| 
 | |
|     OptionValuePropertiesSP plugin_properties_sp =
 | |
|         parent_properties_sp->GetSubProperty(nullptr, g_property_name);
 | |
|     if (!plugin_properties_sp && can_create) {
 | |
|       plugin_properties_sp =
 | |
|           std::make_shared<OptionValueProperties>(g_property_name);
 | |
|       parent_properties_sp->AppendProperty(
 | |
|           g_property_name, ConstString("Settings specify to plugins."), true,
 | |
|           plugin_properties_sp);
 | |
|     }
 | |
| 
 | |
|     if (plugin_properties_sp) {
 | |
|       lldb::OptionValuePropertiesSP plugin_type_properties_sp =
 | |
|           plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name);
 | |
|       if (!plugin_type_properties_sp && can_create) {
 | |
|         plugin_type_properties_sp =
 | |
|             std::make_shared<OptionValueProperties>(plugin_type_name);
 | |
|         plugin_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
 | |
|                                              true, plugin_type_properties_sp);
 | |
|       }
 | |
|       return plugin_type_properties_sp;
 | |
|     }
 | |
|   }
 | |
|   return lldb::OptionValuePropertiesSP();
 | |
| }
 | |
| 
 | |
| // This is deprecated way to register plugin specific settings.  e.g.
 | |
| // "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME"
 | |
| // and Platform generic settings would be under "platform.SETTINGNAME".
 | |
| static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle(
 | |
|     Debugger &debugger, const ConstString &plugin_type_name,
 | |
|     const ConstString &plugin_type_desc, bool can_create) {
 | |
|   static ConstString g_property_name("plugin");
 | |
|   lldb::OptionValuePropertiesSP parent_properties_sp(
 | |
|       debugger.GetValueProperties());
 | |
|   if (parent_properties_sp) {
 | |
|     OptionValuePropertiesSP plugin_properties_sp =
 | |
|         parent_properties_sp->GetSubProperty(nullptr, plugin_type_name);
 | |
|     if (!plugin_properties_sp && can_create) {
 | |
|       plugin_properties_sp =
 | |
|           std::make_shared<OptionValueProperties>(plugin_type_name);
 | |
|       parent_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
 | |
|                                            true, plugin_properties_sp);
 | |
|     }
 | |
| 
 | |
|     if (plugin_properties_sp) {
 | |
|       lldb::OptionValuePropertiesSP plugin_type_properties_sp =
 | |
|           plugin_properties_sp->GetSubProperty(nullptr, g_property_name);
 | |
|       if (!plugin_type_properties_sp && can_create) {
 | |
|         plugin_type_properties_sp =
 | |
|             std::make_shared<OptionValueProperties>(g_property_name);
 | |
|         plugin_properties_sp->AppendProperty(
 | |
|             g_property_name, ConstString("Settings specific to plugins"), true,
 | |
|             plugin_type_properties_sp);
 | |
|       }
 | |
|       return plugin_type_properties_sp;
 | |
|     }
 | |
|   }
 | |
|   return lldb::OptionValuePropertiesSP();
 | |
| }
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| typedef lldb::OptionValuePropertiesSP
 | |
| GetDebuggerPropertyForPluginsPtr(Debugger &, const ConstString &,
 | |
|                                  const ConstString &, bool can_create);
 | |
| 
 | |
| lldb::OptionValuePropertiesSP
 | |
| GetSettingForPlugin(Debugger &debugger, const ConstString &setting_name,
 | |
|                     const ConstString &plugin_type_name,
 | |
|                     GetDebuggerPropertyForPluginsPtr get_debugger_property =
 | |
|                         GetDebuggerPropertyForPlugins) {
 | |
|   lldb::OptionValuePropertiesSP properties_sp;
 | |
|   lldb::OptionValuePropertiesSP plugin_type_properties_sp(get_debugger_property(
 | |
|       debugger, plugin_type_name,
 | |
|       ConstString(), // not creating to so we don't need the description
 | |
|       false));
 | |
|   if (plugin_type_properties_sp)
 | |
|     properties_sp =
 | |
|         plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
 | |
|   return properties_sp;
 | |
| }
 | |
| 
 | |
| bool CreateSettingForPlugin(
 | |
|     Debugger &debugger, const ConstString &plugin_type_name,
 | |
|     const ConstString &plugin_type_desc,
 | |
|     const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property,
 | |
|     GetDebuggerPropertyForPluginsPtr get_debugger_property =
 | |
|         GetDebuggerPropertyForPlugins) {
 | |
|   if (properties_sp) {
 | |
|     lldb::OptionValuePropertiesSP plugin_type_properties_sp(
 | |
|         get_debugger_property(debugger, plugin_type_name, plugin_type_desc,
 | |
|                               true));
 | |
|     if (plugin_type_properties_sp) {
 | |
|       plugin_type_properties_sp->AppendProperty(properties_sp->GetName(),
 | |
|                                                 description, is_global_property,
 | |
|                                                 properties_sp);
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| const char *kDynamicLoaderPluginName("dynamic-loader");
 | |
| const char *kPlatformPluginName("platform");
 | |
| const char *kProcessPluginName("process");
 | |
| const char *kSymbolFilePluginName("symbol-file");
 | |
| const char *kJITLoaderPluginName("jit-loader");
 | |
| const char *kStructuredDataPluginName("structured-data");
 | |
| 
 | |
| } // anonymous namespace
 | |
| 
 | |
| lldb::OptionValuePropertiesSP PluginManager::GetSettingForDynamicLoaderPlugin(
 | |
|     Debugger &debugger, const ConstString &setting_name) {
 | |
|   return GetSettingForPlugin(debugger, setting_name,
 | |
|                              ConstString(kDynamicLoaderPluginName));
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForDynamicLoaderPlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   return CreateSettingForPlugin(
 | |
|       debugger, ConstString(kDynamicLoaderPluginName),
 | |
|       ConstString("Settings for dynamic loader plug-ins"), properties_sp,
 | |
|       description, is_global_property);
 | |
| }
 | |
| 
 | |
| lldb::OptionValuePropertiesSP
 | |
| PluginManager::GetSettingForPlatformPlugin(Debugger &debugger,
 | |
|                                            const ConstString &setting_name) {
 | |
|   return GetSettingForPlugin(debugger, setting_name,
 | |
|                              ConstString(kPlatformPluginName),
 | |
|                              GetDebuggerPropertyForPluginsOldStyle);
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForPlatformPlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   return CreateSettingForPlugin(debugger, ConstString(kPlatformPluginName),
 | |
|                                 ConstString("Settings for platform plug-ins"),
 | |
|                                 properties_sp, description, is_global_property,
 | |
|                                 GetDebuggerPropertyForPluginsOldStyle);
 | |
| }
 | |
| 
 | |
| lldb::OptionValuePropertiesSP
 | |
| PluginManager::GetSettingForProcessPlugin(Debugger &debugger,
 | |
|                                           const ConstString &setting_name) {
 | |
|   return GetSettingForPlugin(debugger, setting_name,
 | |
|                              ConstString(kProcessPluginName));
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForProcessPlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   return CreateSettingForPlugin(debugger, ConstString(kProcessPluginName),
 | |
|                                 ConstString("Settings for process plug-ins"),
 | |
|                                 properties_sp, description, is_global_property);
 | |
| }
 | |
| 
 | |
| lldb::OptionValuePropertiesSP
 | |
| PluginManager::GetSettingForSymbolFilePlugin(Debugger &debugger,
 | |
|                                              const ConstString &setting_name) {
 | |
|   return GetSettingForPlugin(debugger, setting_name,
 | |
|                              ConstString(kSymbolFilePluginName));
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForSymbolFilePlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   return CreateSettingForPlugin(
 | |
|       debugger, ConstString(kSymbolFilePluginName),
 | |
|       ConstString("Settings for symbol file plug-ins"), properties_sp,
 | |
|       description, is_global_property);
 | |
| }
 | |
| 
 | |
| lldb::OptionValuePropertiesSP
 | |
| PluginManager::GetSettingForJITLoaderPlugin(Debugger &debugger,
 | |
|                                             const ConstString &setting_name) {
 | |
|   return GetSettingForPlugin(debugger, setting_name,
 | |
|                              ConstString(kJITLoaderPluginName));
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForJITLoaderPlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   return CreateSettingForPlugin(debugger, ConstString(kJITLoaderPluginName),
 | |
|                                 ConstString("Settings for JIT loader plug-ins"),
 | |
|                                 properties_sp, description, is_global_property);
 | |
| }
 | |
| 
 | |
| static const char *kOperatingSystemPluginName("os");
 | |
| 
 | |
| lldb::OptionValuePropertiesSP PluginManager::GetSettingForOperatingSystemPlugin(
 | |
|     Debugger &debugger, const ConstString &setting_name) {
 | |
|   lldb::OptionValuePropertiesSP properties_sp;
 | |
|   lldb::OptionValuePropertiesSP plugin_type_properties_sp(
 | |
|       GetDebuggerPropertyForPlugins(
 | |
|           debugger, ConstString(kOperatingSystemPluginName),
 | |
|           ConstString(), // not creating to so we don't need the description
 | |
|           false));
 | |
|   if (plugin_type_properties_sp)
 | |
|     properties_sp =
 | |
|         plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
 | |
|   return properties_sp;
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForOperatingSystemPlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   if (properties_sp) {
 | |
|     lldb::OptionValuePropertiesSP plugin_type_properties_sp(
 | |
|         GetDebuggerPropertyForPlugins(
 | |
|             debugger, ConstString(kOperatingSystemPluginName),
 | |
|             ConstString("Settings for operating system plug-ins"), true));
 | |
|     if (plugin_type_properties_sp) {
 | |
|       plugin_type_properties_sp->AppendProperty(properties_sp->GetName(),
 | |
|                                                 description, is_global_property,
 | |
|                                                 properties_sp);
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| lldb::OptionValuePropertiesSP PluginManager::GetSettingForStructuredDataPlugin(
 | |
|     Debugger &debugger, const ConstString &setting_name) {
 | |
|   return GetSettingForPlugin(debugger, setting_name,
 | |
|                              ConstString(kStructuredDataPluginName));
 | |
| }
 | |
| 
 | |
| bool PluginManager::CreateSettingForStructuredDataPlugin(
 | |
|     Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
 | |
|     const ConstString &description, bool is_global_property) {
 | |
|   return CreateSettingForPlugin(
 | |
|       debugger, ConstString(kStructuredDataPluginName),
 | |
|       ConstString("Settings for structured data plug-ins"), properties_sp,
 | |
|       description, is_global_property);
 | |
| }
 |