[lldb/Plugins] Add Attach capabilities to ScriptedProcess

This patch adds process attach capabilities to the ScriptedProcess
plugin. This doesn't really expects a PID or process name, since the
process state is already script, however, this allows to create a
scripted process without requiring to have an executuble in the target.

In order to do so, this patch also turns the scripted process related
getters and setters from the `ProcessLaunchInfo` and
`ProcessAttachInfo` classes to a `ScriptedMetadata` instance and moves
it in the `ProcessInfo` class, so it can be accessed interchangeably.

This also adds the necessary SWIG wrappers to convert the internal
`Process{Attach,Launch}InfoSP` into a `SB{Attach,Launch}Info` to pass it
as argument the scripted process python implementation and convert it
back to the internal representation.

rdar://104577406

Differential Revision: https://reviews.llvm.org/D143104

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
This commit is contained in:
Med Ismail Bennani 2023-03-03 15:17:59 -08:00
parent 3014a1c5a1
commit b9d4c94a60
31 changed files with 316 additions and 109 deletions

View File

@ -93,6 +93,16 @@ PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx) {
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<lldb::SBCommandReturnObject>
ToSWIGWrapper(CommandReturnObject &cmd_retobj) {
return ScopedPythonObject<lldb::SBCommandReturnObject>(

View File

@ -716,6 +716,30 @@ void *lldb_private::LLDBSWIGPython_CastPyObjectToSBData(PyObject * data) {
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;

View File

@ -163,6 +163,18 @@ class ScriptedProcess(metaclass=ABCMeta):
"""
return lldb.SBError()
def attach(self, attach_info):
""" Simulate the scripted process attach.
Args:
attach_info (lldb.SBAttachInfo): The information related to the
process we're attaching to.
Returns:
lldb.SBError: An `lldb.SBError` with error code 0.
"""
return lldb.SBError()
def resume(self):
""" Simulate the scripted process resume.

View File

@ -11,6 +11,10 @@
#include "lldb/API/SBDefines.h"
namespace lldb_private {
class ScriptInterpreter;
}
namespace lldb {
class SBTarget;
@ -175,6 +179,8 @@ public:
protected:
friend class SBTarget;
friend class lldb_private::ScriptInterpreter;
lldb_private::ProcessAttachInfo &ref();
ProcessAttachInfoSP m_opaque_sp;

View File

@ -13,6 +13,7 @@
namespace lldb_private {
class SBLaunchInfoImpl;
class ScriptInterpreter;
}
namespace lldb {
@ -190,6 +191,8 @@ protected:
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);

View File

@ -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 @@ public:
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 @@ protected:
// 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.
};
}

View File

@ -9,8 +9,10 @@
#ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H
#define LLDB_INTERPRETER_SCRIPTINTERPRETER_H
#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBData.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/PluginInterface.h"
@ -585,6 +587,12 @@ public:
Status GetStatusFromSBError(const lldb::SBError &error) const;
lldb::ProcessAttachInfoSP
GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const;
lldb::ProcessLaunchInfoSP
GetOpaqueTypeFromSBLaunchInfo(const lldb::SBLaunchInfo &launch_info) const;
std::optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo(
const lldb::SBMemoryRegionInfo &mem_region) const;

View File

@ -12,7 +12,7 @@
#include "OptionGroupPythonClassWithDict.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/StructuredData.h"
namespace lldb_private {
@ -22,9 +22,12 @@ public:
StructuredData::DictionarySP dict_sp)
: m_class_name(class_name.data()), m_args_sp(dict_sp) {}
ScriptedMetadata(const ProcessLaunchInfo &launch_info) {
m_class_name = launch_info.GetScriptedProcessClassName();
m_args_sp = launch_info.GetScriptedProcessDictionarySP();
ScriptedMetadata(const ProcessInfo &process_info) {
lldb::ScriptedMetadataSP metadata_sp = process_info.GetScriptedMetadata();
if (metadata_sp) {
m_class_name = metadata_sp->GetClassName();
m_args_sp = metadata_sp->GetArgsSP();
}
}
ScriptedMetadata(const OptionGroupPythonClassWithDict &option_group) {
@ -33,6 +36,8 @@ public:
m_args_sp = opt_group.GetStructuredData();
}
explicit operator bool() const { return !m_class_name.empty(); }
llvm::StringRef GetClassName() const { return m_class_name; }
StructuredData::DictionarySP GetArgsSP() const { return m_args_sp; }

View File

@ -30,6 +30,10 @@ public:
virtual StructuredData::DictionarySP GetCapabilities() { return {}; }
virtual Status Attach(const ProcessAttachInfo &attach_info) {
return Status("ScriptedProcess did not attach");
}
virtual Status Launch() { return Status("ScriptedProcess did not launch"); }
virtual Status Resume() { return Status("ScriptedProcess did not resume"); }

View File

@ -193,28 +193,6 @@ public:
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;
@ -232,11 +210,6 @@ protected:
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

View File

@ -1430,6 +1430,8 @@ public:
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.

View File

@ -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 <vector>
namespace lldb_private {
@ -86,6 +87,16 @@ public:
Environment &GetEnvironment() { return m_environment; }
const Environment &GetEnvironment() const { return m_environment; }
bool IsScriptedProcess() const;
lldb::ScriptedMetadataSP GetScriptedMetadata() const {
return m_scripted_metadata_sp;
}
void SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp) {
m_scripted_metadata_sp = metadata_sp;
}
protected:
FileSpec m_executable;
std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
@ -97,6 +108,7 @@ protected:
uint32_t m_gid = UINT32_MAX;
ArchSpec m_arch;
lldb::pid_t m_pid = LLDB_INVALID_PROCESS_ID;
lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr;
};
// ProcessInstanceInfo

View File

@ -181,6 +181,7 @@ class RichManglingContext;
class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
class ScriptedMetadata;
class ScriptedPlatformInterface;
class ScriptedProcessInterface;
class ScriptedThreadInterface;
@ -380,6 +381,7 @@ typedef std::shared_ptr<lldb_private::RecognizedStackFrame>
typedef std::shared_ptr<lldb_private::ScriptSummaryFormat>
ScriptSummaryFormatSP;
typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
typedef std::shared_ptr<lldb_private::ScriptedMetadata> ScriptedMetadataSP;
typedef std::unique_ptr<lldb_private::ScriptedPlatformInterface>
ScriptedPlatformInterfaceUP;
typedef std::unique_ptr<lldb_private::ScriptedProcessInterface>

View File

@ -11,6 +11,7 @@
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/Interpreter/ScriptedMetadata.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Instrumentation.h"
@ -256,25 +257,41 @@ void SBAttachInfo::SetListener(SBListener &listener) {
const char *SBAttachInfo::GetScriptedProcessClassName() const {
LLDB_INSTRUMENT_VA(this);
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
if (!metadata_sp || !*metadata_sp)
return nullptr;
// Constify this string so that it is saved in the string pool. Otherwise it
// would be freed when this function goes out of scope.
ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str());
ConstString class_name(metadata_sp->GetClassName().data());
return class_name.AsCString();
}
void SBAttachInfo::SetScriptedProcessClassName(const char *class_name) {
LLDB_INSTRUMENT_VA(this, class_name);
m_opaque_sp->SetScriptedProcessClassName(class_name);
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
if (!metadata_sp)
metadata_sp = std::make_shared<ScriptedMetadata>(class_name, nullptr);
else
metadata_sp = std::make_shared<ScriptedMetadata>(class_name,
metadata_sp->GetArgsSP());
m_opaque_sp->SetScriptedMetadata(metadata_sp);
}
lldb::SBStructuredData SBAttachInfo::GetScriptedProcessDictionary() const {
LLDB_INSTRUMENT_VA(this);
lldb_private::StructuredData::DictionarySP dict_sp =
m_opaque_sp->GetScriptedProcessDictionarySP();
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
SBStructuredData data;
if (!metadata_sp)
return data;
lldb_private::StructuredData::DictionarySP dict_sp = metadata_sp->GetArgsSP();
data.m_impl_up->SetObjectSP(dict_sp);
return data;
@ -282,6 +299,7 @@ lldb::SBStructuredData SBAttachInfo::GetScriptedProcessDictionary() const {
void SBAttachInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
LLDB_INSTRUMENT_VA(this, dict);
if (!dict.IsValid() || !dict.m_impl_up)
return;
@ -295,5 +313,13 @@ void SBAttachInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid)
return;
m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp);
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
if (!metadata_sp)
metadata_sp = std::make_shared<ScriptedMetadata>("", dict_sp);
else
metadata_sp = std::make_shared<ScriptedMetadata>(
metadata_sp->GetClassName(), dict_sp);
m_opaque_sp->SetScriptedMetadata(metadata_sp);
}

View File

@ -17,6 +17,7 @@
#include "lldb/API/SBStructuredData.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Interpreter/ScriptedMetadata.h"
using namespace lldb;
using namespace lldb_private;
@ -331,25 +332,36 @@ bool SBLaunchInfo::GetDetachOnError() const {
const char *SBLaunchInfo::GetScriptedProcessClassName() const {
LLDB_INSTRUMENT_VA(this);
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
if (!metadata_sp || !*metadata_sp)
return nullptr;
// Constify this string so that it is saved in the string pool. Otherwise it
// would be freed when this function goes out of scope.
ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str());
ConstString class_name(metadata_sp->GetClassName().data());
return class_name.AsCString();
}
void SBLaunchInfo::SetScriptedProcessClassName(const char *class_name) {
LLDB_INSTRUMENT_VA(this, class_name);
m_opaque_sp->SetScriptedProcessClassName(class_name);
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
StructuredData::DictionarySP dict_sp =
metadata_sp ? metadata_sp->GetArgsSP() : nullptr;
metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
m_opaque_sp->SetScriptedMetadata(metadata_sp);
}
lldb::SBStructuredData SBLaunchInfo::GetScriptedProcessDictionary() const {
LLDB_INSTRUMENT_VA(this);
lldb_private::StructuredData::DictionarySP dict_sp =
m_opaque_sp->GetScriptedProcessDictionarySP();
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
SBStructuredData data;
if (!metadata_sp)
return data;
lldb_private::StructuredData::DictionarySP dict_sp = metadata_sp->GetArgsSP();
data.m_impl_up->SetObjectSP(dict_sp);
return data;
@ -370,5 +382,8 @@ void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid)
return;
m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp);
ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
llvm::StringRef class_name = metadata_sp ? metadata_sp->GetClassName() : "";
metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
m_opaque_sp->SetScriptedMetadata(metadata_sp);
}

View File

@ -434,7 +434,8 @@ lldb::SBProcess SBTarget::Attach(SBAttachInfo &sb_attach_info, SBError &error) {
if (target_sp) {
ProcessAttachInfo &attach_info = sb_attach_info.ref();
if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid()) {
if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid() &&
!attach_info.IsScriptedProcess()) {
PlatformSP platform_sp = target_sp->GetPlatform();
// See if we can pre-verify if a process exists or not
if (platform_sp && platform_sp->IsConnected()) {

View File

@ -1188,10 +1188,9 @@ protected:
if (!m_class_options.GetName().empty()) {
m_options.launch_info.SetProcessPluginName("ScriptedProcess");
m_options.launch_info.SetScriptedProcessClassName(
m_class_options.GetName());
m_options.launch_info.SetScriptedProcessDictionarySP(
m_class_options.GetStructuredData());
ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
m_class_options.GetName(), m_class_options.GetStructuredData());
m_options.launch_info.SetScriptedMetadata(metadata_sp);
target->SetProcessLaunchInfo(m_options.launch_info);
}
@ -1608,10 +1607,9 @@ public:
if (!m_class_options.GetName().empty()) {
m_options.attach_info.SetProcessPluginName("ScriptedProcess");
m_options.attach_info.SetScriptedProcessClassName(
m_class_options.GetName());
m_options.attach_info.SetScriptedProcessDictionarySP(
m_class_options.GetStructuredData());
ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
m_class_options.GetName(), m_class_options.GetStructuredData());
m_options.attach_info.SetScriptedMetadata(metadata_sp);
}
Status err;

View File

@ -201,10 +201,9 @@ protected:
if (!m_class_options.GetName().empty()) {
m_options.launch_info.SetProcessPluginName("ScriptedProcess");
m_options.launch_info.SetScriptedProcessClassName(
m_class_options.GetName());
m_options.launch_info.SetScriptedProcessDictionarySP(
m_class_options.GetStructuredData());
ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
m_class_options.GetName(), m_class_options.GetStructuredData());
m_options.launch_info.SetScriptedMetadata(metadata_sp);
target->SetProcessLaunchInfo(m_options.launch_info);
}
@ -356,10 +355,9 @@ protected:
if (!m_class_options.GetName().empty()) {
m_options.attach_info.SetProcessPluginName("ScriptedProcess");
m_options.attach_info.SetScriptedProcessClassName(
m_class_options.GetName());
m_options.attach_info.SetScriptedProcessDictionarySP(
m_class_options.GetStructuredData());
ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
m_class_options.GetName(), m_class_options.GetStructuredData());
m_options.attach_info.SetScriptedMetadata(metadata_sp);
}
// Record the old executable module, we want to issue a warning if the

View File

@ -32,8 +32,7 @@ using namespace lldb_private;
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 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
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;
@ -171,8 +169,6 @@ void ProcessLaunchInfo::Clear() {
m_resume_count = 0;
m_listener_sp.reset();
m_hijack_listener_sp.reset();
m_scripted_process_class_name.clear();
m_scripted_process_dictionary_sp.reset();
}
void ProcessLaunchInfo::NoOpMonitorCallback(lldb::pid_t pid, int signal,

View File

@ -80,6 +80,17 @@ ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const {
return data.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<ProcessLaunchInfo>(
*reinterpret_cast<ProcessLaunchInfo *>(launch_info.m_opaque_sp.get()));
}
Status
ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {
if (error.m_opaque_up)

View File

@ -195,6 +195,34 @@ Status ScriptedProcess::DoResume() {
return error;
}
Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
Status error = GetInterface().Attach(attach_info);
SetPrivateState(eStateRunning);
SetPrivateState(eStateStopped);
if (error.Fail())
return error;
// 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(attach_info);
}
Status ScriptedProcess::DoAttachToProcessWithName(
const char *process_name, const ProcessAttachInfo &attach_info) {
return DoAttach(attach_info);
}
void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
process_arch = GetArchitecture();
}
Status ScriptedProcess::DoStop() {
Log *log = GetLog(LLDBLog::Process);

View File

@ -51,6 +51,15 @@ public:
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;
@ -90,6 +99,8 @@ protected:
Status DoGetMemoryRegionInfo(lldb::addr_t load_addr,
MemoryRegionInfo &range_info) override;
Status DoAttach(const ProcessAttachInfo &attach_info);
private:
friend class ScriptedThread;

View File

@ -77,6 +77,9 @@ 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<lldb::SBValue> value_sb);
PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb);
PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb);
@ -88,6 +91,8 @@ python::ScopedPythonObject<lldb::SBEvent> ToSWIGWrapper(Event *event);
} // namespace python
void *LLDBSWIGPython_CastPyObjectToSBData(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);

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Config.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"
@ -67,6 +68,13 @@ StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() {
return dict;
}
Status
ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) {
lldb::ProcessAttachInfoSP attach_info_sp =
std::make_shared<ProcessAttachInfo>(attach_info);
return GetStatusFromMethod("attach", attach_info_sp);
}
Status ScriptedProcessPythonInterface::Launch() {
return GetStatusFromMethod("launch");
}

View File

@ -31,6 +31,8 @@ public:
StructuredData::DictionarySP GetCapabilities() override;
Status Attach(const ProcessAttachInfo &attach_info) override;
Status Launch() override;
Status Resume() override;

View File

@ -15,7 +15,6 @@
// LLDB Python header must be included first
#include "lldb-python.h"
#include "SWIGPythonBridge.h"
#include "ScriptInterpreterPythonImpl.h"
#include "ScriptedPythonInterface.h"
#include <optional>
@ -71,6 +70,36 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
return m_interpreter.GetDataExtractorFromSBData(*sb_data);
}
template <>
lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) {
lldb::SBAttachInfo *sb_attach_info = reinterpret_cast<lldb::SBAttachInfo *>(
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<lldb::SBLaunchInfo *>(
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<MemoryRegionInfo>
ScriptedPythonInterface::ExtractValueFromPythonObject<

View File

@ -117,6 +117,14 @@ protected:
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 <typename T, typename U>
void ReverseTransform(T &original_arg, U transformed_arg, Status &error) {
// If U is not a PythonObject, don't touch it!
@ -198,6 +206,14 @@ template <>
Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
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<lldb::DataExtractorSP>(

View File

@ -3079,6 +3079,17 @@ bool Target::SetSectionUnloaded(const lldb::SectionSP &section_sp,
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<ProcessLaunchInfo &>(
GetGlobalProperties().GetProcessLaunchInfo());
default_launch_info.SetProcessPluginName("ScriptedProcess");
default_launch_info.SetScriptedMetadata(process_info.GetScriptedMetadata());
SetProcessLaunchInfo(default_launch_info);
}
}
Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
m_stats.SetLaunchOrAttachTime();
Status error;
@ -3108,19 +3119,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
launch_info.GetFlags().Set(eLaunchFlagDebug);
if (launch_info.IsScriptedProcess()) {
// Only copy scripted process launch options.
ProcessLaunchInfo &default_launch_info = const_cast<ProcessLaunchInfo &>(
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
@ -3333,11 +3332,12 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
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()),

View File

@ -8,6 +8,7 @@
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Interpreter/ScriptedMetadata.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
@ -36,6 +37,7 @@ void ProcessInfo::Clear() {
m_gid = UINT32_MAX;
m_arch.Clear();
m_pid = LLDB_INVALID_PROCESS_ID;
m_scripted_metadata_sp.reset();
}
const char *ProcessInfo::GetName() const {
@ -109,6 +111,10 @@ void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {
}
}
bool ProcessInfo::IsScriptedProcess() const {
return m_scripted_metadata_sp && *m_scripted_metadata_sp;
}
void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
if (m_pid != LLDB_INVALID_PROCESS_ID)
s.Printf(" pid = %" PRIu64 "\n", m_pid);

View File

@ -137,8 +137,14 @@ class ScriptedProcesTestCase(TestBase):
target_1 = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
self.assertTrue(target_1, VALID_TARGET)
# We still need to specify a PID when attaching even for scripted processes
attach_info = lldb.SBAttachInfo(42)
attach_info.SetProcessPluginName("ScriptedProcess")
attach_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess")
error = lldb.SBError()
process_1 = target_1.Launch(launch_info, error)
process_1 = target_1.Attach(attach_info, error)
self.assertTrue(process_1 and process_1.IsValid(), PROCESS_IS_VALID)
self.assertEqual(process_1.GetProcessID(), 42)
self.assertEqual(process_1.GetNumThreads(), 1)

View File

@ -139,6 +139,14 @@ void *lldb_private::LLDBSWIGPython_CastPyObjectToSBData(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;
}
@ -268,3 +276,13 @@ bool lldb_private::LLDBSwigPythonStopHookCallHandleStop(
python::PythonObject lldb_private::python::ToSWIGWrapper(const Status &status) {
return python::PythonObject();
}
python::PythonObject
lldb_private::python::ToSWIGWrapper(lldb::ProcessAttachInfoSP) {
return python::PythonObject();
}
python::PythonObject
lldb_private::python::ToSWIGWrapper(lldb::ProcessLaunchInfoSP) {
return python::PythonObject();
}