https://github.com/medismailben updated 
https://github.com/llvm/llvm-project/pull/209311

>From ab637d5201246e88bd3f90d98842a3e65a3f9c86 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <[email protected]>
Date: Mon, 13 Jul 2026 16:01:01 -0700
Subject: [PATCH] [lldb/script] Add scripted extension base-class templates for
 hooks and breakpoint resolvers

This patch adds the Python base-class templates for `ScriptedHook` (a
unified base class that backs both `target hook add -P` and `target
stop-hook add -P`) and `ScriptedBreakpointResolver`, and wires them
into the Python bindings and docs CMake so every scriptable extension
kind has a template that the docs and future tooling can introspect.

The `ScriptedHook` template unifies what used to require separate
subclasses for target hooks and stop hooks: subclasses implement
`handle_stop` (required, so any hook is a valid stop-hook) and
optionally `handle_module_loaded` / `handle_module_unloaded`, which
only fire for hooks registered via `target hook add -P`.

Signed-off-by: Med Ismail Bennani <[email protected]>
---
 lldb/bindings/python/CMakeLists.txt           |   2 +
 lldb/docs/CMakeLists.txt                      |   2 +
 .../python/templates/scripted_breakpoint.py   | 105 ++++++++++++++++++
 .../python/templates/scripted_hook.py         |  62 +++++++++++
 4 files changed, 171 insertions(+)
 create mode 100644 lldb/examples/python/templates/scripted_breakpoint.py
 create mode 100644 lldb/examples/python/templates/scripted_hook.py

diff --git a/lldb/bindings/python/CMakeLists.txt 
b/lldb/bindings/python/CMakeLists.txt
index 4cf216728ede8..9a8a8d420e18a 100644
--- a/lldb/bindings/python/CMakeLists.txt
+++ b/lldb/bindings/python/CMakeLists.txt
@@ -117,6 +117,8 @@ function(finish_swig_python swig_target 
lldb_python_bindings_dir lldb_python_tar
     "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_platform.py"
     "${LLDB_SOURCE_DIR}/examples/python/templates/operating_system.py"
     "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_thread_plan.py"
+    "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_breakpoint.py"
+    "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_hook.py"
     )
 
   if(APPLE)
diff --git a/lldb/docs/CMakeLists.txt b/lldb/docs/CMakeLists.txt
index ccdcb4df1c60e..58c740f16bf78 100644
--- a/lldb/docs/CMakeLists.txt
+++ b/lldb/docs/CMakeLists.txt
@@ -30,6 +30,8 @@ if (LLDB_ENABLE_PYTHON AND SPHINX_FOUND)
       COMMAND "${CMAKE_COMMAND}" -E copy 
"${LLDB_SOURCE_DIR}/examples/python/templates/scripted_platform.py" 
"${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/"
       COMMAND "${CMAKE_COMMAND}" -E copy 
"${LLDB_SOURCE_DIR}/examples/python/templates/operating_system.py" 
"${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/"
       COMMAND "${CMAKE_COMMAND}" -E copy 
"${LLDB_SOURCE_DIR}/examples/python/templates/scripted_thread_plan.py" 
"${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/"
+      COMMAND "${CMAKE_COMMAND}" -E copy 
"${LLDB_SOURCE_DIR}/examples/python/templates/scripted_breakpoint.py" 
"${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/"
+      COMMAND "${CMAKE_COMMAND}" -E copy 
"${LLDB_SOURCE_DIR}/examples/python/templates/scripted_hook.py" 
"${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/"
       COMMENT "Copying lldb.py to pretend its a Python package.")
 
     add_dependencies(lldb-python-doc-package swig_wrapper_python)
diff --git a/lldb/examples/python/templates/scripted_breakpoint.py 
b/lldb/examples/python/templates/scripted_breakpoint.py
new file mode 100644
index 0000000000000..b46ffade34743
--- /dev/null
+++ b/lldb/examples/python/templates/scripted_breakpoint.py
@@ -0,0 +1,105 @@
+from abc import ABCMeta, abstractmethod
+
+import lldb
+
+
+class ScriptedBreakpointResolver(metaclass=ABCMeta):
+    """
+    The base class for a scripted breakpoint resolver.
+    """
+
+    @abstractmethod
+    def __init__(self, bkpt, args):
+        """Construct a scripted breakpoint resolver.
+
+        Args:
+            bkpt (lldb.SBBreakpoint): The breakpoint owning this resolver.
+            args (lldb.SBStructuredData): A Dictionary holding arbitrary
+                key/value pairs used by the scripted breakpoint.
+        """
+        self.bkpt = bkpt
+        self.args = args
+
+    def overrides_resolver(self, resolver_data):
+        """Decide, from the incoming resolver options, whether this
+        breakpoint should have its resolver replaced by this class. When
+        `True`, this class's `__callback__` picks locations for this
+        breakpoint instead of the original resolver's. Search depth is
+        unaffected either way and still comes from `__get_depth__`.
+
+        Args:
+            resolver_data (lldb.SBStructuredData): The resolver options
+                passed in when the breakpoint was created.
+
+        Returns:
+            bool: `True` if this class's `__callback__` should be used in
+            place of the original resolver's, `False` to leave the
+            original resolver in charge.
+        """
+        return False
+
+    def set_breakpoint(self, bkpt):
+        """Called once the underlying breakpoint has been fully created and
+        associated to this resolver.
+
+        Args:
+            bkpt (lldb.SBBreakpoint): The breakpoint owning this resolver.
+        """
+        pass
+
+    @abstractmethod
+    def __callback__(self, sym_ctx):
+        """Called once per symbol context matched by the search depth
+        returned by `__get_depth__`. Set breakpoint locations here by calling
+        `AddLocation` on the resolver's breakpoint.
+
+        Args:
+            sym_ctx (lldb.SBSymbolContext): The symbol context to inspect.
+        """
+        pass
+
+    def __get_depth__(self):
+        """The search depth at which `__callback__` will be called.
+
+        Returns:
+            lldb.SBSearchDepth: One of the `lldb.eSearchDepth*` values.
+            Defaults to `lldb.eSearchDepthModule`.
+        """
+        return lldb.eSearchDepthModule
+
+    def get_short_help(self):
+        """A one-line description of this resolver, shown by `breakpoint list`.
+
+        Returns:
+            str: The short help string.
+        """
+        pass
+
+    def was_hit(self, frame, bp_loc):
+        """Called when a location owned by this resolver is hit, to allow
+        overriding which location is reported as hit.
+
+        Args:
+            frame (lldb.SBFrame): The frame where the breakpoint was hit.
+            bp_loc (lldb.SBBreakpointLocation): The breakpoint location that
+                was hit.
+
+        Returns:
+            lldb.SBBreakpointLocation: The location to report as hit.
+            Defaults to `bp_loc`.
+        """
+        return bp_loc
+
+    def get_location_description(self, bp_loc, level):
+        """Customize the description used when printing a breakpoint location
+        owned by this resolver.
+
+        Args:
+            bp_loc (lldb.SBBreakpointLocation): The breakpoint location to
+                describe.
+            level (lldb.DescriptionLevel): The level of detail requested.
+
+        Returns:
+            str: The description for the location.
+        """
+        pass
diff --git a/lldb/examples/python/templates/scripted_hook.py 
b/lldb/examples/python/templates/scripted_hook.py
new file mode 100644
index 0000000000000..22455fe9981ef
--- /dev/null
+++ b/lldb/examples/python/templates/scripted_hook.py
@@ -0,0 +1,62 @@
+from abc import ABCMeta, abstractmethod
+
+import lldb
+
+
+class ScriptedHook(metaclass=ABCMeta):
+    """
+    The base class for a scripted target hook.
+
+    A single `ScriptedHook` subclass backs both `target hook add -P` and
+    `target stop-hook add -P`. `handle_stop` is required so a hook can
+    always be attached as a stop-hook; `handle_module_loaded` and
+    `handle_module_unloaded` are optional and only called for hooks
+    registered via `target hook add -P`.
+    """
+
+    @abstractmethod
+    def __init__(self, target, args):
+        """Construct a scripted hook.
+
+        Args:
+            target (lldb.SBTarget): The target owning this hook.
+            args (lldb.SBStructuredData): A Dictionary holding arbitrary
+                key/value pairs used by the scripted hook.
+        """
+        self.target = target
+        self.args = args
+
+    def handle_module_loaded(self, stream):
+        """Called whenever a module is loaded into the target.
+
+        Args:
+            stream (lldb.SBStream): The stream to which the hook can write
+                output that will be reported to the user.
+        """
+        pass
+
+    def handle_module_unloaded(self, stream):
+        """Called whenever a module is unloaded from the target.
+
+        Args:
+            stream (lldb.SBStream): The stream to which the hook can write
+                output that will be reported to the user.
+        """
+        pass
+
+    @abstractmethod
+    def handle_stop(self, exe_ctx, stream):
+        """Called whenever the process stops, before control is returned to
+        the user.
+
+        Args:
+            exe_ctx (lldb.SBExecutionContext): The execution context at the
+                point of the stop.
+            stream (lldb.SBStream): The stream to which the hook can write
+                output that will be reported to the user.
+
+        Returns:
+            bool: `True` if the process should stop and control should be
+            returned to the user, `False` if the process should keep running.
+        """
+        pass

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to