| //===-- PluginManager.cpp -------------------------------------------------===// |
| // |
| // 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/Target/Process.h" |
| #include "lldb/Utility/ConstString.h" |
| #include "lldb/Utility/FileSpec.h" |
| #include "lldb/Utility/Status.h" |
| #include "lldb/Utility/StringList.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/DynamicLibrary.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <cassert> |
| #include <map> |
| #include <memory> |
| #include <mutex> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| #if defined(_WIN32) |
| #include "lldb/Host/windows/PosixApi.h" |
| #endif |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| typedef bool (*PluginInitCallback)(); |
| typedef void (*PluginTermCallback)(); |
| |
| struct PluginInfo { |
| PluginInfo() = default; |
| |
| llvm::sys::DynamicLibrary library; |
| PluginInitCallback plugin_init_callback = nullptr; |
| PluginTermCallback plugin_term_callback = nullptr; |
| }; |
| |
| 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>(VPtr); |
| } |
| |
| static FileSystem::EnumerateDirectoryResult |
| LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, |
| llvm::StringRef path) { |
| 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() { |
| 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); |
| } |
| } |
| } |
| |
| 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(); |
| } |
| |
| template <typename Callback> struct PluginInstance { |
| typedef Callback CallbackType; |
| |
| PluginInstance() = default; |
| PluginInstance(llvm::StringRef name, llvm::StringRef description, |
| Callback create_callback, |
| DebuggerInitializeCallback debugger_init_callback = nullptr) |
| : name(name), description(description), create_callback(create_callback), |
| debugger_init_callback(debugger_init_callback) {} |
| |
| llvm::StringRef name; |
| llvm::StringRef description; |
| Callback create_callback; |
| DebuggerInitializeCallback debugger_init_callback; |
| }; |
| |
| template <typename Instance> class PluginInstances { |
| public: |
| template <typename... Args> |
| bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, |
| typename Instance::CallbackType callback, |
| Args &&...args) { |
| if (!callback) |
| return false; |
| assert(!name.empty()); |
| Instance instance = |
| Instance(name, description, callback, std::forward<Args>(args)...); |
| m_instances.push_back(instance); |
| return false; |
| } |
| |
| bool UnregisterPlugin(typename Instance::CallbackType callback) { |
| if (!callback) |
| return false; |
| auto pos = m_instances.begin(); |
| auto end = m_instances.end(); |
| for (; pos != end; ++pos) { |
| if (pos->create_callback == callback) { |
| m_instances.erase(pos); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| typename Instance::CallbackType GetCallbackAtIndex(uint32_t idx) { |
| if (Instance *instance = GetInstanceAtIndex(idx)) |
| return instance->create_callback; |
| return nullptr; |
| } |
| |
| llvm::StringRef GetDescriptionAtIndex(uint32_t idx) { |
| if (Instance *instance = GetInstanceAtIndex(idx)) |
| return instance->description; |
| return ""; |
| } |
| |
| llvm::StringRef GetNameAtIndex(uint32_t idx) { |
| if (Instance *instance = GetInstanceAtIndex(idx)) |
| return instance->name; |
| return ""; |
| } |
| |
| typename Instance::CallbackType GetCallbackForName(llvm::StringRef name) { |
| if (name.empty()) |
| return nullptr; |
| for (auto &instance : m_instances) { |
| if (name == instance.name) |
| return instance.create_callback; |
| } |
| return nullptr; |
| } |
| |
| void PerformDebuggerCallback(Debugger &debugger) { |
| for (auto &instance : m_instances) { |
| if (instance.debugger_init_callback) |
| instance.debugger_init_callback(debugger); |
| } |
| } |
| |
| const std::vector<Instance> &GetInstances() const { return m_instances; } |
| std::vector<Instance> &GetInstances() { return m_instances; } |
| |
| Instance *GetInstanceAtIndex(uint32_t idx) { |
| if (idx < m_instances.size()) |
| return &m_instances[idx]; |
| return nullptr; |
| } |
| |
| private: |
| std::vector<Instance> m_instances; |
| }; |
| |
| #pragma mark ABI |
| |
| typedef PluginInstance<ABICreateInstance> ABIInstance; |
| typedef PluginInstances<ABIInstance> ABIInstances; |
| |
| static ABIInstances &GetABIInstances() { |
| static ABIInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin(llvm::StringRef name, |
| llvm::StringRef description, |
| ABICreateInstance create_callback) { |
| return GetABIInstances().RegisterPlugin(name, description, create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin(ABICreateInstance create_callback) { |
| return GetABIInstances().UnregisterPlugin(create_callback); |
| } |
| |
| ABICreateInstance PluginManager::GetABICreateCallbackAtIndex(uint32_t idx) { |
| return GetABIInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark Architecture |
| |
| typedef PluginInstance<ArchitectureCreateInstance> ArchitectureInstance; |
| typedef std::vector<ArchitectureInstance> ArchitectureInstances; |
| |
| static ArchitectureInstances &GetArchitectureInstances() { |
| static ArchitectureInstances g_instances; |
| return g_instances; |
| } |
| |
| void PluginManager::RegisterPlugin(llvm::StringRef name, |
| llvm::StringRef description, |
| ArchitectureCreateInstance create_callback) { |
| GetArchitectureInstances().push_back({name, description, create_callback}); |
| } |
| |
| void PluginManager::UnregisterPlugin( |
| ArchitectureCreateInstance create_callback) { |
| 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) { |
| for (const auto &instances : GetArchitectureInstances()) { |
| if (auto plugin_up = instances.create_callback(arch)) |
| return plugin_up; |
| } |
| return nullptr; |
| } |
| |
| #pragma mark Disassembler |
| |
| typedef PluginInstance<DisassemblerCreateInstance> DisassemblerInstance; |
| typedef PluginInstances<DisassemblerInstance> DisassemblerInstances; |
| |
| static DisassemblerInstances &GetDisassemblerInstances() { |
| static DisassemblerInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin(llvm::StringRef name, |
| llvm::StringRef description, |
| DisassemblerCreateInstance create_callback) { |
| return GetDisassemblerInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| DisassemblerCreateInstance create_callback) { |
| return GetDisassemblerInstances().UnregisterPlugin(create_callback); |
| } |
| |
| DisassemblerCreateInstance |
| PluginManager::GetDisassemblerCreateCallbackAtIndex(uint32_t idx) { |
| return GetDisassemblerInstances().GetCallbackAtIndex(idx); |
| } |
| |
| DisassemblerCreateInstance |
| PluginManager::GetDisassemblerCreateCallbackForPluginName( |
| llvm::StringRef name) { |
| return GetDisassemblerInstances().GetCallbackForName(name); |
| } |
| |
| #pragma mark DynamicLoader |
| |
| typedef PluginInstance<DynamicLoaderCreateInstance> DynamicLoaderInstance; |
| typedef PluginInstances<DynamicLoaderInstance> DynamicLoaderInstances; |
| |
| static DynamicLoaderInstances &GetDynamicLoaderInstances() { |
| static DynamicLoaderInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| DynamicLoaderCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback) { |
| return GetDynamicLoaderInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| DynamicLoaderCreateInstance create_callback) { |
| return GetDynamicLoaderInstances().UnregisterPlugin(create_callback); |
| } |
| |
| DynamicLoaderCreateInstance |
| PluginManager::GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx) { |
| return GetDynamicLoaderInstances().GetCallbackAtIndex(idx); |
| } |
| |
| DynamicLoaderCreateInstance |
| PluginManager::GetDynamicLoaderCreateCallbackForPluginName( |
| llvm::StringRef name) { |
| return GetDynamicLoaderInstances().GetCallbackForName(name); |
| } |
| |
| #pragma mark JITLoader |
| |
| typedef PluginInstance<JITLoaderCreateInstance> JITLoaderInstance; |
| typedef PluginInstances<JITLoaderInstance> JITLoaderInstances; |
| |
| static JITLoaderInstances &GetJITLoaderInstances() { |
| static JITLoaderInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| JITLoaderCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback) { |
| return GetJITLoaderInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin(JITLoaderCreateInstance create_callback) { |
| return GetJITLoaderInstances().UnregisterPlugin(create_callback); |
| } |
| |
| JITLoaderCreateInstance |
| PluginManager::GetJITLoaderCreateCallbackAtIndex(uint32_t idx) { |
| return GetJITLoaderInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark EmulateInstruction |
| |
| typedef PluginInstance<EmulateInstructionCreateInstance> |
| EmulateInstructionInstance; |
| typedef PluginInstances<EmulateInstructionInstance> EmulateInstructionInstances; |
| |
| static EmulateInstructionInstances &GetEmulateInstructionInstances() { |
| static EmulateInstructionInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| EmulateInstructionCreateInstance create_callback) { |
| return GetEmulateInstructionInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| EmulateInstructionCreateInstance create_callback) { |
| return GetEmulateInstructionInstances().UnregisterPlugin(create_callback); |
| } |
| |
| EmulateInstructionCreateInstance |
| PluginManager::GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx) { |
| return GetEmulateInstructionInstances().GetCallbackAtIndex(idx); |
| } |
| |
| EmulateInstructionCreateInstance |
| PluginManager::GetEmulateInstructionCreateCallbackForPluginName( |
| llvm::StringRef name) { |
| return GetEmulateInstructionInstances().GetCallbackForName(name); |
| } |
| |
| #pragma mark OperatingSystem |
| |
| typedef PluginInstance<OperatingSystemCreateInstance> OperatingSystemInstance; |
| typedef PluginInstances<OperatingSystemInstance> OperatingSystemInstances; |
| |
| static OperatingSystemInstances &GetOperatingSystemInstances() { |
| static OperatingSystemInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| OperatingSystemCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback) { |
| return GetOperatingSystemInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| OperatingSystemCreateInstance create_callback) { |
| return GetOperatingSystemInstances().UnregisterPlugin(create_callback); |
| } |
| |
| OperatingSystemCreateInstance |
| PluginManager::GetOperatingSystemCreateCallbackAtIndex(uint32_t idx) { |
| return GetOperatingSystemInstances().GetCallbackAtIndex(idx); |
| } |
| |
| OperatingSystemCreateInstance |
| PluginManager::GetOperatingSystemCreateCallbackForPluginName( |
| llvm::StringRef name) { |
| return GetOperatingSystemInstances().GetCallbackForName(name); |
| } |
| |
| #pragma mark Language |
| |
| typedef PluginInstance<LanguageCreateInstance> LanguageInstance; |
| typedef PluginInstances<LanguageInstance> LanguageInstances; |
| |
| static LanguageInstances &GetLanguageInstances() { |
| static LanguageInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin(llvm::StringRef name, |
| llvm::StringRef description, |
| LanguageCreateInstance create_callback) { |
| return GetLanguageInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin(LanguageCreateInstance create_callback) { |
| return GetLanguageInstances().UnregisterPlugin(create_callback); |
| } |
| |
| LanguageCreateInstance |
| PluginManager::GetLanguageCreateCallbackAtIndex(uint32_t idx) { |
| return GetLanguageInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark LanguageRuntime |
| |
| struct LanguageRuntimeInstance |
| : public PluginInstance<LanguageRuntimeCreateInstance> { |
| LanguageRuntimeInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| DebuggerInitializeCallback debugger_init_callback, |
| LanguageRuntimeGetCommandObject command_callback, |
| LanguageRuntimeGetExceptionPrecondition precondition_callback) |
| : PluginInstance<LanguageRuntimeCreateInstance>( |
| name, description, create_callback, debugger_init_callback), |
| command_callback(command_callback), |
| precondition_callback(precondition_callback) {} |
| |
| LanguageRuntimeGetCommandObject command_callback; |
| LanguageRuntimeGetExceptionPrecondition precondition_callback; |
| }; |
| |
| typedef PluginInstances<LanguageRuntimeInstance> LanguageRuntimeInstances; |
| |
| static LanguageRuntimeInstances &GetLanguageRuntimeInstances() { |
| static LanguageRuntimeInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| LanguageRuntimeCreateInstance create_callback, |
| LanguageRuntimeGetCommandObject command_callback, |
| LanguageRuntimeGetExceptionPrecondition precondition_callback) { |
| return GetLanguageRuntimeInstances().RegisterPlugin( |
| name, description, create_callback, nullptr, command_callback, |
| precondition_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| LanguageRuntimeCreateInstance create_callback) { |
| return GetLanguageRuntimeInstances().UnregisterPlugin(create_callback); |
| } |
| |
| LanguageRuntimeCreateInstance |
| PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(uint32_t idx) { |
| return GetLanguageRuntimeInstances().GetCallbackAtIndex(idx); |
| } |
| |
| LanguageRuntimeGetCommandObject |
| PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx) { |
| const auto &instances = GetLanguageRuntimeInstances().GetInstances(); |
| if (idx < instances.size()) |
| return instances[idx].command_callback; |
| return nullptr; |
| } |
| |
| LanguageRuntimeGetExceptionPrecondition |
| PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx) { |
| const auto &instances = GetLanguageRuntimeInstances().GetInstances(); |
| if (idx < instances.size()) |
| return instances[idx].precondition_callback; |
| return nullptr; |
| } |
| |
| #pragma mark SystemRuntime |
| |
| typedef PluginInstance<SystemRuntimeCreateInstance> SystemRuntimeInstance; |
| typedef PluginInstances<SystemRuntimeInstance> SystemRuntimeInstances; |
| |
| static SystemRuntimeInstances &GetSystemRuntimeInstances() { |
| static SystemRuntimeInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| SystemRuntimeCreateInstance create_callback) { |
| return GetSystemRuntimeInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| SystemRuntimeCreateInstance create_callback) { |
| return GetSystemRuntimeInstances().UnregisterPlugin(create_callback); |
| } |
| |
| SystemRuntimeCreateInstance |
| PluginManager::GetSystemRuntimeCreateCallbackAtIndex(uint32_t idx) { |
| return GetSystemRuntimeInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark ObjectFile |
| |
| struct ObjectFileInstance : public PluginInstance<ObjectFileCreateInstance> { |
| ObjectFileInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| ObjectFileCreateMemoryInstance create_memory_callback, |
| ObjectFileGetModuleSpecifications get_module_specifications, |
| ObjectFileSaveCore save_core) |
| : PluginInstance<ObjectFileCreateInstance>(name, description, |
| create_callback), |
| create_memory_callback(create_memory_callback), |
| get_module_specifications(get_module_specifications), |
| save_core(save_core) {} |
| |
| ObjectFileCreateMemoryInstance create_memory_callback; |
| ObjectFileGetModuleSpecifications get_module_specifications; |
| ObjectFileSaveCore save_core; |
| }; |
| typedef PluginInstances<ObjectFileInstance> ObjectFileInstances; |
| |
| static ObjectFileInstances &GetObjectFileInstances() { |
| static ObjectFileInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| ObjectFileCreateInstance create_callback, |
| ObjectFileCreateMemoryInstance create_memory_callback, |
| ObjectFileGetModuleSpecifications get_module_specifications, |
| ObjectFileSaveCore save_core) { |
| return GetObjectFileInstances().RegisterPlugin( |
| name, description, create_callback, create_memory_callback, |
| get_module_specifications, save_core); |
| } |
| |
| bool PluginManager::UnregisterPlugin(ObjectFileCreateInstance create_callback) { |
| return GetObjectFileInstances().UnregisterPlugin(create_callback); |
| } |
| |
| ObjectFileCreateInstance |
| PluginManager::GetObjectFileCreateCallbackAtIndex(uint32_t idx) { |
| return GetObjectFileInstances().GetCallbackAtIndex(idx); |
| } |
| |
| ObjectFileCreateMemoryInstance |
| PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(uint32_t idx) { |
| const auto &instances = GetObjectFileInstances().GetInstances(); |
| if (idx < instances.size()) |
| return instances[idx].create_memory_callback; |
| return nullptr; |
| } |
| |
| ObjectFileGetModuleSpecifications |
| PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex( |
| uint32_t idx) { |
| const auto &instances = GetObjectFileInstances().GetInstances(); |
| if (idx < instances.size()) |
| return instances[idx].get_module_specifications; |
| return nullptr; |
| } |
| |
| ObjectFileCreateMemoryInstance |
| PluginManager::GetObjectFileCreateMemoryCallbackForPluginName( |
| llvm::StringRef name) { |
| const auto &instances = GetObjectFileInstances().GetInstances(); |
| for (auto &instance : instances) { |
| if (instance.name == name) |
| return instance.create_memory_callback; |
| } |
| return nullptr; |
| } |
| |
| Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp, |
| const FileSpec &outfile, |
| lldb::SaveCoreStyle &core_style, |
| llvm::StringRef plugin_name) { |
| if (plugin_name.empty()) { |
| // Try saving core directly from the process plugin first. |
| llvm::Expected<bool> ret = process_sp->SaveCore(outfile.GetPath()); |
| if (!ret) |
| return Status(ret.takeError()); |
| if (ret.get()) |
| return Status(); |
| } |
| |
| // Fall back to object plugins. |
| Status error; |
| auto &instances = GetObjectFileInstances().GetInstances(); |
| for (auto &instance : instances) { |
| if (plugin_name.empty() || instance.name == plugin_name) { |
| if (instance.save_core && |
| instance.save_core(process_sp, outfile, core_style, error)) |
| return error; |
| } |
| } |
| error.SetErrorString( |
| "no ObjectFile plugins were able to save a core for this process"); |
| return error; |
| } |
| |
| #pragma mark ObjectContainer |
| |
| struct ObjectContainerInstance |
| : public PluginInstance<ObjectContainerCreateInstance> { |
| ObjectContainerInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| ObjectFileGetModuleSpecifications get_module_specifications) |
| : PluginInstance<ObjectContainerCreateInstance>(name, description, |
| create_callback), |
| get_module_specifications(get_module_specifications) {} |
| |
| ObjectFileGetModuleSpecifications get_module_specifications; |
| }; |
| typedef PluginInstances<ObjectContainerInstance> ObjectContainerInstances; |
| |
| static ObjectContainerInstances &GetObjectContainerInstances() { |
| static ObjectContainerInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| ObjectContainerCreateInstance create_callback, |
| ObjectFileGetModuleSpecifications get_module_specifications) { |
| return GetObjectContainerInstances().RegisterPlugin( |
| name, description, create_callback, get_module_specifications); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| ObjectContainerCreateInstance create_callback) { |
| return GetObjectContainerInstances().UnregisterPlugin(create_callback); |
| } |
| |
| ObjectContainerCreateInstance |
| PluginManager::GetObjectContainerCreateCallbackAtIndex(uint32_t idx) { |
| return GetObjectContainerInstances().GetCallbackAtIndex(idx); |
| } |
| |
| ObjectFileGetModuleSpecifications |
| PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex( |
| uint32_t idx) { |
| const auto &instances = GetObjectContainerInstances().GetInstances(); |
| if (idx < instances.size()) |
| return instances[idx].get_module_specifications; |
| return nullptr; |
| } |
| |
| #pragma mark Platform |
| |
| typedef PluginInstance<PlatformCreateInstance> PlatformInstance; |
| typedef PluginInstances<PlatformInstance> PlatformInstances; |
| |
| static PlatformInstances &GetPlatformInstances() { |
| static PlatformInstances g_platform_instances; |
| return g_platform_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| PlatformCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback) { |
| return GetPlatformInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) { |
| return GetPlatformInstances().UnregisterPlugin(create_callback); |
| } |
| |
| llvm::StringRef PluginManager::GetPlatformPluginNameAtIndex(uint32_t idx) { |
| return GetPlatformInstances().GetNameAtIndex(idx); |
| } |
| |
| llvm::StringRef |
| PluginManager::GetPlatformPluginDescriptionAtIndex(uint32_t idx) { |
| return GetPlatformInstances().GetDescriptionAtIndex(idx); |
| } |
| |
| PlatformCreateInstance |
| PluginManager::GetPlatformCreateCallbackAtIndex(uint32_t idx) { |
| return GetPlatformInstances().GetCallbackAtIndex(idx); |
| } |
| |
| PlatformCreateInstance |
| PluginManager::GetPlatformCreateCallbackForPluginName(llvm::StringRef name) { |
| return GetPlatformInstances().GetCallbackForName(name); |
| } |
| |
| void PluginManager::AutoCompletePlatformName(llvm::StringRef name, |
| CompletionRequest &request) { |
| for (const auto &instance : GetPlatformInstances().GetInstances()) { |
| if (instance.name.startswith(name)) |
| request.AddCompletion(instance.name); |
| } |
| } |
| |
| #pragma mark Process |
| |
| typedef PluginInstance<ProcessCreateInstance> ProcessInstance; |
| typedef PluginInstances<ProcessInstance> ProcessInstances; |
| |
| static ProcessInstances &GetProcessInstances() { |
| static ProcessInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| ProcessCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback) { |
| return GetProcessInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) { |
| return GetProcessInstances().UnregisterPlugin(create_callback); |
| } |
| |
| llvm::StringRef PluginManager::GetProcessPluginNameAtIndex(uint32_t idx) { |
| return GetProcessInstances().GetNameAtIndex(idx); |
| } |
| |
| llvm::StringRef PluginManager::GetProcessPluginDescriptionAtIndex(uint32_t idx) { |
| return GetProcessInstances().GetDescriptionAtIndex(idx); |
| } |
| |
| ProcessCreateInstance |
| PluginManager::GetProcessCreateCallbackAtIndex(uint32_t idx) { |
| return GetProcessInstances().GetCallbackAtIndex(idx); |
| } |
| |
| ProcessCreateInstance |
| PluginManager::GetProcessCreateCallbackForPluginName(llvm::StringRef name) { |
| return GetProcessInstances().GetCallbackForName(name); |
| } |
| |
| void PluginManager::AutoCompleteProcessName(llvm::StringRef name, |
| CompletionRequest &request) { |
| for (const auto &instance : GetProcessInstances().GetInstances()) { |
| if (instance.name.startswith(name)) |
| request.AddCompletion(instance.name, instance.description); |
| } |
| } |
| |
| #pragma mark ScriptInterpreter |
| |
| struct ScriptInterpreterInstance |
| : public PluginInstance<ScriptInterpreterCreateInstance> { |
| ScriptInterpreterInstance(llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| lldb::ScriptLanguage language) |
| : PluginInstance<ScriptInterpreterCreateInstance>(name, description, |
| create_callback), |
| language(language) {} |
| |
| lldb::ScriptLanguage language = lldb::eScriptLanguageNone; |
| }; |
| |
| typedef PluginInstances<ScriptInterpreterInstance> ScriptInterpreterInstances; |
| |
| static ScriptInterpreterInstances &GetScriptInterpreterInstances() { |
| static ScriptInterpreterInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| lldb::ScriptLanguage script_language, |
| ScriptInterpreterCreateInstance create_callback) { |
| return GetScriptInterpreterInstances().RegisterPlugin( |
| name, description, create_callback, script_language); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| ScriptInterpreterCreateInstance create_callback) { |
| return GetScriptInterpreterInstances().UnregisterPlugin(create_callback); |
| } |
| |
| ScriptInterpreterCreateInstance |
| PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) { |
| return GetScriptInterpreterInstances().GetCallbackAtIndex(idx); |
| } |
| |
| lldb::ScriptInterpreterSP |
| PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, |
| Debugger &debugger) { |
| const auto &instances = GetScriptInterpreterInstances().GetInstances(); |
| ScriptInterpreterCreateInstance none_instance = nullptr; |
| for (const auto &instance : instances) { |
| if (instance.language == lldb::eScriptLanguageNone) |
| none_instance = instance.create_callback; |
| |
| if (script_lang == instance.language) |
| return instance.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 StructuredDataPlugin |
| |
| struct StructuredDataPluginInstance |
| : public PluginInstance<StructuredDataPluginCreateInstance> { |
| StructuredDataPluginInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| DebuggerInitializeCallback debugger_init_callback, |
| StructuredDataFilterLaunchInfo filter_callback) |
| : PluginInstance<StructuredDataPluginCreateInstance>( |
| name, description, create_callback, debugger_init_callback), |
| filter_callback(filter_callback) {} |
| |
| StructuredDataFilterLaunchInfo filter_callback = nullptr; |
| }; |
| |
| typedef PluginInstances<StructuredDataPluginInstance> |
| StructuredDataPluginInstances; |
| |
| static StructuredDataPluginInstances &GetStructuredDataPluginInstances() { |
| static StructuredDataPluginInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| StructuredDataPluginCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback, |
| StructuredDataFilterLaunchInfo filter_callback) { |
| return GetStructuredDataPluginInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback, |
| filter_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| StructuredDataPluginCreateInstance create_callback) { |
| return GetStructuredDataPluginInstances().UnregisterPlugin(create_callback); |
| } |
| |
| StructuredDataPluginCreateInstance |
| PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx) { |
| return GetStructuredDataPluginInstances().GetCallbackAtIndex(idx); |
| } |
| |
| StructuredDataFilterLaunchInfo |
| PluginManager::GetStructuredDataFilterCallbackAtIndex( |
| uint32_t idx, bool &iteration_complete) { |
| const auto &instances = GetStructuredDataPluginInstances().GetInstances(); |
| if (idx < instances.size()) { |
| iteration_complete = false; |
| return instances[idx].filter_callback; |
| } else { |
| iteration_complete = true; |
| } |
| return nullptr; |
| } |
| |
| #pragma mark SymbolFile |
| |
| typedef PluginInstance<SymbolFileCreateInstance> SymbolFileInstance; |
| typedef PluginInstances<SymbolFileInstance> SymbolFileInstances; |
| |
| static SymbolFileInstances &GetSymbolFileInstances() { |
| static SymbolFileInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| SymbolFileCreateInstance create_callback, |
| DebuggerInitializeCallback debugger_init_callback) { |
| return GetSymbolFileInstances().RegisterPlugin( |
| name, description, create_callback, debugger_init_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin(SymbolFileCreateInstance create_callback) { |
| return GetSymbolFileInstances().UnregisterPlugin(create_callback); |
| } |
| |
| SymbolFileCreateInstance |
| PluginManager::GetSymbolFileCreateCallbackAtIndex(uint32_t idx) { |
| return GetSymbolFileInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark SymbolVendor |
| |
| typedef PluginInstance<SymbolVendorCreateInstance> SymbolVendorInstance; |
| typedef PluginInstances<SymbolVendorInstance> SymbolVendorInstances; |
| |
| static SymbolVendorInstances &GetSymbolVendorInstances() { |
| static SymbolVendorInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin(llvm::StringRef name, |
| llvm::StringRef description, |
| SymbolVendorCreateInstance create_callback) { |
| return GetSymbolVendorInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| SymbolVendorCreateInstance create_callback) { |
| return GetSymbolVendorInstances().UnregisterPlugin(create_callback); |
| } |
| |
| SymbolVendorCreateInstance |
| PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) { |
| return GetSymbolVendorInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark Trace |
| |
| struct TraceInstance |
| : public PluginInstance<TraceCreateInstanceForSessionFile> { |
| TraceInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback_for_session_file, |
| TraceCreateInstanceForLiveProcess create_callback_for_live_process, |
| llvm::StringRef schema) |
| : PluginInstance<TraceCreateInstanceForSessionFile>( |
| name, description, create_callback_for_session_file), |
| schema(schema), |
| create_callback_for_live_process(create_callback_for_live_process) {} |
| |
| llvm::StringRef schema; |
| TraceCreateInstanceForLiveProcess create_callback_for_live_process; |
| }; |
| |
| typedef PluginInstances<TraceInstance> TraceInstances; |
| |
| static TraceInstances &GetTracePluginInstances() { |
| static TraceInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| TraceCreateInstanceForSessionFile create_callback_for_session_file, |
| TraceCreateInstanceForLiveProcess create_callback_for_live_process, |
| llvm::StringRef schema) { |
| return GetTracePluginInstances().RegisterPlugin( |
| name, description, create_callback_for_session_file, |
| create_callback_for_live_process, schema); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| TraceCreateInstanceForSessionFile create_callback_for_session_file) { |
| return GetTracePluginInstances().UnregisterPlugin( |
| create_callback_for_session_file); |
| } |
| |
| TraceCreateInstanceForSessionFile |
| PluginManager::GetTraceCreateCallback(llvm::StringRef plugin_name) { |
| return GetTracePluginInstances().GetCallbackForName(plugin_name); |
| } |
| |
| TraceCreateInstanceForLiveProcess |
| PluginManager::GetTraceCreateCallbackForLiveProcess(llvm::StringRef plugin_name) { |
| for (const TraceInstance &instance : GetTracePluginInstances().GetInstances()) |
| if (instance.name == plugin_name) |
| return instance.create_callback_for_live_process; |
| return nullptr; |
| } |
| |
| llvm::StringRef PluginManager::GetTraceSchema(llvm::StringRef plugin_name) { |
| for (const TraceInstance &instance : GetTracePluginInstances().GetInstances()) |
| if (instance.name == plugin_name) |
| return instance.schema; |
| return llvm::StringRef(); |
| } |
| |
| llvm::StringRef PluginManager::GetTraceSchema(size_t index) { |
| if (TraceInstance *instance = |
| GetTracePluginInstances().GetInstanceAtIndex(index)) |
| return instance->schema; |
| return llvm::StringRef(); |
| } |
| |
| #pragma mark TraceExporter |
| |
| struct TraceExporterInstance |
| : public PluginInstance<TraceExporterCreateInstance> { |
| TraceExporterInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| TraceExporterCreateInstance create_instance, |
| ThreadTraceExportCommandCreator create_thread_trace_export_command) |
| : PluginInstance<TraceExporterCreateInstance>(name, description, |
| create_instance), |
| create_thread_trace_export_command(create_thread_trace_export_command) { |
| } |
| |
| ThreadTraceExportCommandCreator create_thread_trace_export_command; |
| }; |
| |
| typedef PluginInstances<TraceExporterInstance> TraceExporterInstances; |
| |
| static TraceExporterInstances &GetTraceExporterInstances() { |
| static TraceExporterInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| TraceExporterCreateInstance create_callback, |
| ThreadTraceExportCommandCreator create_thread_trace_export_command) { |
| return GetTraceExporterInstances().RegisterPlugin( |
| name, description, create_callback, create_thread_trace_export_command); |
| } |
| |
| TraceExporterCreateInstance |
| PluginManager::GetTraceExporterCreateCallback(llvm::StringRef plugin_name) { |
| return GetTraceExporterInstances().GetCallbackForName(plugin_name); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| TraceExporterCreateInstance create_callback) { |
| return GetTraceExporterInstances().UnregisterPlugin(create_callback); |
| } |
| |
| ThreadTraceExportCommandCreator |
| PluginManager::GetThreadTraceExportCommandCreatorAtIndex(uint32_t index) { |
| if (TraceExporterInstance *instance = |
| GetTraceExporterInstances().GetInstanceAtIndex(index)) |
| return instance->create_thread_trace_export_command; |
| return nullptr; |
| } |
| |
| llvm::StringRef |
| PluginManager::GetTraceExporterPluginNameAtIndex(uint32_t index) { |
| return GetTraceExporterInstances().GetNameAtIndex(index); |
| } |
| |
| #pragma mark UnwindAssembly |
| |
| typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance; |
| typedef PluginInstances<UnwindAssemblyInstance> UnwindAssemblyInstances; |
| |
| static UnwindAssemblyInstances &GetUnwindAssemblyInstances() { |
| static UnwindAssemblyInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| UnwindAssemblyCreateInstance create_callback) { |
| return GetUnwindAssemblyInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| UnwindAssemblyCreateInstance create_callback) { |
| return GetUnwindAssemblyInstances().UnregisterPlugin(create_callback); |
| } |
| |
| UnwindAssemblyCreateInstance |
| PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx) { |
| return GetUnwindAssemblyInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark MemoryHistory |
| |
| typedef PluginInstance<MemoryHistoryCreateInstance> MemoryHistoryInstance; |
| typedef PluginInstances<MemoryHistoryInstance> MemoryHistoryInstances; |
| |
| static MemoryHistoryInstances &GetMemoryHistoryInstances() { |
| static MemoryHistoryInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| MemoryHistoryCreateInstance create_callback) { |
| return GetMemoryHistoryInstances().RegisterPlugin(name, description, |
| create_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| MemoryHistoryCreateInstance create_callback) { |
| return GetMemoryHistoryInstances().UnregisterPlugin(create_callback); |
| } |
| |
| MemoryHistoryCreateInstance |
| PluginManager::GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx) { |
| return GetMemoryHistoryInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark InstrumentationRuntime |
| |
| struct InstrumentationRuntimeInstance |
| : public PluginInstance<InstrumentationRuntimeCreateInstance> { |
| InstrumentationRuntimeInstance( |
| llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| InstrumentationRuntimeGetType get_type_callback) |
| : PluginInstance<InstrumentationRuntimeCreateInstance>(name, description, |
| create_callback), |
| get_type_callback(get_type_callback) {} |
| |
| InstrumentationRuntimeGetType get_type_callback = nullptr; |
| }; |
| |
| typedef PluginInstances<InstrumentationRuntimeInstance> |
| InstrumentationRuntimeInstances; |
| |
| static InstrumentationRuntimeInstances &GetInstrumentationRuntimeInstances() { |
| static InstrumentationRuntimeInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| InstrumentationRuntimeCreateInstance create_callback, |
| InstrumentationRuntimeGetType get_type_callback) { |
| return GetInstrumentationRuntimeInstances().RegisterPlugin( |
| name, description, create_callback, get_type_callback); |
| } |
| |
| bool PluginManager::UnregisterPlugin( |
| InstrumentationRuntimeCreateInstance create_callback) { |
| return GetInstrumentationRuntimeInstances().UnregisterPlugin(create_callback); |
| } |
| |
| InstrumentationRuntimeGetType |
| PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx) { |
| const auto &instances = GetInstrumentationRuntimeInstances().GetInstances(); |
| if (idx < instances.size()) |
| return instances[idx].get_type_callback; |
| return nullptr; |
| } |
| |
| InstrumentationRuntimeCreateInstance |
| PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx) { |
| return GetInstrumentationRuntimeInstances().GetCallbackAtIndex(idx); |
| } |
| |
| #pragma mark TypeSystem |
| |
| struct TypeSystemInstance : public PluginInstance<TypeSystemCreateInstance> { |
| TypeSystemInstance(llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, |
| LanguageSet supported_languages_for_types, |
| LanguageSet supported_languages_for_expressions) |
| : PluginInstance<TypeSystemCreateInstance>(name, description, |
| create_callback), |
| supported_languages_for_types(supported_languages_for_types), |
| supported_languages_for_expressions( |
| supported_languages_for_expressions) {} |
| |
| LanguageSet supported_languages_for_types; |
| LanguageSet supported_languages_for_expressions; |
| }; |
| |
| typedef PluginInstances<TypeSystemInstance> TypeSystemInstances; |
| |
| static TypeSystemInstances &GetTypeSystemInstances() { |
| static TypeSystemInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin( |
| llvm::StringRef name, llvm::StringRef description, |
| TypeSystemCreateInstance create_callback, |
| LanguageSet supported_languages_for_types, |
| LanguageSet supported_languages_for_expressions) { |
| return GetTypeSystemInstances().RegisterPlugin( |
| name, description, create_callback, supported_languages_for_types, |
| supported_languages_for_expressions); |
| } |
| |
| bool PluginManager::UnregisterPlugin(TypeSystemCreateInstance create_callback) { |
| return GetTypeSystemInstances().UnregisterPlugin(create_callback); |
| } |
| |
| TypeSystemCreateInstance |
| PluginManager::GetTypeSystemCreateCallbackAtIndex(uint32_t idx) { |
| return GetTypeSystemInstances().GetCallbackAtIndex(idx); |
| } |
| |
| LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForTypes() { |
| const auto &instances = GetTypeSystemInstances().GetInstances(); |
| LanguageSet all; |
| for (unsigned i = 0; i < instances.size(); ++i) |
| all.bitvector |= instances[i].supported_languages_for_types.bitvector; |
| return all; |
| } |
| |
| LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() { |
| const auto &instances = GetTypeSystemInstances().GetInstances(); |
| LanguageSet all; |
| for (unsigned i = 0; i < instances.size(); ++i) |
| all.bitvector |= instances[i].supported_languages_for_expressions.bitvector; |
| return all; |
| } |
| |
| #pragma mark REPL |
| |
| struct REPLInstance : public PluginInstance<REPLCreateInstance> { |
| REPLInstance(llvm::StringRef name, llvm::StringRef description, |
| CallbackType create_callback, LanguageSet supported_languages) |
| : PluginInstance<REPLCreateInstance>(name, description, create_callback), |
| supported_languages(supported_languages) {} |
| |
| LanguageSet supported_languages; |
| }; |
| |
| typedef PluginInstances<REPLInstance> REPLInstances; |
| |
| static REPLInstances &GetREPLInstances() { |
| static REPLInstances g_instances; |
| return g_instances; |
| } |
| |
| bool PluginManager::RegisterPlugin(llvm::StringRef name, llvm::StringRef description, |
| REPLCreateInstance create_callback, |
| LanguageSet supported_languages) { |
| return GetREPLInstances().RegisterPlugin(name, description, create_callback, |
| supported_languages); |
| } |
| |
| bool PluginManager::UnregisterPlugin(REPLCreateInstance create_callback) { |
| return GetREPLInstances().UnregisterPlugin(create_callback); |
| } |
| |
| REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) { |
| return GetREPLInstances().GetCallbackAtIndex(idx); |
| } |
| |
| LanguageSet PluginManager::GetREPLAllTypeSystemSupportedLanguages() { |
| const auto &instances = GetREPLInstances().GetInstances(); |
| LanguageSet all; |
| for (unsigned i = 0; i < instances.size(); ++i) |
| all.bitvector |= instances[i].supported_languages.bitvector; |
| return all; |
| } |
| |
| #pragma mark PluginManager |
| |
| void PluginManager::DebuggerInitialize(Debugger &debugger) { |
| GetDynamicLoaderInstances().PerformDebuggerCallback(debugger); |
| GetJITLoaderInstances().PerformDebuggerCallback(debugger); |
| GetPlatformInstances().PerformDebuggerCallback(debugger); |
| GetProcessInstances().PerformDebuggerCallback(debugger); |
| GetSymbolFileInstances().PerformDebuggerCallback(debugger); |
| GetOperatingSystemInstances().PerformDebuggerCallback(debugger); |
| GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger); |
| GetTracePluginInstances().PerformDebuggerCallback(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); |
| } |
| |
| static 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; |
| } |
| |
| static 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; |
| } |
| |
| static const char *kDynamicLoaderPluginName("dynamic-loader"); |
| static const char *kPlatformPluginName("platform"); |
| static const char *kProcessPluginName("process"); |
| static const char *kSymbolFilePluginName("symbol-file"); |
| static const char *kJITLoaderPluginName("jit-loader"); |
| static const char *kStructuredDataPluginName("structured-data"); |
| |
| 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); |
| } |