Index: lldb/examples/python/scripted_process/scripted_process.py =================================================================== --- lldb/examples/python/scripted_process/scripted_process.py +++ lldb/examples/python/scripted_process/scripted_process.py @@ -163,6 +163,14 @@ """ return lldb.SBError() + def attach(self): + """ Simulate the scripted process attach. + + Returns: + lldb.SBError: An `lldb.SBError` with error code 0. + """ + return lldb.SBError() + def resume(self): """ Simulate the scripted process resume. Index: lldb/include/lldb/Host/ProcessLaunchInfo.h =================================================================== --- lldb/include/lldb/Host/ProcessLaunchInfo.h +++ lldb/include/lldb/Host/ProcessLaunchInfo.h @@ -20,7 +20,6 @@ #include "lldb/Host/PseudoTerminal.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/ProcessInfo.h" -#include "lldb/Utility/StructuredData.h" namespace lldb_private { @@ -144,28 +143,6 @@ return m_flags.Test(lldb::eLaunchFlagDetachOnError); } - bool IsScriptedProcess() const { - return !m_scripted_process_class_name.empty(); - } - - std::string GetScriptedProcessClassName() const { - return m_scripted_process_class_name; - } - - void SetScriptedProcessClassName(std::string name) { - m_scripted_process_class_name = name; - } - - lldb_private::StructuredData::DictionarySP - GetScriptedProcessDictionarySP() const { - return m_scripted_process_dictionary_sp; - } - - void SetScriptedProcessDictionarySP( - lldb_private::StructuredData::DictionarySP dictionary_sp) { - m_scripted_process_dictionary_sp = dictionary_sp; - } - protected: FileSpec m_working_dir; std::string m_plugin_name; @@ -179,11 +156,6 @@ // meaning to the upper levels of lldb. lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; - std::string m_scripted_process_class_name; // The name of the class that will - // manage a scripted process. - StructuredData::DictionarySP - m_scripted_process_dictionary_sp; // A dictionary that holds key/value - // pairs passed to the scripted process. }; } Index: lldb/include/lldb/Interpreter/ScriptedProcessInterface.h =================================================================== --- lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -30,6 +30,8 @@ virtual StructuredData::DictionarySP GetCapabilities() { return {}; } + virtual Status Attach() { return Status("ScriptedProcess did not attach"); } + virtual Status Launch() { return Status("ScriptedProcess did not launch"); } virtual Status Resume() { return Status("ScriptedProcess did not resume"); } Index: lldb/include/lldb/Target/Process.h =================================================================== --- lldb/include/lldb/Target/Process.h +++ lldb/include/lldb/Target/Process.h @@ -192,28 +192,6 @@ lldb::ListenerSP GetListenerForProcess(Debugger &debugger); - bool IsScriptedProcess() const { - return !m_scripted_process_class_name.empty(); - } - - std::string GetScriptedProcessClassName() const { - return m_scripted_process_class_name; - } - - void SetScriptedProcessClassName(std::string name) { - m_scripted_process_class_name = name; - } - - lldb_private::StructuredData::DictionarySP - GetScriptedProcessDictionarySP() const { - return m_scripted_process_dictionary_sp; - } - - void SetScriptedProcessDictionarySP( - lldb_private::StructuredData::DictionarySP dictionary_sp) { - m_scripted_process_dictionary_sp = dictionary_sp; - } - protected: lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; @@ -231,11 +209,6 @@ false; // Use an async attach where we start the attach and return // immediately (used by GUI programs with --waitfor so they can // call SBProcess::Stop() to cancel attach) - std::string m_scripted_process_class_name; // The name of the class that will - // manage a scripted process. - StructuredData::DictionarySP - m_scripted_process_dictionary_sp; // A dictionary that holds key/value - // pairs passed to the scripted process. }; // This class tracks the Modification state of the process. Things that can Index: lldb/include/lldb/Target/Target.h =================================================================== --- lldb/include/lldb/Target/Target.h +++ lldb/include/lldb/Target/Target.h @@ -1428,6 +1428,8 @@ return *m_frame_recognizer_manager_up; } + void SaveScriptedLaunchInfo(lldb_private::ProcessInfo &process_info); + /// Add a signal for the target. This will get copied over to the process /// if the signal exists on that target. Only the values with Yes and No are /// set, Calculate values will be ignored. Index: lldb/include/lldb/Utility/ProcessInfo.h =================================================================== --- lldb/include/lldb/Utility/ProcessInfo.h +++ lldb/include/lldb/Utility/ProcessInfo.h @@ -14,6 +14,7 @@ #include "lldb/Utility/Environment.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/StructuredData.h" #include namespace lldb_private { @@ -86,6 +87,28 @@ Environment &GetEnvironment() { return m_environment; } const Environment &GetEnvironment() const { return m_environment; } + bool IsScriptedProcess() const { + return !m_scripted_process_class_name.empty(); + } + + std::string GetScriptedProcessClassName() const { + return m_scripted_process_class_name; + } + + void SetScriptedProcessClassName(std::string name) { + m_scripted_process_class_name = name; + } + + lldb_private::StructuredData::DictionarySP + GetScriptedProcessDictionarySP() const { + return m_scripted_process_dictionary_sp; + } + + void SetScriptedProcessDictionarySP( + lldb_private::StructuredData::DictionarySP dictionary_sp) { + m_scripted_process_dictionary_sp = dictionary_sp; + } + protected: FileSpec m_executable; std::string m_arg0; // argv[0] if supported. If empty, then use m_executable. @@ -97,6 +120,11 @@ uint32_t m_gid = UINT32_MAX; ArchSpec m_arch; lldb::pid_t m_pid = LLDB_INVALID_PROCESS_ID; + std::string m_scripted_process_class_name; // The name of the class that will + // manage a scripted process. + StructuredData::DictionarySP + m_scripted_process_dictionary_sp; // A dictionary that holds key/value + // pairs passed to the scripted process. }; // ProcessInstanceInfo Index: lldb/source/Host/common/ProcessLaunchInfo.cpp =================================================================== --- lldb/source/Host/common/ProcessLaunchInfo.cpp +++ lldb/source/Host/common/ProcessLaunchInfo.cpp @@ -32,8 +32,7 @@ ProcessLaunchInfo::ProcessLaunchInfo() : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0), m_file_actions(), m_pty(new PseudoTerminal), m_monitor_callback(nullptr), - m_listener_sp(), m_hijack_listener_sp(), m_scripted_process_class_name(), - m_scripted_process_dictionary_sp() {} + m_listener_sp(), m_hijack_listener_sp() {} ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, @@ -41,8 +40,7 @@ const FileSpec &working_directory, uint32_t launch_flags) : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags), - m_file_actions(), m_pty(new PseudoTerminal), - m_scripted_process_class_name(), m_scripted_process_dictionary_sp() { + m_file_actions(), m_pty(new PseudoTerminal) { if (stdin_file_spec) { FileAction file_action; const bool read = true; Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.h =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedProcess.h +++ lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -51,6 +51,15 @@ Status DoResume() override; + Status DoAttachToProcessWithID(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) override; + + Status + DoAttachToProcessWithName(const char *process_name, + const ProcessAttachInfo &attach_info) override; + + void DidAttach(ArchSpec &process_arch) override; + Status DoDestroy() override; void RefreshStateAfterStop() override; @@ -88,6 +97,8 @@ Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override; + Status DoAttach(); + private: friend class ScriptedThread; Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -195,6 +195,38 @@ return error; } +Status ScriptedProcess::DoAttach() { + CheckInterpreterAndScriptObject(); + + Status error = GetInterface().Attach(); + SetPrivateState(eStateRunning); + + if (error.Fail()) + return error; + + SetPrivateState(eStateStopped); + // NOTE: We need to set the PID before finishing to attach otherwise we will + // hit an assert when calling the attach completion handler. + DidLaunch(); + + return {}; +} + +Status +ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid, + const ProcessAttachInfo &attach_info) { + return DoAttach(); +} + +Status ScriptedProcess::DoAttachToProcessWithName( + const char *process_name, const ProcessAttachInfo &attach_info) { + return DoAttach(); +} + +void ScriptedProcess::DidAttach(ArchSpec &process_arch) { + process_arch = GetArchitecture(); +} + Status ScriptedProcess::DoStop() { CheckInterpreterAndScriptObject(); Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -31,6 +31,8 @@ StructuredData::DictionarySP GetCapabilities() override; + Status Attach() override; + Status Launch() override; Status Resume() override; Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp =================================================================== --- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -67,6 +67,10 @@ return dict; } +Status ScriptedProcessPythonInterface::Attach() { + return GetStatusFromMethod("attach"); +} + Status ScriptedProcessPythonInterface::Launch() { return GetStatusFromMethod("launch"); } Index: lldb/source/Target/Target.cpp =================================================================== --- lldb/source/Target/Target.cpp +++ lldb/source/Target/Target.cpp @@ -3080,6 +3080,22 @@ void Target::ClearAllLoadedSections() { m_section_load_history.Clear(); } +void Target::SaveScriptedLaunchInfo(lldb_private::ProcessInfo &process_info) { + if (process_info.IsScriptedProcess()) { + // Only copy scripted process launch options. + ProcessLaunchInfo &default_launch_info = const_cast( + GetGlobalProperties().GetProcessLaunchInfo()); + + default_launch_info.SetProcessPluginName("ScriptedProcess"); + default_launch_info.SetScriptedProcessClassName( + process_info.GetScriptedProcessClassName()); + default_launch_info.SetScriptedProcessDictionarySP( + process_info.GetScriptedProcessDictionarySP()); + + SetProcessLaunchInfo(default_launch_info); + } +} + Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { m_stats.SetLaunchOrAttachTime(); Status error; @@ -3109,19 +3125,7 @@ launch_info.GetFlags().Set(eLaunchFlagDebug); - if (launch_info.IsScriptedProcess()) { - // Only copy scripted process launch options. - ProcessLaunchInfo &default_launch_info = const_cast( - GetGlobalProperties().GetProcessLaunchInfo()); - - default_launch_info.SetProcessPluginName("ScriptedProcess"); - default_launch_info.SetScriptedProcessClassName( - launch_info.GetScriptedProcessClassName()); - default_launch_info.SetScriptedProcessDictionarySP( - launch_info.GetScriptedProcessDictionarySP()); - - SetProcessLaunchInfo(launch_info); - } + SaveScriptedLaunchInfo(launch_info); // Get the value of synchronous execution here. If you wait till after you // have started to run, then you could have hit a breakpoint, whose command @@ -3334,11 +3338,12 @@ Status error; if (state != eStateConnected && platform_sp != nullptr && - platform_sp->CanDebugProcess()) { + platform_sp->CanDebugProcess() && !attach_info.IsScriptedProcess()) { SetPlatform(platform_sp); process_sp = platform_sp->Attach(attach_info, GetDebugger(), this, error); } else { if (state != eStateConnected) { + SaveScriptedLaunchInfo(attach_info); const char *plugin_name = attach_info.GetProcessPluginName(); process_sp = CreateProcess(attach_info.GetListenerForProcess(GetDebugger()), Index: lldb/source/Utility/ProcessInfo.cpp =================================================================== --- lldb/source/Utility/ProcessInfo.cpp +++ lldb/source/Utility/ProcessInfo.cpp @@ -21,12 +21,14 @@ using namespace lldb_private; ProcessInfo::ProcessInfo() - : m_executable(), m_arguments(), m_environment(), m_arch() {} + : m_executable(), m_arguments(), m_environment(), m_arch(), + m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {} ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid) : m_executable(name), m_arguments(), m_environment(), m_arch(arch), - m_pid(pid) {} + m_pid(pid), m_scripted_process_class_name(), + m_scripted_process_dictionary_sp() {} void ProcessInfo::Clear() { m_executable.Clear(); @@ -36,6 +38,8 @@ m_gid = UINT32_MAX; m_arch.Clear(); m_pid = LLDB_INVALID_PROCESS_ID; + m_scripted_process_class_name.clear(); + m_scripted_process_dictionary_sp.reset(); } const char *ProcessInfo::GetName() const {