|  | //===-- 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/FileSystem.h" | 
|  | #include "lldb/Host/HostInfo.h" | 
|  | #include "lldb/Interpreter/OptionValueProperties.h" | 
|  | #include "lldb/Utility/ConstString.h" | 
|  | #include "lldb/Utility/FileSpec.h" | 
|  | #include "lldb/Utility/Status.h" | 
|  | #include "lldb/Utility/StringList.h" | 
|  |  | 
|  | #if defined(_WIN32) | 
|  | #include "lldb/Host/windows/PosixApi.h" | 
|  | #endif | 
|  |  | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/Support/DynamicLibrary.h" | 
|  | #include "llvm/Support/FileSystem.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <mutex> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include <assert.h> | 
|  |  | 
|  | 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 FileSystem::EnumerateDirectoryResult | 
|  | LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, | 
|  | llvm::StringRef path) { | 
|  | //    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(path); | 
|  | FileSystem::Instance().Resolve(plugin_file_spec); | 
|  |  | 
|  | if (PluginIsLoaded(plugin_file_spec)) | 
|  | return FileSystem::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 FileSystem::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 FileSystem::eEnumerateDirectoryResultEnter; | 
|  | } | 
|  |  | 
|  | return FileSystem::eEnumerateDirectoryResultNext; | 
|  | } | 
|  |  | 
|  | void PluginManager::Initialize() { | 
|  | #if 1 | 
|  | const bool find_directories = true; | 
|  | const bool find_files = true; | 
|  | const bool find_other = true; | 
|  | char dir_path[PATH_MAX]; | 
|  | if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) { | 
|  | if (FileSystem::Instance().Exists(dir_spec) && | 
|  | dir_spec.GetPath(dir_path, sizeof(dir_path))) { | 
|  | FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, | 
|  | find_files, find_other, | 
|  | LoadPluginCallback, nullptr); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) { | 
|  | if (FileSystem::Instance().Exists(dir_spec) && | 
|  | dir_spec.GetPath(dir_path, sizeof(dir_path))) { | 
|  | FileSystem::Instance().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 Architecture | 
|  |  | 
|  | struct ArchitectureInstance { | 
|  | ConstString name; | 
|  | std::string description; | 
|  | PluginManager::ArchitectureCreateInstance create_callback; | 
|  | }; | 
|  |  | 
|  | typedef std::vector<ArchitectureInstance> ArchitectureInstances; | 
|  |  | 
|  | static std::mutex &GetArchitectureMutex() { | 
|  | static std::mutex g_architecture_mutex; | 
|  | return g_architecture_mutex; | 
|  | } | 
|  |  | 
|  | static ArchitectureInstances &GetArchitectureInstances() { | 
|  | static ArchitectureInstances g_instances; | 
|  | return g_instances; | 
|  | } | 
|  |  | 
|  | void PluginManager::RegisterPlugin(const ConstString &name, | 
|  | llvm::StringRef description, | 
|  | ArchitectureCreateInstance create_callback) { | 
|  | std::lock_guard<std::mutex> guard(GetArchitectureMutex()); | 
|  | GetArchitectureInstances().push_back({name, description, create_callback}); | 
|  | } | 
|  |  | 
|  | void PluginManager::UnregisterPlugin( | 
|  | ArchitectureCreateInstance create_callback) { | 
|  | std::lock_guard<std::mutex> guard(GetArchitectureMutex()); | 
|  | auto &instances = GetArchitectureInstances(); | 
|  |  | 
|  | for (auto pos = instances.begin(), end = instances.end(); pos != end; ++pos) { | 
|  | if (pos->create_callback == create_callback) { | 
|  | instances.erase(pos); | 
|  | return; | 
|  | } | 
|  | } | 
|  | llvm_unreachable("Plugin not found"); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<Architecture> | 
|  | PluginManager::CreateArchitectureInstance(const ArchSpec &arch) { | 
|  | std::lock_guard<std::mutex> guard(GetArchitectureMutex()); | 
|  | for (const auto &instances : GetArchitectureInstances()) { | 
|  | if (auto plugin_up = instances.create_callback(arch)) | 
|  | return plugin_up; | 
|  | } | 
|  | 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); | 
|  | } |