[lldb] Add a way to get a scripted process implementation from the SBAPI

This patch introduces a new `GetScriptedImplementation` method to the
SBProcess class in the SBAPI. It will allow users of Scripted Processes to
fetch the scripted implementation object from to script interpreter to be
able to interact with it directly (without having to go through lldb).

This allows to user to perform action that are not specified in the
scripted process interface, like calling un-specified methods, but also
to enrich the implementation, by passing it complex objects.

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

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
This commit is contained in:
Med Ismail Bennani
2023-02-03 12:28:47 -08:00
parent a48c4a45e0
commit c192803304
11 changed files with 64 additions and 0 deletions

View File

@@ -344,6 +344,12 @@ public:
bool
GetDescription (lldb::SBStream &description);
%feature("autodoc", "
Returns the implementation object of the process plugin if available. None
otherwise.") GetScriptedImplementation;
ScriptedObject
GetScriptedImplementation();
%feature("autodoc", "
Returns the process' extended crash information.") GetExtendedCrashInformation;
lldb::SBStructuredData

View File

@@ -54,6 +54,16 @@
free((char *) $1);
}
%typemap(out) lldb::ScriptedObject {
$result = nullptr;
if (const void* impl = $1)
$result = (PyObject*) impl;
if (!$result) {
$result = Py_None;
Py_INCREF(Py_None);
}
}
%typemap(out) char** {
int len;
int i;

View File

@@ -110,6 +110,7 @@ class LLDB_API SBUnixSignals;
typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
SBThread &thread,
lldb::SBBreakpointLocation &location);
typedef void *ScriptedObject;
}
#endif // LLDB_API_SBDEFINES_H

View File

@@ -423,6 +423,8 @@ public:
///
lldb::SBError DeallocateMemory(lldb::addr_t ptr);
lldb::ScriptedObject GetScriptedImplementation();
protected:
friend class SBAddress;
friend class SBBreakpoint;

View File

@@ -2526,6 +2526,8 @@ void PruneThreadPlans();
lldb::StructuredDataPluginSP
GetStructuredDataPlugin(ConstString type_name) const;
virtual void *GetImplementation() { return nullptr; }
protected:
friend class Trace;

View File

@@ -1262,3 +1262,9 @@ lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) {
}
return sb_error;
}
ScriptedObject SBProcess::GetScriptedImplementation() {
LLDB_INSTRUMENT_VA(this);
ProcessSP process_sp(GetSP());
return (process_sp) ? process_sp->GetImplementation() : nullptr;
}

View File

@@ -512,3 +512,10 @@ void ScriptedProcess::UpdateQueueListIfNeeded() {
ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
return m_interpreter->GetScriptedProcessInterface();
}
void *ScriptedProcess::GetImplementation() {
if (m_script_object_sp &&
m_script_object_sp->GetType() == eStructuredDataTypeGeneric)
return m_script_object_sp->GetAsGeneric()->GetValue();
return nullptr;
}

View File

@@ -74,6 +74,8 @@ public:
void UpdateQueueListIfNeeded() override;
void *GetImplementation() override;
protected:
ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
const ScriptedMetadata &scripted_metadata, Status &error);

View File

@@ -10,6 +10,8 @@ from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
from lldbsuite.test import lldbtest
import dummy_scripted_process
class ScriptedProcesTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@@ -118,6 +120,14 @@ class ScriptedProcesTestCase(TestBase):
self.assertEqual(process.GetProcessID(), 42)
self.assertEqual(process.GetNumThreads(), 1)
py_impl = process.GetScriptedImplementation()
self.assertTrue(py_impl)
self.assertTrue(isinstance(py_impl, dummy_scripted_process.DummyScriptedProcess))
self.assertFalse(hasattr(py_impl, 'my_super_secret_member'))
py_impl.my_super_secret_member = 42
self.assertTrue(hasattr(py_impl, 'my_super_secret_member'))
self.assertEqual(py_impl.my_super_secret_method(), 42)
addr = 0x500000000
message = "Hello, world!"
buff = process.ReadCStringFromMemory(addr, len(message) + 1, error)

View File

@@ -43,6 +43,12 @@ class DummyScriptedProcess(ScriptedProcess):
def get_scripted_thread_plugin(self):
return DummyScriptedThread.__module__ + "." + DummyScriptedThread.__name__
def my_super_secret_method(self):
if hasattr(self, 'my_super_secret_member'):
return self.my_super_secret_member
else:
return None
class DummyScriptedThread(ScriptedThread):
def __init__(self, process, args):

View File

@@ -18,6 +18,18 @@ class ProcessAPITestCase(TestBase):
"main.cpp",
"// Set break point at this line and check variable 'my_char'.")
def test_scripted_implementation(self):
self.build()
exe = self.getBuildArtifact("a.out")
(target, process, _, _) = \
lldbutil.run_to_source_breakpoint(self, "Set break point",
lldb.SBFileSpec("main.cpp"))
self.assertTrue(process, PROCESS_IS_VALID)
self.assertEqual(process.GetScriptedImplementation(), None)
def test_read_memory(self):
"""Test Python SBProcess.ReadMemory() API."""
self.build()