Index: lldb/bindings/interface/SBPlatform.i =================================================================== --- lldb/bindings/interface/SBPlatform.i +++ lldb/bindings/interface/SBPlatform.i @@ -126,6 +126,18 @@ SBPlatform (const char *); + %feature("docstring", " + Create a platform instance using a specific platform plugin name, debugger, + script name and user-provided dictionary. + + :param platform_name: name of the platform plugin to use to create the platform + :param debugger: debugger instance owning the platform + :param script_name: name of the script class and module to use to create the platform + :param dict: user-provided dictionary that can be used when instanciating a platform + ") + SBPlatform (const char *, const SBDebugger&, + const char *, const SBStructuredData&); + ~SBPlatform(); static SBPlatform GetHostPlatform(); Index: lldb/include/lldb/API/SBDebugger.h =================================================================== --- lldb/include/lldb/API/SBDebugger.h +++ lldb/include/lldb/API/SBDebugger.h @@ -420,6 +420,7 @@ const SBFileSpec &trace_description_file); private: + friend class SBPlatform; friend class SBCommandInterpreter; friend class SBInputReader; friend class SBListener; Index: lldb/include/lldb/API/SBPlatform.h =================================================================== --- lldb/include/lldb/API/SBPlatform.h +++ lldb/include/lldb/API/SBPlatform.h @@ -96,6 +96,9 @@ SBPlatform(const char *platform_name); + SBPlatform(const char *platform_name, const SBDebugger &debugger, + const char *script_name, const SBStructuredData &dict); + SBPlatform(const SBPlatform &rhs); SBPlatform &operator=(const SBPlatform &rhs); Index: lldb/include/lldb/API/SBStructuredData.h =================================================================== --- lldb/include/lldb/API/SBStructuredData.h +++ lldb/include/lldb/API/SBStructuredData.h @@ -93,6 +93,7 @@ friend class SBLaunchInfo; friend class SBDebugger; friend class SBTarget; + friend class SBPlatform; friend class SBProcess; friend class SBThread; friend class SBThreadPlan; Index: lldb/include/lldb/Interpreter/OptionGroupPlatform.h =================================================================== --- lldb/include/lldb/Interpreter/OptionGroupPlatform.h +++ lldb/include/lldb/Interpreter/OptionGroupPlatform.h @@ -9,19 +9,22 @@ #ifndef LLDB_INTERPRETER_OPTIONGROUPPLATFORM_H #define LLDB_INTERPRETER_OPTIONGROUPPLATFORM_H +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/Options.h" #include "lldb/Utility/ConstString.h" #include "llvm/Support/VersionTuple.h" namespace lldb_private { +class CommandObjectPlatformSelect; // PlatformOptionGroup // // Make platform options available to any commands that need the settings. class OptionGroupPlatform : public OptionGroup { public: OptionGroupPlatform(bool include_platform_option) - : m_include_platform_option(include_platform_option) {} + : m_include_platform_option(include_platform_option), + m_class_options("scripted platform", true, 'C', 'K', 'V', 0) {} ~OptionGroupPlatform() override = default; @@ -60,11 +63,14 @@ bool PlatformMatches(const lldb::PlatformSP &platform_sp) const; protected: + friend class CommandObjectPlatformSelect; + std::string m_platform_name; ConstString m_sdk_sysroot; ConstString m_sdk_build; llvm::VersionTuple m_os_version; bool m_include_platform_option; + OptionGroupPythonClassWithDict m_class_options; }; } // namespace lldb_private Index: lldb/include/lldb/Target/Platform.h =================================================================== --- lldb/include/lldb/Target/Platform.h +++ lldb/include/lldb/Target/Platform.h @@ -21,6 +21,7 @@ #include "lldb/Core/UserSettingsController.h" #include "lldb/Host/File.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/ScriptedMetadata.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" @@ -58,6 +59,8 @@ typedef llvm::SmallVector MmapArgList; +class PlatformMetadata; + /// \class Platform Platform.h "lldb/Target/Platform.h" /// A plug-in interface definition class for debug platform that /// includes many platform abilities such as: @@ -610,6 +613,10 @@ virtual const char *GetLocalCacheDirectory(); + void SetMetadata(std::unique_ptr metadata); + + virtual bool ReloadMetadata() { return true; } + virtual std::string GetPlatformSpecificConnectionInformation() { return ""; } virtual bool CalculateMD5(const FileSpec &file_spec, uint64_t &low, @@ -926,6 +933,7 @@ std::vector m_trap_handlers; bool m_calculated_trap_handlers; const std::unique_ptr m_module_cache; + std::unique_ptr m_metadata; /// Ask the Platform subclass to fill in the list of trap handler names /// @@ -1092,6 +1100,21 @@ const PlatformList &operator=(const PlatformList &) = delete; }; +class PlatformMetadata { +public: + PlatformMetadata(Debugger &debugger, const ScriptedMetadata *metadata); + ~PlatformMetadata() = default; + + Debugger &GetDebugger() const { return m_debugger; } + const ScriptedMetadata *GetScriptedMetadata() const { + return m_scripted_metadata; + } + +protected: + Debugger &m_debugger; + const ScriptedMetadata *m_scripted_metadata; +}; + class OptionGroupPlatformRSync : public lldb_private::OptionGroup { public: OptionGroupPlatformRSync() = default; Index: lldb/source/API/SBPlatform.cpp =================================================================== --- lldb/source/API/SBPlatform.cpp +++ lldb/source/API/SBPlatform.cpp @@ -7,13 +7,16 @@ //===----------------------------------------------------------------------===// #include "lldb/API/SBPlatform.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBEnvironment.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBPlatform.h" +#include "lldb/API/SBStructuredData.h" #include "lldb/API/SBUnixSignals.h" #include "lldb/Host/File.h" +#include "lldb/Interpreter/ScriptedMetadata.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ArchSpec.h" @@ -295,6 +298,35 @@ m_opaque_sp = Platform::Create(platform_name); } +SBPlatform::SBPlatform(const char *platform_name, const SBDebugger &debugger, + const char *script_name, const SBStructuredData &dict) + : SBPlatform(platform_name) { + LLDB_INSTRUMENT_VA(this, platform_name, debugger, script_name, dict); + + if (!m_opaque_sp) + return; + + if (!script_name || !dict.IsValid() || !dict.m_impl_up) + return; + + StructuredData::ObjectSP obj_sp = dict.m_impl_up->GetObjectSP(); + + if (!obj_sp) + return; + + StructuredData::DictionarySP dict_sp = + std::make_shared(obj_sp); + if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) + return; + + const ScriptedMetadata scripted_metadata(script_name, dict_sp); + + auto metadata = + std::make_unique(debugger.ref(), &scripted_metadata); + m_opaque_sp->SetMetadata(std::move(metadata)); + m_opaque_sp->ReloadMetadata(); +} + SBPlatform::SBPlatform(const SBPlatform &rhs) { LLDB_INSTRUMENT_VA(this, rhs); Index: lldb/source/Commands/CommandObjectPlatform.h =================================================================== --- lldb/source/Commands/CommandObjectPlatform.h +++ lldb/source/Commands/CommandObjectPlatform.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLATFORM_H #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/OptionGroupPlatform.h" namespace lldb_private { @@ -27,6 +28,23 @@ operator=(const CommandObjectPlatform &) = delete; }; +class CommandObjectPlatformSelect : public CommandObjectParsed { +public: + CommandObjectPlatformSelect(CommandInterpreter &interpreter); + + ~CommandObjectPlatformSelect() override = default; + + void HandleCompletion(CompletionRequest &request) override; + + Options *GetOptions() override; + +protected: + bool DoExecute(Args &args, CommandReturnObject &result) override; + + OptionGroupOptions m_option_group; + OptionGroupPlatform m_platform_options; +}; + } // namespace lldb_private #endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTPLATFORM_H Index: lldb/source/Commands/CommandObjectPlatform.cpp =================================================================== --- lldb/source/Commands/CommandObjectPlatform.cpp +++ lldb/source/Commands/CommandObjectPlatform.cpp @@ -139,63 +139,65 @@ }; // "platform select " -class CommandObjectPlatformSelect : public CommandObjectParsed { -public: - CommandObjectPlatformSelect(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "platform select", - "Create a platform if needed and select it as the " - "current platform.", - "platform select ", 0), - m_platform_options( - false) // Don't include the "--platform" option by passing false - { - m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1); - m_option_group.Finalize(); - CommandArgumentData platform_arg{eArgTypePlatform, eArgRepeatPlain}; - m_arguments.push_back({platform_arg}); - } - - ~CommandObjectPlatformSelect() override = default; +CommandObjectPlatformSelect::CommandObjectPlatformSelect( + CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "platform select", + "Create a platform if needed and select it as the " + "current platform.", + "platform select ", 0), + m_platform_options( + false) // Don't include the "--platform" option by passing false +{ + m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1); + m_option_group.Append(&m_platform_options.m_class_options, + LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_ALL); + m_option_group.Finalize(); + CommandArgumentData platform_arg{eArgTypePlatform, eArgRepeatPlain}; + m_arguments.push_back({platform_arg}); +} - void HandleCompletion(CompletionRequest &request) override { - CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request, - nullptr); - } +void CommandObjectPlatformSelect::HandleCompletion(CompletionRequest &request) { + CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request, + nullptr); +} - Options *GetOptions() override { return &m_option_group; } +Options *CommandObjectPlatformSelect::GetOptions() { return &m_option_group; } -protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { - if (args.GetArgumentCount() == 1) { - const char *platform_name = args.GetArgumentAtIndex(0); - if (platform_name && platform_name[0]) { - const bool select = true; - m_platform_options.SetPlatformName(platform_name); - Status error; - ArchSpec platform_arch; - PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions( - m_interpreter, ArchSpec(), select, error, platform_arch)); - if (platform_sp) { - GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp); - - platform_sp->GetStatus(result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendError(error.AsCString()); - } +bool CommandObjectPlatformSelect::DoExecute(Args &args, + CommandReturnObject &result) { + if (args.GetArgumentCount() == 1) { + const char *platform_name = args.GetArgumentAtIndex(0); + if (platform_name && platform_name[0]) { + const bool select = true; + m_platform_options.SetPlatformName(platform_name); + Status error; + ArchSpec platform_arch; + PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions( + m_interpreter, ArchSpec(), select, error, platform_arch)); + if (platform_sp) { + GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp); + const ScriptedMetadata scripted_metadata( + m_platform_options.m_class_options); + + auto metadata = std::make_unique(GetDebugger(), + &scripted_metadata); + platform_sp->SetMetadata(std::move(metadata)); + if (!platform_sp->ReloadMetadata()) + result.AppendError("platform couldn't reload metadata\n"); + platform_sp->GetStatus(result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); } else { - result.AppendError("invalid platform name"); + result.AppendError(error.AsCString()); } } else { - result.AppendError( - "platform create takes a platform name as an argument\n"); + result.AppendError("invalid platform name"); } - return result.Succeeded(); + } else { + result.AppendError( + "platform create takes a platform name as an argument\n"); } - - OptionGroupOptions m_option_group; - OptionGroupPlatform m_platform_options; -}; + return result.Succeeded(); +} // "platform list" class CommandObjectPlatformList : public CommandObjectParsed { Index: lldb/source/Plugins/Platform/scripted/ScriptedPlatform.h =================================================================== --- lldb/source/Plugins/Platform/scripted/ScriptedPlatform.h +++ lldb/source/Plugins/Platform/scripted/ScriptedPlatform.h @@ -16,14 +16,13 @@ class ScriptedPlatform : public Platform { public: - ScriptedPlatform(Debugger *debugger, - const ScriptedMetadata *scripted_metadata, Status &error); + ScriptedPlatform(); ~ScriptedPlatform() override; - static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch, - const Debugger *debugger, - const ScriptedMetadata *metadata); + bool SetupScriptedObject(Status &error); + + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); static void Initialize(); @@ -60,6 +59,8 @@ void CalculateTrapHandlerSymbolNames() override {} + bool ReloadMetadata() override; + private: inline void CheckInterpreterAndScriptObject() const { assert(m_interpreter && "Invalid Script Interpreter."); @@ -76,7 +77,7 @@ static bool IsScriptLanguageSupported(lldb::ScriptLanguage language); - const ScriptedMetadata *m_scripted_metadata = nullptr; + ScriptedMetadata *m_scripted_metadata = nullptr; lldb_private::ScriptInterpreter *m_interpreter = nullptr; lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr; }; Index: lldb/source/Plugins/Platform/scripted/ScriptedPlatform.cpp =================================================================== --- lldb/source/Plugins/Platform/scripted/ScriptedPlatform.cpp +++ lldb/source/Plugins/Platform/scripted/ScriptedPlatform.cpp @@ -38,10 +38,8 @@ return m_interpreter->GetScriptedPlatformInterface(); } -lldb::PlatformSP -ScriptedPlatform::CreateInstance(bool force, const ArchSpec *arch, - const Debugger *debugger, - const ScriptedMetadata *metadata) { +lldb::PlatformSP ScriptedPlatform::CreateInstance(bool force, + const ArchSpec *arch) { Log *log = GetLog(LLDBLog::Platform); if (log) { const char *arch_name; @@ -53,70 +51,62 @@ const char *triple_cstr = arch ? arch->GetTriple().getTriple().c_str() : ""; - LLDB_LOGF(log, - "ScriptedPlatform::%s(force=%s, arch={%s,%s}, debugger=%" PRIxPTR - ")", + LLDB_LOGF(log, "ScriptedPlatform::%s(force=%s, arch={%s,%s})", __PRETTY_FUNCTION__, force ? "true" : "false", arch_name, - triple_cstr, (uintptr_t)debugger); + triple_cstr); } - if (!debugger || !IsScriptLanguageSupported(debugger->GetScriptLanguage())) - return {}; + return std::make_shared(); +} - if (!metadata) - return {}; +ScriptedPlatform::ScriptedPlatform() : Platform(false) {} - Status error; - std::shared_ptr scripted_platform_sp = - std::make_shared(const_cast(debugger), - metadata, error); +bool ScriptedPlatform::SetupScriptedObject(Status &error) { - if (error.Success()) - return scripted_platform_sp; + auto error_with_message = [&error](llvm::StringRef message) { + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, message, error, LLDBLog::Platform); + }; - LLDB_LOGF(log, "ScriptedPlatform::%s() aborting creation of platform", - __PRETTY_FUNCTION__); + Debugger &debugger = m_metadata->GetDebugger(); - return {}; -} + if (!IsScriptLanguageSupported(debugger.GetScriptLanguage())) + return error_with_message("Debugger language not supported"); -ScriptedPlatform::ScriptedPlatform(Debugger *debugger, - const ScriptedMetadata *scripted_metadata, - Status &error) - : Platform(false), m_scripted_metadata(scripted_metadata) { - if (!debugger) { - error.SetErrorStringWithFormat("ScriptedPlatform::%s () - ERROR: %s", - __FUNCTION__, "Invalid debugger"); - return; - } + m_interpreter = debugger.GetScriptInterpreter(); - m_interpreter = debugger->GetScriptInterpreter(); + if (!m_interpreter) + return error_with_message("Debugger has no Script Interpreter"); - if (!m_interpreter) { - error.SetErrorStringWithFormat("ScriptedPlatform::%s () - ERROR: %s", - __FUNCTION__, - "Debugger has no Script Interpreter"); - return; - } + const ScriptedMetadata *scripted_metadata = m_metadata->GetScriptedMetadata(); - ExecutionContext e; + if (!scripted_metadata) + return error_with_message("No scripted metadata"); + + m_scripted_metadata = const_cast(scripted_metadata); + ExecutionContext e; StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject( m_scripted_metadata->GetClassName(), e, m_scripted_metadata->GetArgsSP()); - if (!object_sp || !object_sp->IsValid()) { - error.SetErrorStringWithFormat("ScriptedPlatform::%s () - ERROR: %s", - __FUNCTION__, - "Failed to create valid script object"); - return; - } + if (!object_sp || !object_sp->IsValid()) + return error_with_message("Failed to create valid script object"); m_hostname = GetHostPlatform()->GetHostname(); m_script_object_sp = object_sp; + return true; } ScriptedPlatform::~ScriptedPlatform() {} +bool ScriptedPlatform::ReloadMetadata() { + if (!m_metadata) + return false; + + Status error; + return SetupScriptedObject(error); +} + void ScriptedPlatform::Initialize() { if (g_initialize_count++ == 0) { // NOTE: This should probably be using the driving process platform @@ -269,7 +259,9 @@ } Status ScriptedPlatform::LaunchProcess(ProcessLaunchInfo &launch_info) { - return GetInterface().LaunchProcess(); + lldb::ProcessLaunchInfoSP launch_info_sp = + std::make_shared(launch_info); + return GetInterface().LaunchProcess(launch_info_sp); } Status ScriptedPlatform::KillProcess(const lldb::pid_t pid) { Index: lldb/source/Target/Platform.cpp =================================================================== --- lldb/source/Target/Platform.cpp +++ lldb/source/Target/Platform.cpp @@ -164,40 +164,6 @@ return FileSpecList(); } -// PlatformSP -// Platform::FindPlugin (Process *process, ConstString plugin_name) -//{ -// PlatformCreateInstance create_callback = nullptr; -// if (plugin_name) -// { -// create_callback = -// PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name); -// if (create_callback) -// { -// ArchSpec arch; -// if (process) -// { -// arch = process->GetTarget().GetArchitecture(); -// } -// PlatformSP platform_sp(create_callback(process, &arch)); -// if (platform_sp) -// return platform_sp; -// } -// } -// else -// { -// for (uint32_t idx = 0; (create_callback = -// PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != nullptr; -// ++idx) -// { -// PlatformSP platform_sp(create_callback(process, nullptr)); -// if (platform_sp) -// return platform_sp; -// } -// } -// return PlatformSP(); -//} - Status Platform::GetSharedModule( const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, @@ -268,6 +234,10 @@ return HostInfo::GetAugmentedArchSpec(triple); } +PlatformMetadata::PlatformMetadata(Debugger &debugger, + const ScriptedMetadata *metadata) + : m_debugger(debugger), m_scripted_metadata(metadata) {} + /// Default Constructor Platform::Platform(bool is_host) : m_is_host(is_host), m_os_version_set_while_connected(false), @@ -276,7 +246,7 @@ m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(), m_ignores_remote_hostname(false), m_trap_handlers(), m_calculated_trap_handlers(false), - m_module_cache(std::make_unique()) { + m_module_cache(std::make_unique()), m_metadata() { Log *log = GetLog(LLDBLog::Object); LLDB_LOGF(log, "%p Platform::Platform()", static_cast(this)); } @@ -1328,6 +1298,10 @@ return m_local_cache_directory.c_str(); } +void Platform::SetMetadata(std::unique_ptr metadata) { + m_metadata = std::move(metadata); +} + static constexpr OptionDefinition g_rsync_option_table[] = { {LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable rsync."},