Index: lldb/bindings/python/python-swigsafecast.swig =================================================================== --- lldb/bindings/python/python-swigsafecast.swig +++ lldb/bindings/python/python-swigsafecast.swig @@ -93,6 +93,16 @@ SWIGTYPE_p_lldb__SBSymbolContext); } +PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp) { + return ToSWIGHelper(new lldb::ProcessLaunchInfoSP(std::move(launch_info_sp)), + SWIGTYPE_p_lldb__SBLaunchInfo); +} + +PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp) { + return ToSWIGHelper(new lldb::ProcessAttachInfoSP(std::move(attach_info_sp)), + SWIGTYPE_p_lldb__SBAttachInfo); +} + ScopedPythonObject ToSWIGWrapper(CommandReturnObject &cmd_retobj) { return ScopedPythonObject( Index: lldb/bindings/python/python-wrapper.swig =================================================================== --- lldb/bindings/python/python-wrapper.swig +++ lldb/bindings/python/python-wrapper.swig @@ -716,6 +716,66 @@ return sb_ptr; } +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBProcess(PyObject * data) { + lldb::SBProcess *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBProcess, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBDebugger(PyObject * data) { + lldb::SBDebugger *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBDebugger, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBTarget(PyObject * data) { + lldb::SBTarget *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBTarget, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject * data) { + lldb::SBAttachInfo *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBAttachInfo, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject * data) { + lldb::SBLaunchInfo *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBLaunchInfo, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + void *lldb_private::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data) { lldb::SBError *sb_ptr = nullptr; Index: lldb/examples/python/scripted_process/scripted_platform.py =================================================================== --- lldb/examples/python/scripted_process/scripted_platform.py +++ lldb/examples/python/scripted_process/scripted_platform.py @@ -60,14 +60,17 @@ pass @abstractmethod - def attach_to_process(self, attach_info): + def attach_to_process(self, attach_info, target, debugger, error): """ Attach to a process. Args: attach_info (lldb.SBAttachInfo): The information related to attach to a process. + target (lldb.SBTarget): The optional target that we are trying to attach to. + debugger (lldb.SBDebugger): The debugger instance. + error (lldb.SBError): A status object notifying if the attach succeeded. Returns: - lldb.SBError: A status object notifying if the attach succeeded. + lldb.SBProcess: The process that the platform attached to, or None. """ pass Index: lldb/include/lldb/API/SBAttachInfo.h =================================================================== --- lldb/include/lldb/API/SBAttachInfo.h +++ lldb/include/lldb/API/SBAttachInfo.h @@ -11,6 +11,10 @@ #include "lldb/API/SBDefines.h" +namespace lldb_private { +class ScriptInterpreter; +} + namespace lldb { class SBTarget; @@ -167,6 +171,8 @@ protected: friend class SBTarget; + friend class lldb_private::ScriptInterpreter; + lldb_private::ProcessAttachInfo &ref(); ProcessAttachInfoSP m_opaque_sp; Index: lldb/include/lldb/API/SBDebugger.h =================================================================== --- lldb/include/lldb/API/SBDebugger.h +++ lldb/include/lldb/API/SBDebugger.h @@ -14,6 +14,10 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBPlatform.h" +namespace lldb_private { +class ScriptInterpreter; +} + namespace lldb { class LLDB_API SBInputReader { @@ -428,6 +432,8 @@ friend class SBTarget; friend class SBTrace; + friend class lldb_private::ScriptInterpreter; + lldb::SBTarget FindTargetWithLLDBProcess(const lldb::ProcessSP &processSP); void reset(const lldb::DebuggerSP &debugger_sp); Index: lldb/include/lldb/API/SBLaunchInfo.h =================================================================== --- lldb/include/lldb/API/SBLaunchInfo.h +++ lldb/include/lldb/API/SBLaunchInfo.h @@ -13,6 +13,7 @@ namespace lldb_private { class SBLaunchInfoImpl; +class ScriptInterpreter; } namespace lldb { @@ -183,6 +184,8 @@ friend class SBPlatform; friend class SBTarget; + friend class lldb_private::ScriptInterpreter; + const lldb_private::ProcessLaunchInfo &ref() const; void set_ref(const lldb_private::ProcessLaunchInfo &info); Index: lldb/include/lldb/API/SBProcess.h =================================================================== --- lldb/include/lldb/API/SBProcess.h +++ lldb/include/lldb/API/SBProcess.h @@ -16,6 +16,10 @@ #include "lldb/API/SBTarget.h" #include +namespace lldb_private { +class ScriptInterpreter; +} + namespace lldb { class SBEvent; @@ -437,6 +441,8 @@ friend class SBValue; friend class lldb_private::QueueImpl; + friend class lldb_private::ScriptInterpreter; + lldb::ProcessSP GetSP() const; void SetSP(const lldb::ProcessSP &process_sp); Index: lldb/include/lldb/API/SBTarget.h =================================================================== --- lldb/include/lldb/API/SBTarget.h +++ lldb/include/lldb/API/SBTarget.h @@ -22,6 +22,10 @@ #include "lldb/API/SBValue.h" #include "lldb/API/SBWatchpoint.h" +namespace lldb_private { +class ScriptInterpreter; +} + namespace lldb { class SBPlatform; @@ -880,6 +884,8 @@ friend class SBValue; friend class SBVariablesOptions; + friend class lldb_private::ScriptInterpreter; + // Constructors are private, use static Target::Create function to create an // instance of this class. Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h =================================================================== --- lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -9,9 +9,14 @@ #ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H #define LLDB_INTERPRETER_SCRIPTINTERPRETER_H +#include "lldb/API/SBAttachInfo.h" #include "lldb/API/SBData.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBMemoryRegionInfo.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBTarget.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SearchFilter.h" @@ -583,6 +588,20 @@ Status GetStatusFromSBError(const lldb::SBError &error) const; + lldb::ProcessSP + GetOpaqueTypeFromSBProcess(const lldb::SBProcess &process) const; + + lldb::DebuggerSP + GetOpaqueTypeFromSBDebugger(const lldb::SBDebugger &debugger) const; + + lldb::TargetSP GetOpaqueTypeFromSBTarget(const lldb::SBTarget &target) const; + + lldb::ProcessAttachInfoSP + GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const; + + lldb::ProcessLaunchInfoSP + GetOpaqueTypeFromSBLaunchInfo(const lldb::SBLaunchInfo &launch_info) const; + std::optional GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const; Index: lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h =================================================================== --- lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h +++ lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h @@ -32,8 +32,11 @@ return {}; } - virtual Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) { - return Status("ScriptedPlatformInterface cannot attach to a process"); + virtual lldb::ProcessSP + AttachToProcess(lldb::ProcessAttachInfoSP attach_info_sp, + lldb::TargetSP target_sp, lldb::DebuggerSP debugger_sp, + Status &error) { + return {}; } virtual Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) { Index: lldb/source/Interpreter/ScriptInterpreter.cpp =================================================================== --- lldb/source/Interpreter/ScriptInterpreter.cpp +++ lldb/source/Interpreter/ScriptInterpreter.cpp @@ -82,6 +82,32 @@ return data.m_opaque_sp; } +lldb::ProcessSP ScriptInterpreter::GetOpaqueTypeFromSBProcess( + const lldb::SBProcess &process) const { + return process.m_opaque_wp.lock(); +} + +lldb::DebuggerSP ScriptInterpreter::GetOpaqueTypeFromSBDebugger( + const lldb::SBDebugger &debugger) const { + return debugger.m_opaque_sp; +} + +lldb::TargetSP ScriptInterpreter::GetOpaqueTypeFromSBTarget( + const lldb::SBTarget &target) const { + return target.m_opaque_sp; +} + +lldb::ProcessAttachInfoSP ScriptInterpreter::GetOpaqueTypeFromSBAttachInfo( + const lldb::SBAttachInfo &attach_info) const { + return attach_info.m_opaque_sp; +} + +lldb::ProcessLaunchInfoSP ScriptInterpreter::GetOpaqueTypeFromSBLaunchInfo( + const lldb::SBLaunchInfo &launch_info) const { + return std::make_shared( + *reinterpret_cast(launch_info.m_opaque_sp.get())); +} + Status ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const { if (error.m_opaque_up) Index: lldb/source/Plugins/Platform/CMakeLists.txt =================================================================== --- lldb/source/Plugins/Platform/CMakeLists.txt +++ lldb/source/Plugins/Platform/CMakeLists.txt @@ -6,5 +6,6 @@ add_subdirectory(NetBSD) add_subdirectory(OpenBSD) add_subdirectory(POSIX) +add_subdirectory(Scripted) add_subdirectory(QemuUser) add_subdirectory(Windows) Index: lldb/source/Plugins/Platform/scripted/CMakeLists.txt =================================================================== --- /dev/null +++ lldb/source/Plugins/Platform/scripted/CMakeLists.txt @@ -0,0 +1,8 @@ +add_lldb_library(lldbPluginScriptedPlatform PLUGIN + ScriptedPlatform.cpp + + LINK_LIBS + lldbCore + lldbTarget + lldbUtility + ) Index: lldb/source/Plugins/Platform/scripted/ScriptedPlatform.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Platform/scripted/ScriptedPlatform.h @@ -0,0 +1,86 @@ +//===-- ScriptedPlatform.h --------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_SCRIPTED_PLATFORM_H +#define LLDB_SOURCE_PLUGINS_SCRIPTED_PLATFORM_H + +#include "lldb/Interpreter/ScriptedMetadata.h" +#include "lldb/Target/Platform.h" + +namespace lldb_private { + +class ScriptedPlatform : public Platform { +public: + ScriptedPlatform(Debugger *debugger, + const ScriptedMetadata *scripted_metadata, Status &error); + + ~ScriptedPlatform() override; + + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch, + const Debugger *debugger, + const ScriptedMetadata *metadata); + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "scripted-platform"; } + + static llvm::StringRef GetDescriptionStatic() { + return "Scripted Platform plug-in."; + } + + llvm::StringRef GetDescription() override { return GetDescriptionStatic(); } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + std::vector + GetSupportedArchitectures(const ArchSpec &process_host_arch) override; + + bool IsConnected() const override { return true; } + + lldb::ProcessSP Attach(lldb_private::ProcessAttachInfo &attach_info, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Status &error) override; + + uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos) override; + + bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info) override; + + Status LaunchProcess(ProcessLaunchInfo &launch_info) override; + + Status KillProcess(const lldb::pid_t pid) override; + + void CalculateTrapHandlerSymbolNames() override {} + +private: + inline void CheckInterpreterAndScriptObject() const { + assert(m_interpreter && "Invalid Script Interpreter."); + assert(m_script_object_sp && "Invalid Script Object."); + } + + ScriptedPlatform(const ScriptedPlatform &) = delete; + const ScriptedPlatform &operator=(const ScriptedPlatform &) = delete; + + ScriptedPlatformInterface &GetInterface() const; + + llvm::Expected + ParseProcessInfo(StructuredData::Dictionary &dict, lldb::pid_t pid) const; + + static bool IsScriptLanguageSupported(lldb::ScriptLanguage language); + + const ScriptedMetadata *m_scripted_metadata = nullptr; + lldb_private::ScriptInterpreter *m_interpreter = nullptr; + lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_PLATFORM_H Index: lldb/source/Plugins/Platform/scripted/ScriptedPlatform.cpp =================================================================== --- /dev/null +++ lldb/source/Plugins/Platform/scripted/ScriptedPlatform.cpp @@ -0,0 +1,290 @@ +//===-- ScriptedPlatform.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 "ScriptedPlatform.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/LLDBLog.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ScriptedPlatform) + +static uint32_t g_initialize_count = 0; + +static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { + ScriptLanguage::eScriptLanguagePython, +}; + +bool ScriptedPlatform::IsScriptLanguageSupported( + lldb::ScriptLanguage language) { + llvm::ArrayRef supported_languages = + llvm::makeArrayRef(g_supported_script_languages); + + return llvm::is_contained(supported_languages, language); +} + +ScriptedPlatformInterface &ScriptedPlatform::GetInterface() const { + return m_interpreter->GetScriptedPlatformInterface(); +} + +lldb::PlatformSP +ScriptedPlatform::CreateInstance(bool force, const ArchSpec *arch, + const Debugger *debugger, + const ScriptedMetadata *metadata) { + Log *log = GetLog(LLDBLog::Platform); + if (log) { + const char *arch_name; + if (arch && arch->GetArchitectureName()) + arch_name = arch->GetArchitectureName(); + else + arch_name = ""; + + const char *triple_cstr = + arch ? arch->GetTriple().getTriple().c_str() : ""; + + LLDB_LOGF(log, + "ScriptedPlatform::%s(force=%s, arch={%s,%s}, debugger=%" PRIxPTR + ")", + __PRETTY_FUNCTION__, force ? "true" : "false", arch_name, + triple_cstr, (uintptr_t)debugger); + } + + if (!debugger || !IsScriptLanguageSupported(debugger->GetScriptLanguage())) + return {}; + + if (!metadata) + return {}; + + Status error; + std::shared_ptr scripted_platform_sp = + std::make_shared(const_cast(debugger), + metadata, error); + + if (error.Success()) + return scripted_platform_sp; + + LLDB_LOGF(log, "ScriptedPlatform::%s() aborting creation of platform", + __PRETTY_FUNCTION__); + + return {}; +} + +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(); + + if (!m_interpreter) { + error.SetErrorStringWithFormat("ScriptedPlatform::%s () - ERROR: %s", + __FUNCTION__, + "Debugger has no Script Interpreter"); + return; + } + + 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; + } + + m_hostname = GetHostPlatform()->GetHostname(); + m_script_object_sp = object_sp; +} + +ScriptedPlatform::~ScriptedPlatform() {} + +void ScriptedPlatform::Initialize() { + if (g_initialize_count++ == 0) { + // NOTE: This should probably be using the driving process platform + PluginManager::RegisterPlugin(ScriptedPlatform::GetPluginNameStatic(), + ScriptedPlatform::GetDescriptionStatic(), + ScriptedPlatform::CreateInstance); + } +} + +void ScriptedPlatform::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(ScriptedPlatform::CreateInstance); + } + } +} + +std::vector +ScriptedPlatform::GetSupportedArchitectures(const ArchSpec &process_host_arch) { + std::vector result; + result.push_back(process_host_arch); + return result; +} + +lldb::ProcessSP +ScriptedPlatform::Attach(lldb_private::ProcessAttachInfo &attach_info, + lldb_private::Debugger &debugger, + lldb_private::Target *target, // Can be nullptr, if + // nullptr create a new + // target, else use + // existing one + lldb_private::Status &error) { + lldb::ProcessAttachInfoSP attach_info_sp = + std::make_shared(attach_info); + + if (!target) { + target = &debugger.GetSelectedOrDummyTarget(); + } + + ProcessSP process_sp = + GetInterface().AttachToProcess(attach_info_sp, target->shared_from_this(), + debugger.shared_from_this(), error); + if (!process_sp || error.Fail()) + return {}; + return process_sp; +} + +llvm::Expected +ScriptedPlatform::ParseProcessInfo(StructuredData::Dictionary &dict, + lldb::pid_t pid) const { + if (!dict.HasKey("name")) + return llvm::make_error( + "No 'arch' key in process info dictionary.", + llvm::inconvertibleErrorCode()); + if (!dict.HasKey("arch")) + return llvm::make_error( + "No 'arch' key in process info dictionary.", + llvm::inconvertibleErrorCode()); + + llvm::StringRef result; + if (!dict.GetValueForKeyAsString("name", result)) + return llvm::make_error( + "Couldn't extract 'name' key from process info dictionary.", + llvm::inconvertibleErrorCode()); + std::string name = result.str(); + + if (!dict.GetValueForKeyAsString("arch", result)) + return llvm::make_error( + "Couldn't extract 'arch' key from process info dictionary.", + llvm::inconvertibleErrorCode()); + const ArchSpec arch(result.data()); + if (!arch.IsValid()) + return llvm::make_error( + "Invalid 'arch' key in process info dictionary.", + llvm::inconvertibleErrorCode()); + + ProcessInstanceInfo proc_info = ProcessInstanceInfo(name.c_str(), arch, pid); + + lldb::pid_t parent = LLDB_INVALID_PROCESS_ID; + if (dict.GetValueForKeyAsInteger("parent", parent)) + proc_info.SetParentProcessID(parent); + + uint32_t uid = UINT32_MAX; + if (dict.GetValueForKeyAsInteger("uid", uid)) + proc_info.SetEffectiveUserID(uid); + + uint32_t gid = UINT32_MAX; + if (dict.GetValueForKeyAsInteger("gid", gid)) + proc_info.SetEffectiveGroupID(gid); + + return proc_info; +} + +uint32_t +ScriptedPlatform::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos) { + CheckInterpreterAndScriptObject(); + StructuredData::DictionarySP dict_sp = GetInterface().ListProcesses(); + + Status error; + if (!dict_sp) + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, "Failed to get scripted platform processes.", + error, LLDBLog::Platform); + + auto parse_process_info = [this, &proc_infos](ConstString key, + StructuredData::Object *val) { + if (!val) + return false; + + StructuredData::Dictionary *dict = val->GetAsDictionary(); + + if (!dict || !dict->IsValid()) + return false; + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + if (!llvm::to_integer(key.GetStringRef(), pid)) + return false; + + auto proc_info_or_error = ParseProcessInfo(*dict, pid); + + if (llvm::Error e = proc_info_or_error.takeError()) { + LLDB_LOGF(GetLog(LLDBLog::Platform), "%s ERROR = %s", + LLVM_PRETTY_FUNCTION, llvm::toString(std::move(e)).c_str()); + return false; + } + + if (!proc_info_or_error) { + llvm::consumeError(proc_info_or_error.takeError()); + return false; + } + + proc_infos.push_back(*proc_info_or_error); + return true; + }; + + dict_sp->ForEach(parse_process_info); + + // TODO: Use match_info to filter through processes + return proc_infos.size(); +} + +bool ScriptedPlatform::GetProcessInfo(lldb::pid_t pid, + ProcessInstanceInfo &proc_info) { + if (pid == LLDB_INVALID_PROCESS_ID) + return false; + + StructuredData::DictionarySP dict_sp = GetInterface().GetProcessInfo(pid); + + if (!dict_sp || !dict_sp->IsValid()) + return false; + + auto proc_info_or_error = ParseProcessInfo(*dict_sp.get(), pid); + + if (!proc_info_or_error) { + llvm::consumeError(proc_info_or_error.takeError()); + return false; + } + + proc_info = *proc_info_or_error; + return true; +} + +Status ScriptedPlatform::LaunchProcess(ProcessLaunchInfo &launch_info) { + return GetInterface().LaunchProcess(); +} + +Status ScriptedPlatform::KillProcess(const lldb::pid_t pid) { + return GetInterface().KillProcess(pid); +} Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.h =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedProcess.h +++ lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -91,15 +91,18 @@ private: friend class ScriptedThread; - void CheckInterpreterAndScriptObject() const; + inline void CheckInterpreterAndScriptObject() const { + lldbassert(m_interpreter && "Invalid Script Interpreter."); + lldbassert(m_script_object_sp && "Invalid Script Object."); + } + ScriptedProcessInterface &GetInterface() const; + static bool IsScriptLanguageSupported(lldb::ScriptLanguage language); - // Member variables. const ScriptedMetadata m_scripted_metadata; lldb_private::ScriptInterpreter *m_interpreter = nullptr; lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr; - //@} }; } // namespace lldb_private Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -50,11 +50,6 @@ return llvm::is_contained(supported_languages, language); } -void ScriptedProcess::CheckInterpreterAndScriptObject() const { - lldbassert(m_interpreter && "Invalid Script Interpreter."); - lldbassert(m_script_object_sp && "Invalid Script Object."); -} - lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *file, Index: lldb/source/Plugins/Process/scripted/ScriptedThread.h =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedThread.h +++ lldb/source/Plugins/Process/scripted/ScriptedThread.h @@ -61,7 +61,11 @@ StructuredData::ObjectSP FetchThreadExtendedInfo() override; private: - void CheckInterpreterAndScriptObject() const; + inline void CheckInterpreterAndScriptObject() const { + assert(m_script_object_sp && "Invalid Script Object."); + assert(GetInterface() && "Invalid Scripted Thread Interface."); + } + lldb::ScriptedThreadInterfaceSP GetInterface() const; ScriptedThread(const ScriptedThread &) = delete; Index: lldb/source/Plugins/Process/scripted/ScriptedThread.cpp =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -23,11 +23,6 @@ using namespace lldb; using namespace lldb_private; -void ScriptedThread::CheckInterpreterAndScriptObject() const { - lldbassert(m_script_object_sp && "Invalid Script Object."); - lldbassert(GetInterface() && "Invalid Scripted Thread Interface."); -} - llvm::Expected> ScriptedThread::Create(ScriptedProcess &process, StructuredData::Generic *script_object) { Index: lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -76,7 +76,8 @@ PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp); PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options); PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx); - +PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp); +PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp); PythonObject ToSWIGWrapper(std::unique_ptr value_sb); PythonObject ToSWIGWrapper(std::unique_ptr stream_sb); PythonObject ToSWIGWrapper(std::unique_ptr data_sb); @@ -88,6 +89,11 @@ } // namespace python void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBProcess(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBDebugger(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBTarget(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h @@ -32,7 +32,10 @@ StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override; - Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) override; + lldb::ProcessSP AttachToProcess(lldb::ProcessAttachInfoSP attach_info_sp, + lldb::TargetSP target_sp, + lldb::DebuggerSP debugger_sp, + Status &error) override; Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) override; Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp @@ -89,16 +89,29 @@ return dict_sp; } -Status ScriptedPlatformPythonInterface::AttachToProcess( - ProcessAttachInfoSP attach_info) { - // FIXME: Pass `attach_info` to method call - return GetStatusFromMethod("attach_to_process"); +lldb::ProcessSP ScriptedPlatformPythonInterface::AttachToProcess( + lldb::ProcessAttachInfoSP attach_info_sp, lldb::TargetSP target_sp, + lldb::DebuggerSP debugger_sp, Status &error) { + Status py_error; + ProcessSP process_sp = + Dispatch("attach_to_process", py_error, attach_info_sp, + target_sp, debugger_sp, error); + + if (!process_sp || error.Fail()) { + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return process_sp; } Status ScriptedPlatformPythonInterface::LaunchProcess( - ProcessLaunchInfoSP launch_info) { - // FIXME: Pass `launch_info` to method call - return GetStatusFromMethod("launch_process"); + ProcessLaunchInfoSP launch_info_sp) { + return GetStatusFromMethod("launch_process", launch_info_sp); } Status ScriptedPlatformPythonInterface::KillProcess(lldb::pid_t pid) { Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -117,6 +117,22 @@ return python::ToSWIGWrapper(arg); } + python::PythonObject Transform(lldb::TargetSP arg) { + return python::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::DebuggerSP arg) { + return python::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { + return python::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { + return python::ToSWIGWrapper(arg); + } + template void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { // If U is not a PythonObject, don't touch it! @@ -198,6 +214,29 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject( python::PythonObject &p, Status &error); +template <> +lldb::ProcessSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +lldb::DebuggerSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +lldb::TargetSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); + template <> lldb::DataExtractorSP ScriptedPythonInterface::ExtractValueFromPythonObject( Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp @@ -71,6 +71,81 @@ return m_interpreter.GetDataExtractorFromSBData(*sb_data); } +template <> +lldb::ProcessSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + lldb::SBProcess *sb_process = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBProcess(p.get())); + + if (!sb_process) { + error.SetErrorString("Couldn't cast lldb::SBProcess to lldb::ProcessSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBProcess(*sb_process); +} + +template <> +lldb::DebuggerSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + lldb::SBDebugger *sb_debugger = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBDebugger(p.get())); + + if (!sb_debugger) { + error.SetErrorString("Couldn't cast lldb::SBDebugger to lldb::DebuggerSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBDebugger(*sb_debugger); +} + +template <> +lldb::TargetSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + lldb::SBTarget *sb_target = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBTarget(p.get())); + + if (!sb_target) { + error.SetErrorString("Couldn't cast lldb::SBTarget to lldb::TargetSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBTarget(*sb_target); +} + +template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBAttachInfo *sb_attach_info = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBAttachInfo(p.get())); + + if (!sb_attach_info) { + error.SetErrorString( + "Couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBAttachInfo(*sb_attach_info); +} + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBLaunchInfo(p.get())); + + if (!sb_launch_info) { + error.SetErrorString( + "Couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBLaunchInfo(*sb_launch_info); +} + template <> std::optional ScriptedPythonInterface::ExtractValueFromPythonObject< Index: lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py =================================================================== --- lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py +++ lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py @@ -23,6 +23,9 @@ def get_process_info(self, pid): return self.processes[pid] + def attach_to_process(self, attach_info, target, debugger, error): + return None + def launch_process(self, launch_info): return lldb.SBError() Index: lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp =================================================================== --- lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp +++ lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp @@ -139,6 +139,26 @@ return nullptr; } +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBProcess(PyObject *data) { + return nullptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBDebugger(PyObject *data) { + return nullptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBTarget(PyObject *data) { + return nullptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data) { + return nullptr; +} + +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data) { + return nullptr; +} + void *lldb_private::LLDBSWIGPython_CastPyObjectToSBError(PyObject *data) { return nullptr; }