diff --git a/lldb/bindings/interface/SBProcess.i b/lldb/bindings/interface/SBProcess.i --- a/lldb/bindings/interface/SBProcess.i +++ b/lldb/bindings/interface/SBProcess.i @@ -344,6 +344,12 @@ 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 diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig --- a/lldb/bindings/python/python-typemaps.swig +++ b/lldb/bindings/python/python-typemaps.swig @@ -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; diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -110,6 +110,7 @@ typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process, SBThread &thread, lldb::SBBreakpointLocation &location); +typedef void *ScriptedObject; } #endif // LLDB_API_SBDEFINES_H diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -423,6 +423,8 @@ /// lldb::SBError DeallocateMemory(lldb::addr_t ptr); + lldb::ScriptedObject GetScriptedImplementation(); + protected: friend class SBAddress; friend class SBBreakpoint; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -2526,6 +2526,8 @@ lldb::StructuredDataPluginSP GetStructuredDataPlugin(ConstString type_name) const; + virtual void *GetImplementation() { return nullptr; } + protected: friend class Trace; diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -1262,3 +1262,9 @@ } return sb_error; } + +ScriptedObject SBProcess::GetScriptedImplementation() { + LLDB_INSTRUMENT_VA(this); + ProcessSP process_sp(GetSP()); + return (process_sp) ? process_sp->GetImplementation() : nullptr; +} diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -74,6 +74,8 @@ void UpdateQueueListIfNeeded() override; + void *GetImplementation() override; + protected: ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const ScriptedMetadata &scripted_metadata, Status &error); diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -512,3 +512,10 @@ 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; +} diff --git a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py --- a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py @@ -10,6 +10,8 @@ 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 @@ 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) diff --git a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py --- a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py @@ -43,6 +43,12 @@ 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): diff --git a/lldb/test/API/python_api/process/TestProcessAPI.py b/lldb/test/API/python_api/process/TestProcessAPI.py --- a/lldb/test/API/python_api/process/TestProcessAPI.py +++ b/lldb/test/API/python_api/process/TestProcessAPI.py @@ -18,6 +18,18 @@ "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()