Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

medismailben
Copy link
Member

@medismailben medismailben commented Sep 12, 2025

This pages improve the LLDB website documentation readability and discoverability by breaking down the very long python-reference page into multiple subpages each explaining a specific topic.

The long term goal is to have tutorials for every scripting extension.

This also converts the pages to markdown, since it's easier to write.

@llvmbot
Copy link
Member

llvmbot commented Sep 12, 2025

@llvm/pr-subscribers-lldb

Author: Med Ismail Bennani (medismailben)

Changes

This pages improve the LLDB website documentation readability and discoverability by breaking down the very long python-reference page into multiple subpages each explaining a specific topic.

The long term goal is to have tutorials for every scripting extension.

This also converts the pages into markdown, since it's easier to write.


Patch is 167.69 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158331.diff

12 Files Affected:

  • (modified) lldb/docs/use/python-reference.rst (+18-1123)
  • (removed) lldb/docs/use/python.rst (-799)
  • (added) lldb/docs/use/tutorials/accessing-documentation.md (+59)
  • (added) lldb/docs/use/tutorials/breakpoint-triggered-scripts.md (+85)
  • (added) lldb/docs/use/tutorials/creating-custom-breakpoints.md (+128)
  • (added) lldb/docs/use/tutorials/custom-frame-recognizers.md (+52)
  • (added) lldb/docs/use/tutorials/custom-stepping-behavior.md (+42)
  • (added) lldb/docs/use/tutorials/python-embedded-interpreter.md (+66)
  • (added) lldb/docs/use/tutorials/python-standalone-scripts.md (+132)
  • (added) lldb/docs/use/tutorials/python-stop-hooks.md (+27)
  • (added) lldb/docs/use/tutorials/script-driven-debugging.md (+492)
  • (added) lldb/docs/use/tutorials/writing-custom-commands.md (+420)
diff --git a/lldb/docs/use/python-reference.rst b/lldb/docs/use/python-reference.rst
index 4292714c9c208..1d61cb29ef821 100644
--- a/lldb/docs/use/python-reference.rst
+++ b/lldb/docs/use/python-reference.rst
@@ -10,1126 +10,21 @@ command interpreter (we refer to this for brevity as the embedded interpreter).
 Of course, in this context it has full access to the LLDB API - with some
 additional conveniences we will call out in the FAQ.
 
-Documentation
---------------
-
-The LLDB API is contained in a python module named lldb. A useful resource when
-writing Python extensions is the lldb Python classes reference guide.
-
-The documentation is also accessible in an interactive debugger session with
-the following command:
-
-::
-
-   (lldb) script help(lldb)
-      Help on package lldb:
-
-      NAME
-         lldb - The lldb module contains the public APIs for Python binding.
-
-      FILE
-         /System/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python/lldb/__init__.py
-
-      DESCRIPTION
-   ...
-
-You can also get help using a module class name. The full API that is exposed
-for that class will be displayed in a man page style window. Below we want to
-get help on the lldb.SBFrame class:
-
-::
-
-   (lldb) script help(lldb.SBFrame)
-      Help on class SBFrame in module lldb:
-
-      class SBFrame(__builtin__.object)
-      |  Represents one of the stack frames associated with a thread.
-      |  SBThread contains SBFrame(s). For example (from test/lldbutil.py),
-      |
-      |  def print_stacktrace(thread, string_buffer = False):
-      |      '''Prints a simple stack trace of this thread.'''
-      |
-   ...
-
-Or you can get help using any python object, here we use the lldb.process
-object which is a global variable in the lldb module which represents the
-currently selected process:
-
-::
-
-   (lldb) script help(lldb.process)
-      Help on SBProcess in module lldb object:
-
-      class SBProcess(__builtin__.object)
-      |  Represents the process associated with the target program.
-      |
-      |  SBProcess supports thread iteration. For example (from test/lldbutil.py),
-      |
-      |  # ==================================================
-      |  # Utility functions related to Threads and Processes
-      |  # ==================================================
-      |
-   ...
-
-Embedded Python Interpreter
----------------------------
-
-The embedded python interpreter can be accessed in a variety of ways from
-within LLDB. The easiest way is to use the lldb command script with no
-arguments at the lldb command prompt:
-
-::
-
-   (lldb) script
-   Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
-   >>> 2+3
-   5
-   >>> hex(12345)
-   '0x3039'
-   >>>
-
-This drops you into the embedded python interpreter. When running under the
-script command, lldb sets some convenience variables that give you quick access
-to the currently selected entities that characterize the program and debugger
-state. In each case, if there is no currently selected entity of the
-appropriate type, the variable's IsValid method will return false. These
-variables are:
-
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-| Variable          | Type                | Equivalent                          | Description                                                                         |
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-| ``lldb.debugger`` | `lldb.SBDebugger`   | `SBTarget.GetDebugger`              | Contains the debugger object whose ``script`` command was invoked.                  |
-|                   |                     |                                     | The `lldb.SBDebugger` object owns the command interpreter                           |
-|                   |                     |                                     | and all the targets in your debug session.  There will always be a                  |
-|                   |                     |                                     | Debugger in the embedded interpreter.                                               |
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-| ``lldb.target``   | `lldb.SBTarget`     | `SBDebugger.GetSelectedTarget`      | Contains the currently selected target - for instance the one made with the         |
-|                   |                     |                                     | ``file`` or selected by the ``target select <target-index>`` command.               |
-|                   |                     | `SBProcess.GetTarget`               | The `lldb.SBTarget` manages one running process, and all the executable             |
-|                   |                     |                                     | and debug files for the process.                                                    |
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-| ``lldb.process``  | `lldb.SBProcess`    | `SBTarget.GetProcess`               | Contains the process of the currently selected target.                              |
-|                   |                     |                                     | The `lldb.SBProcess` object manages the threads and allows access to                |
-|                   |                     | `SBThread.GetProcess`               | memory for the process.                                                             |
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-| ``lldb.thread``   | `lldb.SBThread`     | `SBProcess.GetSelectedThread`       | Contains the currently selected thread.                                             |
-|                   |                     |                                     | The `lldb.SBThread` object manages the stack frames in that thread.                 |
-|                   |                     | `SBFrame.GetThread`                 | A thread is always selected in the command interpreter when a target stops.         |
-|                   |                     |                                     | The ``thread select <thread-index>`` command can be used to change the              |
-|                   |                     |                                     | currently selected thread.  So as long as you have a stopped process, there will be |
-|                   |                     |                                     | some selected thread.                                                               |
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-| ``lldb.frame``    | `lldb.SBFrame`      | `SBThread.GetSelectedFrame`         | Contains the currently selected stack frame.                                        |
-|                   |                     |                                     | The `lldb.SBFrame` object manage the stack locals and the register set for          |
-|                   |                     |                                     | that stack.                                                                         |
-|                   |                     |                                     | A stack frame is always selected in the command interpreter when a target stops.    |
-|                   |                     |                                     | The ``frame select <frame-index>`` command can be used to change the                |
-|                   |                     |                                     | currently selected frame.  So as long as you have a stopped process, there will     |
-|                   |                     |                                     | be some selected frame.                                                             |
-+-------------------+---------------------+-------------------------------------+-------------------------------------------------------------------------------------+
-
-While extremely convenient, these variables have a couple caveats that you
-should be aware of. First of all, they hold the values of the selected objects
-on entry to the embedded interpreter. They do not update as you use the LLDB
-API's to change, for example, the currently selected stack frame or thread.
-
-Moreover, they are only defined and meaningful while in the interactive Python
-interpreter. There is no guarantee on their value in any other situation, hence
-you should not use them when defining Python formatters, breakpoint scripts and
-commands (or any other Python extension point that LLDB provides). For the
-latter you'll be passed an `SBDebugger`, `SBTarget`, `SBProcess`, `SBThread` or
-`SBFrame` instance and you can use the functions from the "Equivalent" column
-to navigate between them.
-
-As a rationale for such behavior, consider that lldb can run in a multithreaded
-environment, and another thread might call the "script" command, changing the
-value out from under you.
-
-To get started with these objects and LLDB scripting, please note that almost
-all of the lldb Python objects are able to briefly describe themselves when you
-pass them to the Python print function:
-
-::
-
-   (lldb) script
-   Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
-   >>> print(lldb.debugger)
-   Debugger (instance: "debugger_1", id: 1)
-   >>> print(lldb.target)
-   a.out
-   >>> print(lldb.process)
-   SBProcess: pid = 58842, state = stopped, threads = 1, executable = a.out
-   >>> print(lldb.thread)
-   thread #1: tid = 0x2265ce3, 0x0000000100000334 a.out`main at t.c:2:3, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
-   >>> print(lldb.frame)
-   frame #0: 0x0000000100000334 a.out`main at t.c:2:3
-
-
-Running a python script when a breakpoint gets hit
---------------------------------------------------
-
-One very powerful use of the lldb Python API is to have a python script run
-when a breakpoint gets hit. Adding python scripts to breakpoints provides a way
-to create complex breakpoint conditions and also allows for smart logging and
-data gathering.
-
-When your process hits a breakpoint to which you have attached some python
-code, the code is executed as the body of a function which takes three
-arguments:
-
-::
-
-  def breakpoint_function_wrapper(frame, bp_loc, internal_dict):
-     # Your code goes here
-
-or:
-
-::
-
-  def breakpoint_function_wrapper(frame, bp_loc, extra_args, internal_dict):
-     # Your code goes here
-
-
-+-------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
-| Argument          | Type                          | Description                                                                                                                               |
-+-------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
-| ``frame``         | `lldb.SBFrame`                | The current stack frame where the breakpoint got hit.                                                                                     |
-|                   |                               | The object will always be valid.                                                                                                          |
-|                   |                               | This ``frame`` argument might *not* match the currently selected stack frame found in the `lldb` module global variable ``lldb.frame``.   |
-+-------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
-| ``bp_loc``        | `lldb.SBBreakpointLocation`   | The breakpoint location that just got hit. Breakpoints are represented by `lldb.SBBreakpoint`                                             |
-|                   |                               | objects. These breakpoint objects can have one or more locations. These locations                                                         |
-|                   |                               | are represented by `lldb.SBBreakpointLocation` objects.                                                                                   |
-+-------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
-| ``extra_args``    | `lldb.SBStructuredData`       | ``Optional`` If your breakpoint callback function takes this extra parameter, then when the callback gets added to a breakpoint, its      |
-|                   |                               | contents can parametrize this use of the callback.  For instance, instead of writing a callback that stops when the caller is "Foo",      |
-|                   |                               | you could take the function name from a field in the ``extra_args``, making the callback more general.  The ``-k`` and ``-v`` options     |
-|                   |                               | to ``breakpoint command add`` will be passed as a Dictionary in the ``extra_args`` parameter, or you can provide it with the SB API's.    |
-+-------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
-| ``internal_dict`` | ``dict``                      | The python session dictionary as a standard python dictionary object.                                                                     |
-+-------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
-
-Optionally, a Python breakpoint command can return a value. Returning False
-tells LLDB that you do not want to stop at the breakpoint. Any other return
-value (including None or leaving out the return statement altogether) is akin
-to telling LLDB to actually stop at the breakpoint. This can be useful in
-situations where a breakpoint only needs to stop the process when certain
-conditions are met, and you do not want to inspect the program state manually
-at every stop and then continue.
-
-An example will show how simple it is to write some python code and attach it
-to a breakpoint. The following example will allow you to track the order in
-which the functions in a given shared library are first executed during one run
-of your program. This is a simple method to gather an order file which can be
-used to optimize function placement within a binary for execution locality.
-
-We do this by setting a regular expression breakpoint that will match every
-function in the shared library. The regular expression '.' will match any
-string that has at least one character in it, so we will use that. This will
-result in one lldb.SBBreakpoint object that contains an
-lldb.SBBreakpointLocation object for each function. As the breakpoint gets hit,
-we use a counter to track the order in which the function at this particular
-breakpoint location got hit. Since our code is passed the location that was
-hit, we can get the name of the function from the location, disable the
-location so we won't count this function again; then log some info and continue
-the process.
-
-Note we also have to initialize our counter, which we do with the simple
-one-line version of the script command.
-
-Here is the code:
-
-::
-
-   (lldb) breakpoint set --func-regex=. --shlib=libfoo.dylib
-   Breakpoint created: 1: regex = '.', module = libfoo.dylib, locations = 223
-   (lldb) script counter = 0
-   (lldb) breakpoint command add --script-type python 1
-   Enter your Python command(s). Type 'DONE' to end.
-   > # Increment our counter.  Since we are in a function, this must be a global python variable
-   > global counter
-   > counter += 1
-   > # Get the name of the function
-   > name = frame.GetFunctionName()
-   > # Print the order and the function name
-   > print('[%i] %s' % (counter, name))
-   > # Disable the current breakpoint location so it doesn't get hit again
-   > bp_loc.SetEnabled(False)
-   > # No need to stop here
-   > return False
-   > DONE
-
-The breakpoint command add command above attaches a python script to breakpoint 1. To remove the breakpoint command:
-
-::
-
-   (lldb) breakpoint command delete 1
-
-
-Using the python api's to create custom breakpoints
----------------------------------------------------
-
-
-Another use of the Python API's in lldb is to create a custom breakpoint
-resolver. This facility was added in r342259.
-
-It allows you to provide the algorithm which will be used in the breakpoint's
-search of the space of the code in a given Target to determine where to set the
-breakpoint locations - the actual places where the breakpoint will trigger. To
-understand how this works you need to know a little about how lldb handles
-breakpoints.
-
-In lldb, a breakpoint is composed of three parts: the Searcher, the Resolver,
-and the Stop Options. The Searcher and Resolver cooperate to determine how
-breakpoint locations are set and differ between each breakpoint type. Stop
-options determine what happens when a location triggers and includes the
-commands, conditions, ignore counts, etc. Stop options are common between all
-breakpoint types, so for our purposes only the Searcher and Resolver are
-relevant.
-
-The Searcher's job is to traverse in a structured way the code in the current
-target. It proceeds from the Target, to search all the Modules in the Target,
-in each Module it can recurse into the Compile Units in that module, and within
-each Compile Unit it can recurse over the Functions it contains.
-
-The Searcher can be provided with a SearchFilter that it will use to restrict
-this search. For instance, if the SearchFilter specifies a list of Modules, the
-Searcher will not recurse into Modules that aren't on the list. When you pass
-the -s modulename flag to break set you are creating a Module-based search
-filter. When you pass -f filename.c to break set -n you are creating a file
-based search filter. If neither of these is specified, the breakpoint will have
-a no-op search filter, so all parts of the program are searched and all
-locations accepted.
-
-The Resolver has two functions. The most important one is the callback it
-provides. This will get called at the appropriate time in the course of the
-search. The callback is where the job of adding locations to the breakpoint
-gets done.
-
-The other function is specifying to the Searcher at what depth in the above
-described recursion it wants to be called. Setting a search depth also provides
-a stop for the recursion. For instance, if you request a Module depth search,
-then the callback will be called for each Module as it gets added to the
-Target, but the searcher will not recurse into the Compile Units in the module.
-
-One other slight subtlety is that the depth at which you get called back is not
-necessarily the depth at which the SearchFilter is specified. For instance,
-if you are doing symbol searches, it is convenient to use the Module depth for
-the search, since symbols are stored in the module. But the SearchFilter might
-specify some subset of CompileUnits, so not all the symbols you might find in
-each module will pass the search. You don't need to handle this situation
-yourself, since SBBreakpoint::AddLocation will only add locations that pass the
-Search Filter. This API returns an SBError to inform you whether your location
-was added.
-
-When the...
[truncated]

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. There's tons of opportunity for improvement but that shouldn't block this PR.

@jimingham
Copy link
Collaborator

The one downside to this is that any links that we've handed out to the documentation in the past will get broken. Is there any way that we can keep the links that used to be in python-reference.rst, but have them redirected to the new files?

Other than that it looks like a good change to me, and will improve readability.

@medismailben
Copy link
Member Author

medismailben commented Sep 12, 2025

The one downside to this is that any links that we've handed out to the documentation in the past will get broken. Is there any way that we can keep the links that used to be in python-reference.rst, but have them redirected to the new files?

Other than that it looks like a good change to me, and will improve readability.

That'd be nice indeed. We could achieve that by using sphinx-reredirects to redirect the previous urls. @gkistanova can I just add this to llvm/docs/requirements.txt or is there a process for adding new dependencies to the documentation generator bots ?

@medismailben medismailben force-pushed the docs-reference branch 2 times, most recently from 48b8af1 to 7a4bee6 Compare September 12, 2025 22:47
@medismailben
Copy link
Member Author

The one downside to this is that any links that we've handed out to the documentation in the past will get broken. Is there any way that we can keep the links that used to be in python-reference.rst, but have them redirected to the new files?
Other than that it looks like a good change to me, and will improve readability.

That'd be nice indeed. We could achieve that by using sphinx-reredirects to redirect the previous urls. @gkistanova can I just add this to llvm/docs/requirements.txt or is there a process for adding new dependencies to the documentation generator bots ?

Luckily, libc already uses sphinx-reredirects so I can just make use of it in this PR to avoid breaking existing links.

@JDevlieghere
Copy link
Member

Any reason we can't use the existing .htaccess for that?

@medismailben
Copy link
Member Author

Any reason we can't use the existing .htaccess for that?

Sure, we can also do that

Copy link
Contributor

@kastiglione kastiglione left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more comment about one of the updated examples

This pages improve the LLDB website documentation readability and
discoverability by breaking down the very long python-reference page
into multiple subpages each explaining a specific topic.

The long term goal is to have tutorials for every scripting extension.

This also converts the pages to markdown, since it's easier to write.

Signed-off-by: Med Ismail Bennani <[email protected]>
@medismailben medismailben merged commit 2610007 into llvm:main Sep 13, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants