llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Med Ismail Bennani (medismailben) <details> <summary>Changes</summary> 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 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] `````````` </details> https://github.com/llvm/llvm-project/pull/158331 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits