[Lldb-commits] [lldb] bb4ccc6 - [lldb] Add ScriptedPlatform python implementation
Med Ismail Bennani via lldb-commits
lldb-commits at lists.llvm.org
Thu Jan 12 12:54:18 PST 2023
Author: Med Ismail Bennani
Date: 2023-01-12T12:49:05-08:00
New Revision: bb4ccc6688893d1bf38cfca76620d84f947b9de1
URL: https://github.com/llvm/llvm-project/commit/bb4ccc6688893d1bf38cfca76620d84f947b9de1
DIFF: https://github.com/llvm/llvm-project/commit/bb4ccc6688893d1bf38cfca76620d84f947b9de1.diff
LOG: [lldb] Add ScriptedPlatform python implementation
This patch introduces both the Scripted Platform python base
implementation and an example for it.
The base implementation is embedded in lldb python module under
`lldb.plugins.scripted_platform`.
This patch also refactor the various SWIG methods to create scripted
objects into a single method, that is now shared between the Scripted
Platform, Process and Thread. It also replaces the target argument by a
execution context object.
Differential Revision: https://reviews.llvm.org/D139250
Signed-off-by: Med Ismail Bennani <medismail.bennani at gmail.com>
Added:
lldb/examples/python/scripted_process/scripted_platform.py
lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py
Modified:
lldb/bindings/python/CMakeLists.txt
lldb/bindings/python/python-wrapper.swig
lldb/examples/python/scripted_process/crashlog_scripted_process.py
lldb/examples/python/scripted_process/scripted_process.py
lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
Removed:
################################################################################
diff --git a/lldb/bindings/python/CMakeLists.txt b/lldb/bindings/python/CMakeLists.txt
index afad367baa9fa..4f7941e6cff1d 100644
--- a/lldb/bindings/python/CMakeLists.txt
+++ b/lldb/bindings/python/CMakeLists.txt
@@ -109,6 +109,13 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar
FILES
"${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_process.py")
+ create_python_package(
+ ${swig_target}
+ ${lldb_python_target_dir}
+ "plugins"
+ FILES
+ "${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_platform.py")
+
if(APPLE)
create_python_package(
${swig_target}
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 91b26fff05a1c..9a08c3000b79a 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -229,9 +229,9 @@ PythonObject lldb_private::LLDBSwigPythonCreateCommandObject(
return pfunc(ToSWIGWrapper(std::move(debugger_sp)), dict);
}
-PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess(
+PythonObject lldb_private::LLDBSwigPythonCreateScriptedObject(
const char *python_class_name, const char *session_dictionary_name,
- const lldb::TargetSP &target_sp,
+ lldb::ExecutionContextRefSP exe_ctx_sp,
const lldb_private::StructuredDataImpl &args_impl,
std::string &error_string) {
if (python_class_name == NULL || python_class_name[0] == '\0' ||
@@ -251,8 +251,6 @@ PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess(
return PythonObject();
}
- PythonObject target_arg = ToSWIGWrapper(target_sp);
-
llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
if (!arg_info) {
llvm::handleAllErrors(
@@ -266,7 +264,7 @@ PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess(
PythonObject result = {};
if (arg_info.get().max_positional_args == 2) {
- result = pfunc(target_arg, ToSWIGWrapper(args_impl));
+ result = pfunc(ToSWIGWrapper(exe_ctx_sp), ToSWIGWrapper(args_impl));
} else {
error_string.assign("wrong number of arguments in __init__, should be 2 "
"(not including self)");
@@ -274,46 +272,6 @@ PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess(
return result;
}
-PythonObject lldb_private::LLDBSwigPythonCreateScriptedThread(
- const char *python_class_name, const char *session_dictionary_name,
- const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl,
- std::string &error_string) {
- if (python_class_name == NULL || python_class_name[0] == '\0' ||
- !session_dictionary_name)
- return PythonObject();
-
- PyErr_Cleaner py_err_cleaner(true);
-
- auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
- session_dictionary_name);
- auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
- python_class_name, dict);
-
- if (!pfunc.IsAllocated()) {
- error_string.append("could not find script class: ");
- error_string.append(python_class_name);
- return PythonObject();
- }
-
- llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
- if (!arg_info) {
- llvm::handleAllErrors(
- arg_info.takeError(),
- [&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
- [&](const llvm::ErrorInfoBase &E) {
- error_string.append(E.message());
- });
- return PythonObject();
- }
-
- if (arg_info.get().max_positional_args == 2)
- return pfunc(ToSWIGWrapper(process_sp), ToSWIGWrapper(args_impl));
-
- error_string.assign("wrong number of arguments in __init__, should be 2 "
- "(not including self)");
- return PythonObject();
-}
-
PythonObject lldb_private::LLDBSwigPythonCreateScriptedThreadPlan(
const char *python_class_name, const char *session_dictionary_name,
const lldb_private::StructuredDataImpl &args_impl,
diff --git a/lldb/examples/python/scripted_process/crashlog_scripted_process.py b/lldb/examples/python/scripted_process/crashlog_scripted_process.py
index 71cfff2ac5b03..eddf96786d9e4 100644
--- a/lldb/examples/python/scripted_process/crashlog_scripted_process.py
+++ b/lldb/examples/python/scripted_process/crashlog_scripted_process.py
@@ -62,8 +62,8 @@ def load_images(self, images):
self.addr_mask,
self.target)
- def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
- super().__init__(target, args)
+ def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredData):
+ super().__init__(exe_ctx, args)
if not self.target or not self.target.IsValid():
# Return error
diff --git a/lldb/examples/python/scripted_process/scripted_platform.py b/lldb/examples/python/scripted_process/scripted_platform.py
new file mode 100644
index 0000000000000..95b97911fc1a3
--- /dev/null
+++ b/lldb/examples/python/scripted_process/scripted_platform.py
@@ -0,0 +1,96 @@
+from abc import ABCMeta, abstractmethod
+
+import lldb
+
+class ScriptedPlatform(metaclass=ABCMeta):
+
+ """
+ The base class for a scripted platform.
+
+ Most of the base class methods are `@abstractmethod` that need to be
+ overwritten by the inheriting class.
+
+ DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE.
+ THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE.
+ """
+
+ processes = None
+
+ @abstractmethod
+ def __init__(self, exe_ctx, args):
+ """ Construct a scripted platform.
+
+ Args:
+ exe_ctx (lldb.SBExecutionContext): The execution context for the scripted platform
+ args (lldb.SBStructuredData): A Dictionary holding arbitrary
+ key/value pairs used by the scripted platform.
+ """
+ processes = []
+
+ @abstractmethod
+ def list_processes(self):
+ """ Get a list of processes that are running or that can be attached to on the platform.
+
+ processes = {
+ 420: {
+ name: a.out,
+ arch: aarch64,
+ pid: 420,
+ parent_pid: 42 (optional),
+ uid: 0 (optional),
+ gid: 0 (optional),
+ },
+ }
+
+ Returns:
+ Dict: The processes represented as a dictionary, with at least the
+ process ID, name, architecture. Optionally, the user can also
+ provide the parent process ID and the user and group IDs.
+ The dictionary can be empty.
+ """
+ pass
+
+ def get_process_info(self, pid):
+ """ Get the dictionary describing the process.
+
+ Returns:
+ Dict: The dictionary of process info that matched process ID.
+ None if the process doesn't exists
+ """
+ pass
+
+ @abstractmethod
+ def attach_to_process(self, attach_info):
+ """ Attach to a process.
+
+ Args:
+ attach_info (lldb.SBAttachInfo): The information related to attach to a process.
+
+ Returns:
+ lldb.SBError: A status object notifying if the attach succeeded.
+ """
+ pass
+
+ @abstractmethod
+ def launch_process(self, launch_info):
+ """ Launch a process.
+
+ Args:
+ launch_info (lldb.SBLaunchInfo): The information related to the process launch.
+
+ Returns:
+ lldb.SBError: A status object notifying if the launch succeeded.
+ """
+ pass
+
+ @abstractmethod
+ def kill_process(self, pid):
+ """ Kill a process.
+
+ Args:
+ pid (int): Process ID for the process to be killed.
+
+ Returns:
+ lldb.SBError: A status object notifying if the shutdown succeeded.
+ """
+ pass
diff --git a/lldb/examples/python/scripted_process/scripted_process.py b/lldb/examples/python/scripted_process/scripted_process.py
index cc886c6ff467e..a84e057edc5ec 100644
--- a/lldb/examples/python/scripted_process/scripted_process.py
+++ b/lldb/examples/python/scripted_process/scripted_process.py
@@ -20,17 +20,20 @@ class ScriptedProcess(metaclass=ABCMeta):
metadata = None
@abstractmethod
- def __init__(self, target, args):
+ def __init__(self, exe_ctx, args):
""" Construct a scripted process.
Args:
- target (lldb.SBTarget): The target launching the scripted process.
+ exe_ctx (lldb.SBExecutionContext): The execution context for the scripted process.
args (lldb.SBStructuredData): A Dictionary holding arbitrary
key/value pairs used by the scripted process.
"""
+ target = None
self.target = None
self.args = None
self.arch = None
+ if isinstance(exe_ctx, lldb.SBExecutionContext):
+ target = exe_ctx.target
if isinstance(target, lldb.SBTarget) and target.IsValid():
self.target = target
triple = self.target.triple
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 35c96215d4a58..3dc2864f8d424 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -96,14 +96,10 @@ void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
// Although these are scripting-language specific, their definition depends on
// the public API.
-python::PythonObject LLDBSwigPythonCreateScriptedProcess(
+python::PythonObject LLDBSwigPythonCreateScriptedObject(
const char *python_class_name, const char *session_dictionary_name,
- const lldb::TargetSP &target_sp, const StructuredDataImpl &args_impl,
- std::string &error_string);
-
-python::PythonObject LLDBSwigPythonCreateScriptedThread(
- const char *python_class_name, const char *session_dictionary_name,
- const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl,
+ lldb::ExecutionContextRefSP exe_ctx_sp,
+ const lldb_private::StructuredDataImpl &args_impl,
std::string &error_string);
llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction(
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
index 5fd085df26a8e..6f087e8390ced 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
@@ -37,16 +37,18 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
if (class_name.empty())
return {};
- TargetSP target_sp = exe_ctx.GetTargetSP();
StructuredDataImpl args_impl(args_sp);
std::string error_string;
Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
- PythonObject ret_val = LLDBSwigPythonCreateScriptedProcess(
- class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp,
- args_impl, error_string);
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp =
+ std::make_shared<ExecutionContextRef>(exe_ctx);
+
+ PythonObject ret_val = LLDBSwigPythonCreateScriptedObject(
+ class_name.str().c_str(), m_interpreter.GetDictionaryName(),
+ exe_ctx_ref_sp, args_impl, error_string);
m_object_instance_sp =
StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
index 21d2ed35250f2..1b31ed2e58817 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
@@ -35,7 +35,6 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject(
if (class_name.empty() && !script_obj)
return {};
- ProcessSP process_sp = exe_ctx.GetProcessSP();
StructuredDataImpl args_impl(args_sp);
std::string error_string;
@@ -44,11 +43,13 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject(
PythonObject ret_val;
- if (!script_obj)
- ret_val = LLDBSwigPythonCreateScriptedThread(
- class_name.str().c_str(), m_interpreter.GetDictionaryName(), process_sp,
- args_impl, error_string);
- else
+ if (!script_obj) {
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp =
+ std::make_shared<ExecutionContextRef>(exe_ctx);
+ ret_val = LLDBSwigPythonCreateScriptedObject(
+ class_name.str().c_str(), m_interpreter.GetDictionaryName(),
+ exe_ctx_ref_sp, args_impl, error_string);
+ } else
ret_val = PythonObject(PyRefType::Borrowed,
static_cast<PyObject *>(script_obj->GetValue()));
diff --git a/lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py b/lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py
new file mode 100644
index 0000000000000..3849f47b01adb
--- /dev/null
+++ b/lldb/test/API/functionalities/scripted_platform/my_scripted_platform.py
@@ -0,0 +1,38 @@
+import os
+
+import lldb
+from lldb.plugins.scripted_platform import ScriptedPlatform
+
+class MyScriptedPlatform(ScriptedPlatform):
+
+ def __init__(self, exe_ctx, args):
+ self.processes = {}
+
+ proc = {}
+ proc['name'] = 'a.out'
+ proc['arch'] = 'arm64-apple-macosx'
+ proc['pid'] = 420
+ proc['parent'] = 42
+ proc['uid'] = 501
+ proc['gid'] = 20
+ self.processes[420] = proc
+
+ def list_processes(self):
+ return self.processes
+
+ def get_process_info(self, pid):
+ return self.processes[pid]
+
+ def launch_process(self, launch_info):
+ return lldb.SBError()
+
+ def kill_process(self, pid):
+ return lldb.SBError()
+
+def __lldb_init_module(debugger, dict):
+ if not 'SKIP_SCRIPTED_PLATFORM_SELECT' in os.environ:
+ debugger.HandleCommand(
+ "platform select scripted-platform -C %s.%s" % (__name__, MyScriptedPlatform.__name__))
+ else:
+ print("Name of the class that will manage the scripted platform: '%s.%s'"
+ % (__name__, MyScriptedPlatform.__name__))
diff --git a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
index d4f7953907346..83df1ad8cbbb3 100644
--- a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
+++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py
@@ -7,8 +7,8 @@
from lldb.plugins.scripted_process import ScriptedThread
class DummyScriptedProcess(ScriptedProcess):
- def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
- super().__init__(target, args)
+ def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredData):
+ super().__init__(exe_ctx, args)
self.threads[0] = DummyScriptedThread(self, None)
def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
diff --git a/lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py b/lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
index 62db547a1baf6..5852df9625d98 100644
--- a/lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
+++ b/lldb/test/API/functionalities/scripted_process/invalid_scripted_process.py
@@ -7,8 +7,8 @@
from lldb.plugins.scripted_process import ScriptedThread
class InvalidScriptedProcess(ScriptedProcess):
- def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
- super().__init__(target, args)
+ def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredData):
+ super().__init__(exe_ctx, args)
self.threads[0] = InvalidScriptedThread(self, None)
def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
diff --git a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
index 67a1256c8eef9..44a2a37fcc3f1 100644
--- a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
+++ b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
@@ -13,8 +13,8 @@ def get_module_with_name(self, target, name):
return module
return None
- def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
- super().__init__(target, args)
+ def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredData):
+ super().__init__(exe_ctx, args)
self.corefile_target = None
self.corefile_process = None
@@ -25,7 +25,7 @@ def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
idx = self.backing_target_idx.GetIntegerValue(42)
if self.backing_target_idx.GetType() == lldb.eStructuredDataTypeString:
idx = int(self.backing_target_idx.GetStringValue(100))
- self.corefile_target = target.GetDebugger().GetTargetAtIndex(idx)
+ self.corefile_target = self.target.GetDebugger().GetTargetAtIndex(idx)
self.corefile_process = self.corefile_target.GetProcess()
for corefile_thread in self.corefile_process:
structured_data = lldb.SBStructuredData()
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 4d2f27e0b0d76..75391e2ce4777 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -200,16 +200,9 @@ lldb_private::LLDBSWIGPythonCreateOSPlugin(const char *python_class_name,
return python::PythonObject();
}
-python::PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess(
+python::PythonObject lldb_private::LLDBSwigPythonCreateScriptedObject(
const char *python_class_name, const char *session_dictionary_name,
- const lldb::TargetSP &target_sp, const StructuredDataImpl &args_impl,
- std::string &error_string) {
- return python::PythonObject();
-}
-
-python::PythonObject lldb_private::LLDBSwigPythonCreateScriptedThread(
- const char *python_class_name, const char *session_dictionary_name,
- const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl,
+ lldb::ExecutionContextRefSP exe_ctx_sp, const StructuredDataImpl &args_impl,
std::string &error_string) {
return python::PythonObject();
}
More information about the lldb-commits
mailing list