[Lldb-commits] [lldb] r360386 - [Docs] Port python reference page

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Thu May 9 15:14:15 PDT 2019


Author: jdevlieghere
Date: Thu May  9 15:14:14 2019
New Revision: 360386

URL: http://llvm.org/viewvc/llvm-project?rev=360386&view=rev
Log:
[Docs] Port python reference page

I somehow forgot to port over this page from the old website. Thank you
Jim for the heads up!

Added:
    lldb/trunk/docs/use/python-reference.rst
Modified:
    lldb/trunk/docs/index.rst

Modified: lldb/trunk/docs/index.rst
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/docs/index.rst?rev=360386&r1=360385&r2=360386&view=diff
==============================================================================
--- lldb/trunk/docs/index.rst (original)
+++ lldb/trunk/docs/index.rst Thu May  9 15:14:14 2019
@@ -40,6 +40,7 @@ Use & Extension
    use/symbolication
    use/symbols
    use/python
+   use/python-reference
    use/remote
    use/troubleshooting
    use/architecture

Added: lldb/trunk/docs/use/python-reference.rst
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/docs/use/python-reference.rst?rev=360386&view=auto
==============================================================================
--- lldb/trunk/docs/use/python-reference.rst (added)
+++ lldb/trunk/docs/use/python-reference.rst Thu May  9 15:14:14 2019
@@ -0,0 +1,822 @@
+Python Reference
+================
+
+The entire LLDB API is available as Python functions through a script bridging
+interface. This means the LLDB API's can be used directly from python either
+interactively or to build python apps that provide debugger features.
+
+Additionally, Python can be used as a programmatic interface within the lldb
+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.
+
+.. contents::
+   :local:
+
+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                | Description                                                                                     |
++-------------------+---------------------+-------------------------------------------------------------------------------------------------+
+| **lldb.debugger** | **lldb.SBDebugger** | 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**   | Contains the currently selected target - for instance the one made with the                     |
+|                   |                     |             **file** or selected by the **target select <target-index>** command.               |
+|                   |                     |             The **lldb.SBTarget** manages one running process, and all the executable           |
+|                   |                     |             and debug files for the process.                                                    |
++-------------------+---------------------+-------------------------------------------------------------------------------------------------+
+| **lldb.process**  | **lldb.SBProcess**  | Contains the process of the currently selected target.                                          |
+|                   |                     |             The **lldb.SBProcess** object manages the threads and allows access to              |
+|                   |                     |             memory for the process.                                                             |
++-------------------+---------------------+-------------------------------------------------------------------------------------------------+
+| **lldb.thread**   | **lldb.SBThread**   | Contains the currently selected thread.                                                         |
+|                   |                     |             The **lldb.SBThread** object manages the stack frames in that thread.               |
+|                   |                     |             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**    | 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). 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 = 59289, state = stopped, threads = 1, executable = a.out
+   >>> print lldb.thread
+   SBThread: tid = 0x1f03
+   >>> print lldb.frame
+   frame #0: 0x0000000100000bb6 a.out main + 54 at main.c:16
+
+
+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, 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.                                                                                 |
++------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+
+| **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 sublety is that the depth at which you get called back is not
+necessarily the depth at which the 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 breakpoint is originally created, its Searcher will process all the
+currently loaded modules. The Searcher will also visit any new modules as they
+are added to the target. This happens, for instance, when a new shared library
+gets added to the target in the course of running, or on rerunning if any of
+the currently loaded modules have been changed. Note, in the latter case, all
+the locations set in the old module will get deleted and you will be asked to
+recreate them in the new version of the module when your callback gets called
+with that module. For this reason, you shouldn't try to manage the locations
+you add to the breakpoint yourself. Note that the Breakpoint takes care of
+deduplicating equal addresses in AddLocation, so you shouldn't need to worry
+about that anyway.
+
+At present, when adding a scripted Breakpoint type, you can only provide a
+custom Resolver, not a custom SearchFilter.
+
+The custom Resolver is provided as a Python class with the following methods:
+
++--------------------+---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+| Name               | Arguments                             | Description                                                                                                                     |
++--------------------+---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+| **__init__**       | **bkpt: lldb.SBBreakpoint**           | This is the constructor for the new Resolver.                                                                                   |
+|                    | **extra_args: lldb.SBStructuredData** |                                                                                                                                 |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       | **bkpt** is the breakpoint owning this Resolver.                                                                                |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       | **extra_args** is an SBStructuredData object that the user can pass in when creating instances of this                          |
+|                    |                                       |                breakpoint.  It is not required, but is quite handy.  For instance if you were implementing a breakpoint on some |
+|                    |                                       |                symbol name, you could write a generic symbol name based Resolver, and then allow the user to pass               |
+|                    |                                       |                in the particular symbol in the extra_args                                                                       |
++--------------------+---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+| **__callback__**   | **sym_ctx: lldb.SBSymbolContext**     | This is the Resolver callback.                                                                                                  |
+|                    |                                       |             The **sym_ctx** argument will be filled with the current stage                                                      |
+|                    |                                       |             of the search.                                                                                                      |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       |                For instance, if you asked for a search depth of lldb.eSearchDepthCompUnit, then the                             |
+|                    |                                       |                target, module and compile_unit fields of the sym_ctx will be filled.  The callback should look just in the      |
+|                    |                                       |                context passed in **sym_ctx** for new locations.  If the callback finds an address of interest, it               |
+|                    |                                       |                can add it to the breakpoint with the **SBBreakpoint::AddLocation** method, using the breakpoint passed          |
+|                    |                                       |                in to the **__init__** method.                                                                                   |
++--------------------+---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+| **__get_depth__**  | **None**                              | Specify the depth at which you wish your callback to get called.  The currently supported options are:                          |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       | lldb.eSearchDepthModule                                                                                                         |
+|                    |                                       | lldb.eSearchDepthCompUnit                                                                                                       |
+|                    |                                       | lldb.eSearchDepthFunction                                                                                                       |
+|                    |                                       |                                                                                                                                 |
+|                    |                                       |             For instance, if you are looking                                                                                    |
+|                    |                                       |             up symbols, which are stored at the Module level, you will want to get called back module by module.                |
+|                    |                                       |             So you would want to return **lldb.eSearchDepthModule**.  This method is optional.  If not provided the search      |
+|                    |                                       |             will be done at Module depth.                                                                                       |
++--------------------+---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+| **get_short_help** | **None**                              | This is an optional method.  If provided, the returned string will be printed at the beginning of                               |
+|                    |                                       |             the description for this breakpoint.                                                                                |
++--------------------+---------------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+
+To define a new breakpoint command defined by this class from the lldb command
+line, use the command:
+
+::
+
+  (lldb) breakpoint set -P MyModule.MyResolverClass
+
+You can also populate the extra_args SBStructuredData with a dictionary of
+key/value pairs with:
+
+::
+
+  (lldb) breakpoint set -P MyModule.MyResolverClass -k key_1 -v value_1 -k key_2 -v value_2
+
+Although you can't write a scripted SearchFilter, both the command line and the
+SB API's for adding a scripted resolver allow you to specify a SearchFilter
+restricted to certain modules or certain compile units. When using the command
+line to create the resolver, you can specify a Module specific SearchFilter by
+passing the -s ModuleName option - which can be specified multiple times. You
+can also specify a SearchFilter restricted to certain compile units by passing
+in the -f CompUnitName option. This can also be specified more than once. And
+you can mix the two to specify "this comp unit in this module". So, for
+instance,
+
+::
+
+  (lldb) breakpoint set -P MyModule.MyResolverClass -s a.out
+
+will use your resolver, but will only recurse into or accept new locations in
+the module a.out.
+
+Another option for creating scripted breakpoints is to use the
+SBTarget.CreateBreakpointFromScript API. This one has the advantage that you
+can pass in an arbitrary SBStructuredData object, so you can create more
+complex parametrizations. SBStructuredData has a handy SetFromJSON method which
+you can use for this purpose. Your __init__ function gets passed this
+SBStructuredData object. This API also allows you to directly provide the list
+of Modules and the list of CompileUnits that will make up the SearchFilter. If
+you pass in empty lists, the breakpoint will use the default "search
+everywhere,accept everything" filter.
+
+Using the python API' to create custom stepping logic
+-----------------------------------------------------
+
+A slightly esoteric use of the Python API's is to construct custom stepping
+types. LLDB's stepping is driven by a stack of "thread plans" and a fairly
+simple state machine that runs the plans. You can create a Python class that
+works as a thread plan, and responds to the requests the state machine makes to
+run its operations.
+
+There is a longer discussion of scripted thread plans and the state machine,
+and several interesting examples of their use in:
+
+https://github.com/llvm/llvm-project/blob/master/lldb/examples/python/scripted_step.py
+
+And for a MUCH fuller discussion of the whole state machine, see:
+
+https://github.com/llvm/llvm-project/blob/master/lldb/include/lldb/Target/ThreadPlan.h
+
+If you are reading those comments it is useful to know that scripted thread
+plans are set to be "MasterPlans", and not "OkayToDiscard".
+
+To implement a scripted step, you define a python class that has the following
+methods:
+
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+| Name              | Arguments                          | Description                                                                           |
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+| **__init__**      | **thread_plan: lldb.SBThreadPlan** | This is the underlying SBThreadPlan that is pushed onto the plan stack.               |
+|                   |                                    |             You will want to store this away in an ivar.  Also, if you are going to   |
+|                   |                                    |             use one of the canned thread plans, you can queue it at this point.       |
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+| **explains_stop** | **event: lldb.SBEvent**            | Return True if this stop is part of your thread plans logic, false otherwise.         |
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+| **is_stale**      | **None**                           | If your plan is no longer relevant (for instance, you were                            |
+|                   |                                    |             stepping in a particular stack frame, but some other operation            |
+|                   |                                    |             pushed that frame off the stack) return True and your plan will           |
+|                   |                                    |             get popped.                                                               |
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+| **should_step**   | **None**                           | Return True if you want lldb to instruction step one instruction,                     |
+|                   |                                    |             or False to continue till the next breakpoint is hit.                     |
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+| **should_stop**   | **event: lldb.SBEvent**            | If your plan wants to stop and return control to the user at this point, return True. |
+|                   |                                    |             If your plan is done at this point, call SetPlanComplete on your          |
+|                   |                                    |             thread plan instance.                                                     |
+|                   |                                    |             Also, do any work you need here to set up the next stage of stepping.     |
++-------------------+------------------------------------+---------------------------------------------------------------------------------------+
+
+To use this class to implement a step, use the command:
+
+::
+
+  (lldb) thread step-scripted -C MyModule.MyStepPlanClass
+
+Or use the SBThread.StepUsingScriptedThreadPlan API. The SBThreadPlan passed
+into your __init__ function can also push several common plans (step
+in/out/over and run-to-address) in front of itself on the stack, which can be
+used to compose more complex stepping operations. When you use subsidiary plans
+your explains_stop and should_stop methods won't get called until the
+subsidiary plan is done, or the process stops for an event the subsidiary plan
+doesn't explain. For instance, step over plans don't explain a breakpoint hit
+while performing the step-over.
+
+
+Create a new lldb command using a Python function
+-------------------------------------------------
+
+Python functions can be used to create new LLDB command interpreter commands,
+which will work like all the natively defined lldb commands. This provides a
+very flexible and easy way to extend LLDB to meet your debugging requirements.
+
+To write a python function that implements a new LLDB command define the
+function to take four arguments as follows:
+
+::
+
+  def command_function(debugger, command, result, internal_dict):
+      # Your code goes here
+
+Optionally, you can also provide a Python docstring, and LLDB will use it when providing help for your command, as in:
+
+::
+
+  def command_function(debugger, command, result, internal_dict):
+      """This command takes a lot of options and does many fancy things"""
+      # Your code goes here
+
+Starting with SVN revision 218834, LLDB Python commands can also take an
+SBExecutionContext as an argument. This is useful in cases where the command's
+notion of where to act is independent of the currently-selected entities in the
+debugger.
+
+This feature is enabled if the command-implementing function can be recognized
+as taking 5 arguments, or a variable number of arguments, and it alters the
+signature as such:
+
+::
+
+  def command_function(debugger, command, exe_ctx, result, internal_dict):
+      # Your code goes here
+
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+| Argument          | Type                           | Description                                                                                                                      |
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+| **debugger**      | **lldb.SBDebugger**            | The current debugger object.                                                                                                     |
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+| **command**       | **python string**              | A python string containing all arguments for your command. If you need to chop up the arguments                                  |
+|                   |                                |             try using the **shlex** module's shlex.split(command) to properly extract the                                        |
+|                   |                                |             arguments.                                                                                                           |
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+| **exe_ctx**       | **lldb.SBExecutionContext**    | An execution context object carrying around information on the inferior process' context in which the command is expected to act |
+|                   |                                |                                                                                                                                  |
+|                   |                                | *Optional since SVN r218834, unavailable before*                                                                                 |
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+| **result**        | **lldb.SBCommandReturnObject** | A return object which encapsulates success/failure information for the command and output text                                   |
+|                   |                                |             that needs to be printed as a result of the command. The plain Python "print" command also works but                 |
+|                   |                                |             text won't go in the result by default (it is useful as a temporary logging facility).                               |
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+| **internal_dict** | **python dict object**         | The dictionary for the current embedded script session which contains all variables                                              |
+|                   |                                |             and functions.                                                                                                       |
++-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+
+
+Starting with SVN revision 232224, Python commands can also be implemented by
+means of a class which should implement the following interface:
+
+::
+
+  class CommandObjectType:
+      def __init__(self, debugger, session_dict):
+          this call should initialize the command with respect to the command interpreter for the passed-in debugger
+      def __call__(self, debugger, command, exe_ctx, result):
+          this is the actual bulk of the command, akin to Python command functions
+      def get_short_help(self):
+          this call should return the short help text for this command[1]
+      def get_long_help(self):
+          this call should return the long help text for this command[1]
+
+[1] This method is optional.
+
+As a convenience, you can treat the result object as a Python file object, and
+say
+
+::
+
+  print >>result, "my command does lots of cool stuff"
+
+SBCommandReturnObject and SBStream both support this file-like behavior by
+providing write() and flush() calls at the Python layer.
+
+One other handy convenience when defining lldb command-line commands is the
+command command script import which will import a module specified by file
+path, so you don't have to change your PYTHONPATH for temporary scripts. It
+also has another convenience that if your new script module has a function of
+the form:
+
+::
+
+  def __lldb_init_module(debugger, internal_dict):
+      # Command Initialization code goes here
+
+where debugger and internal_dict are as above, that function will get run when
+the module is loaded allowing you to add whatever commands you want into the
+current debugger. Note that this function will only be run when using the LLDB
+command command script import, it will not get run if anyone imports your
+module from another module. If you want to always run code when your module is
+loaded from LLDB or when loaded via an import statement in python code you can
+test the lldb.debugger object, since you imported the module at the top of the
+python ls.py module. This test must be in code that isn't contained inside of
+any function or class, just like the standard test for __main__ like all python
+modules usually do. Sample code would look like:
+
+::
+
+  if __name__ == '__main__':
+      # Create a new debugger instance in your module if your module
+      # can be run from the command line. When we run a script from
+      # the command line, we won't have any debugger object in
+      # lldb.debugger, so we can just create it if it will be needed
+      lldb.debugger = lldb.SBDebugger.Create()
+  elif lldb.debugger:
+      # Module is being run inside the LLDB interpreter
+      lldb.debugger.HandleCommand('command script add -f ls.ls ls')
+      print 'The "ls" python command has been installed and is ready for use.'
+
+Now we can create a module called ls.py in the file ~/ls.py that will implement
+a function that can be used by LLDB's python command code:
+
+::
+
+  #!/usr/bin/python
+
+  import lldb
+  import commands
+  import optparse
+  import shlex
+
+  def ls(debugger, command, result, internal_dict):
+      print >>result, (commands.getoutput('/bin/ls %s' % command))
+
+  # And the initialization code to add your commands
+  def __lldb_init_module(debugger, internal_dict):
+      debugger.HandleCommand('command script add -f ls.ls ls')
+      print 'The "ls" python command has been installed and is ready for use.'
+
+Now we can load the module into LLDB and use it
+
+::
+
+  % lldb
+  (lldb) command script import ~/ls.py
+  The "ls" python command has been installed and is ready for use.
+  (lldb) ls -l /tmp/
+  total 365848
+  -rw-r--r--@  1 someuser  wheel         6148 Jan 19 17:27 .DS_Store
+  -rw-------   1 someuser  wheel         7331 Jan 19 15:37 crash.log
+
+A more interesting template has been created in the source repository that can
+help you to create lldb command quickly:
+
+https://github.com/llvm/llvm-project/blob/master/lldb/examples/python/cmdtemplate.py
+
+A commonly required facility is being able to create a command that does some
+token substitution, and then runs a different debugger command (usually, it
+po'es the result of an expression evaluated on its argument). For instance,
+given the following program:
+
+::
+
+  #import <Foundation/Foundation.h>
+  NSString*
+  ModifyString(NSString* src)
+  {
+  	return [src stringByAppendingString:@"foobar"];
+  }
+
+  int main()
+  {
+  	NSString* aString = @"Hello world";
+  	NSString* anotherString = @"Let's be friends";
+  	return 1;
+  }
+
+you may want a pofoo X command, that equates po [ModifyString(X)
+capitalizedString]. The following debugger interaction shows how to achieve
+that goal:
+
+::
+
+  (lldb) script
+  Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
+  >>> def pofoo_funct(debugger, command, result, internal_dict):
+  ...	cmd = "po [ModifyString(" + command + ") capitalizedString]"
+  ...	lldb.debugger.HandleCommand(cmd)
+  ...
+  >>> ^D
+  (lldb) command script add pofoo -f pofoo_funct
+  (lldb) pofoo aString
+  $1 = 0x000000010010aa00 Hello Worldfoobar
+  (lldb) pofoo anotherString
+  $2 = 0x000000010010aba0 Let's Be Friendsfoobar
+
+Using the lldb.py module in Python
+----------------------------------
+
+LLDB has all of its core code build into a shared library which gets used by
+the lldb command line application. On Mac OS X this shared library is a
+framework: LLDB.framework and on other unix variants the program is a shared
+library: lldb.so. LLDB also provides an lldb.py module that contains the
+bindings from LLDB into Python. To use the LLDB.framework to create your own
+stand-alone python programs, you will need to tell python where to look in
+order to find this module. This is done by setting the PYTHONPATH environment
+variable, adding a path to the directory that contains the lldb.py python
+module. The lldb driver program has an option to report the path to the lldb
+module. You can use that to point to correct lldb.py:
+
+For csh and tcsh:
+
+::
+
+  % setenv PYTHONPATH `lldb -P`
+
+For sh and bash:
+
+::
+
+  % export PYTHONPATH=`lldb -P`
+
+Alternately, you can append the LLDB Python directory to the sys.path list
+directly in your Python code before importing the lldb module.
+
+Now your python scripts are ready to import the lldb module. Below is a python
+script that will launch a program from the current working directory called
+"a.out", set a breakpoint at "main", and then run and hit the breakpoint, and
+print the process, thread and frame objects if the process stopped:
+
+::
+
+  #!/usr/bin/python
+
+  import lldb
+  import os
+
+  def disassemble_instructions(insts):
+      for i in insts:
+          print i
+
+  # Set the path to the executable to debug
+  exe = "./a.out"
+
+  # Create a new debugger instance
+  debugger = lldb.SBDebugger.Create()
+
+  # When we step or continue, don't return from the function until the process
+  # stops. Otherwise we would have to handle the process events ourselves which, while doable is
+  #a little tricky.  We do this by setting the async mode to false.
+  debugger.SetAsync (False)
+
+  # Create a target from a file and arch
+  print "Creating a target for '%s'" % exe
+
+  target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
+
+  if target:
+      # If the target is valid set a breakpoint at main
+      main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename());
+
+      print main_bp
+
+      # Launch the process. Since we specified synchronous mode, we won't return
+      # from this function until we hit the breakpoint at main
+      process = target.LaunchSimple (None, None, os.getcwd())
+
+      # Make sure the launch went ok
+      if process:
+          # Print some simple process info
+          state = process.GetState ()
+          print process
+          if state == lldb.eStateStopped:
+              # Get the first thread
+              thread = process.GetThreadAtIndex (0)
+              if thread:
+                  # Print some simple thread info
+                  print thread
+                  # Get the first frame
+                  frame = thread.GetFrameAtIndex (0)
+                  if frame:
+                      # Print some simple frame info
+                      print frame
+                      function = frame.GetFunction()
+                      # See if we have debug info (a function)
+                      if function:
+                          # We do have a function, print some info for the function
+                          print function
+                          # Now get all instructions for this function and print them
+                          insts = function.GetInstructions(target)
+                          disassemble_instructions (insts)
+                      else:
+                          # See if we have a symbol in the symbol table for where we stopped
+                          symbol = frame.GetSymbol();
+                          if symbol:
+                              # We do have a symbol, print some info for the symbol
+                              print symbol
+
+Writing lldb frame recognizers in Python
+----------------------------------------
+
+Frame recognizers allow for retrieving information about special frames based
+on ABI, arguments or other special properties of that frame, even without
+source code or debug info. Currently, one use case is to extract function
+arguments that would otherwise be unaccesible, or augment existing arguments.
+
+Adding a custom frame recognizer is done by implementing a Python class and
+using the 'frame recognizer add' command. The Python class should have a
+'get_recognized_arguments' method and it will receive an argument of type
+lldb.SBFrame representing the current frame that we are trying to recognize.
+The method should return a (possibly empty) list of lldb.SBValue objects that
+represent the recognized arguments.
+
+An example of a recognizer that retrieves the file descriptor values from libc
+functions 'read', 'write' and 'close' follows:
+
+::
+
+  class LibcFdRecognizer(object):
+    def get_recognized_arguments(self, frame):
+      if frame.name in ["read", "write", "close"]:
+        fd = frame.EvaluateExpression("$arg1").unsigned
+        value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd)
+        return [value]
+      return []
+
+The file containing this implementation can be imported via 'command script
+import' and then we can register this recognizer with 'frame recognizer add'.
+It's important to restrict the recognizer to the libc library (which is
+libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
+in other modules:
+
+::
+
+  (lldb) command script import .../fd_recognizer.py
+  (lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
+
+When the program is stopped at the beginning of the 'read' function in libc, we can view the recognizer arguments in 'frame variable':
+
+::
+
+  (lldb) b read
+  (lldb) r
+  Process 1234 stopped
+  * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
+      frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
+  (lldb) frame variable
+  (int) fd = 3




More information about the lldb-commits mailing list