mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
[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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -423,6 +423,8 @@ public:
|
||||
///
|
||||
lldb::SBError DeallocateMemory(lldb::addr_t ptr);
|
||||
|
||||
lldb::ScriptedObject GetScriptedImplementation();
|
||||
|
||||
protected:
|
||||
friend class SBAddress;
|
||||
friend class SBBreakpoint;
|
||||
|
||||
@@ -2526,6 +2526,8 @@ void PruneThreadPlans();
|
||||
lldb::StructuredDataPluginSP
|
||||
GetStructuredDataPlugin(ConstString type_name) const;
|
||||
|
||||
virtual void *GetImplementation() { return nullptr; }
|
||||
|
||||
protected:
|
||||
friend class Trace;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user