aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Core/PluginManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Core/PluginManager.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Core/PluginManager.cpp2625
1 files changed, 2625 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Core/PluginManager.cpp b/contrib/llvm-project/lldb/source/Core/PluginManager.cpp
new file mode 100644
index 000000000000..24cadcd85bf5
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Core/PluginManager.cpp
@@ -0,0 +1,2625 @@
+//===-- PluginManager.cpp ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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(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(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(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(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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(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(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;
+ LanguageRuntimeGetExceptionPrecondition precondition_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(
+ ConstString name, const char *description,
+ LanguageRuntimeCreateInstance create_callback,
+ LanguageRuntimeGetCommandObject command_callback,
+ LanguageRuntimeGetExceptionPrecondition precondition_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;
+ instance.precondition_callback = precondition_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;
+}
+
+LanguageRuntimeGetExceptionPrecondition
+PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx) {
+ std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
+ LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
+ if (idx < instances.size())
+ return instances[idx].precondition_callback;
+ return nullptr;
+}
+
+LanguageRuntimeCreateInstance
+PluginManager::GetLanguageRuntimeCreateCallbackForPluginName(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(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(
+ 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(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(
+ 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,
+ Debugger &debugger) {
+ 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(debugger);
+ }
+
+ // If we didn't find one, return the ScriptInterpreter for the null language.
+ assert(none_instance != nullptr);
+ return none_instance(debugger);
+}
+
+#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(
+ 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(
+ 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(
+ 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(
+ 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(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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(
+ 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(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(
+ 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(
+ 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(
+ 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(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(
+ 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, ConstString plugin_type_name,
+ 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, ConstString plugin_type_name,
+ 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 &, ConstString ,
+ ConstString , bool can_create);
+
+lldb::OptionValuePropertiesSP
+GetSettingForPlugin(Debugger &debugger, ConstString setting_name,
+ 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, ConstString plugin_type_name,
+ ConstString plugin_type_desc,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ 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, ConstString setting_name) {
+ return GetSettingForPlugin(debugger, setting_name,
+ ConstString(kDynamicLoaderPluginName));
+}
+
+bool PluginManager::CreateSettingForDynamicLoaderPlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ 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,
+ ConstString setting_name) {
+ return GetSettingForPlugin(debugger, setting_name,
+ ConstString(kPlatformPluginName),
+ GetDebuggerPropertyForPluginsOldStyle);
+}
+
+bool PluginManager::CreateSettingForPlatformPlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ 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,
+ ConstString setting_name) {
+ return GetSettingForPlugin(debugger, setting_name,
+ ConstString(kProcessPluginName));
+}
+
+bool PluginManager::CreateSettingForProcessPlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ 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,
+ ConstString setting_name) {
+ return GetSettingForPlugin(debugger, setting_name,
+ ConstString(kSymbolFilePluginName));
+}
+
+bool PluginManager::CreateSettingForSymbolFilePlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ 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,
+ ConstString setting_name) {
+ return GetSettingForPlugin(debugger, setting_name,
+ ConstString(kJITLoaderPluginName));
+}
+
+bool PluginManager::CreateSettingForJITLoaderPlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ 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, 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,
+ 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, ConstString setting_name) {
+ return GetSettingForPlugin(debugger, setting_name,
+ ConstString(kStructuredDataPluginName));
+}
+
+bool PluginManager::CreateSettingForStructuredDataPlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ ConstString description, bool is_global_property) {
+ return CreateSettingForPlugin(
+ debugger, ConstString(kStructuredDataPluginName),
+ ConstString("Settings for structured data plug-ins"), properties_sp,
+ description, is_global_property);
+}