aboutsummaryrefslogtreecommitdiff
path: root/lldb/examples/python
diff options
context:
space:
mode:
authorMed Ismail Bennani <ismail@bennani.ma>2023-10-23 15:42:59 -0700
committerMed Ismail Bennani <ismail@bennani.ma>2023-10-26 15:12:22 -0700
commitec456ba9ca0a097da63daafbb031cb2024f5513a (patch)
tree68ec4f819792e9d08d27f3761ddcef63920bbd85 /lldb/examples/python
parent7a1e8783586ecc90ee15f12c7b76799313bb32e8 (diff)
downloadllvm-ec456ba9ca0a097da63daafbb031cb2024f5513a.zip
llvm-ec456ba9ca0a097da63daafbb031cb2024f5513a.tar.gz
llvm-ec456ba9ca0a097da63daafbb031cb2024f5513a.tar.bz2
[lldb] Add OperatingSystem base class to the lldb python module
This patch introduces an `OperatingSystem` base implementation in the `lldb` python module to make it easier for lldb users to write their own implementation. The `OperatingSystem` base implementation is derived itself from the `ScriptedThread` base implementation since they share some common grounds. To achieve that, this patch makes changes to the `ScriptedThread` initializer since it gets called by the `OperatingSystem` initializer. I also took the opportunity to document the `OperatingSystem` base class and methods. Differential Revision: https://reviews.llvm.org/D159315 Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Diffstat (limited to 'lldb/examples/python')
-rw-r--r--lldb/examples/python/templates/operating_system.py103
-rw-r--r--lldb/examples/python/templates/scripted_process.py26
2 files changed, 118 insertions, 11 deletions
diff --git a/lldb/examples/python/templates/operating_system.py b/lldb/examples/python/templates/operating_system.py
new file mode 100644
index 0000000..a8053bc
--- /dev/null
+++ b/lldb/examples/python/templates/operating_system.py
@@ -0,0 +1,103 @@
+from abc import abstractmethod
+
+import lldb
+import struct
+
+from lldb.plugins.scripted_process import ScriptedThread
+
+
+class OperatingSystem(ScriptedThread):
+ """
+ Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class.
+
+ ```
+ thread_info = {
+ "tid": tid,
+ "name": "four",
+ "queue": "queue4",
+ "state": "stopped",
+ "stop_reason": "none",
+ "core" : 2
+ }
+ ```
+
+ - tid : thread ID (mandatory)
+ - name : thread name (optional key/value pair)
+ - queue : thread dispatch queue name (optional key/value pair)
+ - state : thread state (mandatory, set to 'stopped' for now)
+ - core : the index of the core (lldb) thread that this OS Thread should shadow
+ - stop_reason : thread stop reason. (mandatory, usually set to 'none')
+ Possible values include:
+ - 'breakpoint': thread is stopped at a breakpoint
+ - 'none': thread is stopped because the process is stopped
+ - 'trace': thread is stopped after single stepping
+ The usual value for this while threads are in memory is 'none'
+ - register_data_addr : the address of the register data in memory (optional key/value pair)
+ Specifying this key/value pair for a thread will avoid a call to get_register_data()
+ and can be used when your registers are in a thread context structure that is contiguous
+ in memory. Don't specify this if your register layout in memory doesn't match the layout
+ described by the dictionary returned from a call to the get_register_info() method.
+ """
+
+ def __init__(self, process):
+ """Initialization needs a valid lldb.SBProcess object. This plug-in
+ will get created after a live process is valid and has stopped for the
+ first time.
+
+ Args:
+ process (lldb.SBProcess): The process owning this thread.
+ """
+ self.registers = None
+ super().__init__(process, None)
+ self.registers = self.register_info
+ self.threads = []
+
+ def create_thread(self, tid, context):
+ """Lazily create an operating system thread using a thread information
+ dictionary and an optional operating system thread context address.
+ This method is called manually, using the SBAPI
+ `lldb.SBProcess.CreateOSPluginThread` affordance.
+
+ Args:
+ tid (int): Thread ID to get `thread_info` dictionary for.
+ context (int): Address of the operating system thread struct.
+
+ Returns:
+ Dict: The `thread_info` dictionary containing the various information
+ for lldb to create a Thread object and add it to the process thread list.
+ """
+ return None
+
+ @abstractmethod
+ def get_thread_info(self):
+ """Get the list of operating system threads. This method gets called
+ automatically every time the process stops and it needs to update its
+ thread list.
+
+ Returns:
+ List[thread_info]: A list of `os_thread` dictionaries
+ containing at least for each entry, the thread id, it's name,
+ queue, state, stop reason. It can also contain a
+ `register_data_addr`. The list can be empty.
+ """
+ pass
+
+ @abstractmethod
+ def get_register_data(self, tid):
+ """Get the operating system thread register context for given a thread
+ id. This method is called when unwinding the stack of one of the
+ operating system threads.
+
+ Args:
+ tid (int): Thread ID to get register context for.
+
+ Returns:
+ str: A byte representing all register's value.
+ """
+ pass
+
+ def get_register_context(self):
+ pass
+
+ def get_stop_reason(self):
+ pass
diff --git a/lldb/examples/python/templates/scripted_process.py b/lldb/examples/python/templates/scripted_process.py
index d74ef02..3ddcebd 100644
--- a/lldb/examples/python/templates/scripted_process.py
+++ b/lldb/examples/python/templates/scripted_process.py
@@ -244,16 +244,16 @@ class ScriptedThread(metaclass=ABCMeta):
"""
@abstractmethod
- def __init__(self, scripted_process, args):
+ def __init__(self, process, args):
"""Construct a scripted thread.
Args:
- process (ScriptedProcess): The scripted process owning this thread.
+ process (ScriptedProcess/lldb.SBProcess): The process owning this thread.
args (lldb.SBStructuredData): A Dictionary holding arbitrary
key/value pairs used by the scripted thread.
"""
self.target = None
- self.scripted_process = None
+ self.originating_process = None
self.process = None
self.args = None
self.idx = 0
@@ -268,9 +268,13 @@ class ScriptedThread(metaclass=ABCMeta):
self.frames = []
self.extended_info = []
- if isinstance(scripted_process, ScriptedProcess):
- self.target = scripted_process.target
- self.scripted_process = scripted_process
+ if (
+ isinstance(process, ScriptedProcess)
+ or isinstance(process, lldb.SBProcess)
+ and process.IsValid()
+ ):
+ self.target = process.target
+ self.originating_process = process
self.process = self.target.GetProcess()
self.get_register_info()
@@ -354,14 +358,14 @@ class ScriptedThread(metaclass=ABCMeta):
def get_register_info(self):
if self.register_info is None:
self.register_info = dict()
- if self.scripted_process.arch == "x86_64":
+ if self.originating_process.arch == "x86_64":
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = INTEL64_GPR
- elif "arm64" in self.scripted_process.arch:
+ elif "arm64" in self.originating_process.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = ARM64_GPR
else:
- raise ValueError("Unknown architecture", self.scripted_process.arch)
+ raise ValueError("Unknown architecture", self.originating_process.arch)
return self.register_info
@abstractmethod
@@ -505,12 +509,12 @@ class PassthroughScriptedThread(ScriptedThread):
# TODO: Passthrough stop reason from driving process
if self.driving_thread.GetStopReason() != lldb.eStopReasonNone:
- if "arm64" in self.scripted_process.arch:
+ if "arm64" in self.originating_process.arch:
stop_reason["type"] = lldb.eStopReasonException
stop_reason["data"][
"desc"
] = self.driving_thread.GetStopDescription(100)
- elif self.scripted_process.arch == "x86_64":
+ elif self.originating_process.arch == "x86_64":
stop_reason["type"] = lldb.eStopReasonSignal
stop_reason["data"]["signal"] = signal.SIGTRAP
else: