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

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lldb/docs/.htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Redirect 301 /resources/architecture.html https://lldb.llvm.org/resources/overvi
Redirect 301 /design/sbapi.html https://lldb.llvm.org/resources/sbapi.html
Redirect 301 /design/overview.html https://lldb.llvm.org/resources/overview.html
Redirect 301 /use/extensions.html https://lldb.llvm.org/resources/extensions.html
Redirect 301 /use/python.html https://lldb.llvm.org/use/tutorials/script-driven-debugging.html
Redirect 301 /resources/bots.html https://lldb.llvm.org/resources/test.html

# Redirect old Python API to new Python API.
Expand Down
1,141 changes: 18 additions & 1,123 deletions lldb/docs/use/python-reference.rst

Large diffs are not rendered by default.

799 changes: 0 additions & 799 deletions lldb/docs/use/python.rst

This file was deleted.

62 changes: 62 additions & 0 deletions lldb/docs/use/tutorials/accessing-documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Accessing Script 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:

```python3
(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:

```python3
(lldb) script help(lldb.SBFrame)
Help on class SBFrame in module lldb:

class SBFrame(builtins.object)
| SBFrame(*args)
|
| 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:

```python3
(lldb) script help(lldb.process)
Help on SBProcess in module lldb object:

class SBProcess(builtins.object)
| SBProcess(*args)
|
| 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
| # ==================================================
...
```
42 changes: 42 additions & 0 deletions lldb/docs/use/tutorials/automating-stepping-logic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Automating 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.

The base class for the [ScriptedThreadPlan](https://lldb.llvm.org/python_api/lldb.plugins.scripted_thread_plan.ScriptedThreadPlan.html) is provided as part of the lldb python module, making it easy to derive a new class from it.

There is a longer discussion of scripted thread plans and the state machine,
and several interesting examples of their use in [scripted_step.py](https://github.com/llvm/llvm-project/blob/main/lldb/examples/python/scripted_step.py)
and for a **MUCH** fuller discussion of the whole state machine, see [ThreadPlan.h](https://github.com/llvm/llvm-project/blob/main/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 either ***"ControllingPlans"*** or ***"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:

```python3
(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.
85 changes: 85 additions & 0 deletions lldb/docs/use/tutorials/breakpoint-triggered-scripts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Breakpoint-Triggered Scripts

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:

```python3
def breakpoint_function_wrapper(frame, bp_loc, internal_dict):
# Your code goes here
```

or:

```python3
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:

```python3
(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:

```python3
(lldb) breakpoint command delete 1
```
128 changes: 128 additions & 0 deletions lldb/docs/use/tutorials/creating-custom-breakpoints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Custom Breakpoint Resolvers

Another use of the Python API's in lldb is to create a custom breakpoint
resolver.

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:
1. the Searcher
2. the Resolver,
3. 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.

### Breakpoint Searcher

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.

### Breakpoint Resolver

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 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.

### Scripted Breakpoint Resolver

At present, when adding a ScriptedBreakpoint 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` `extra_args`: `lldb.SBStructuredData` | This is the constructor for the new Resolver. `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.BreakpointCreateFromScript 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.
51 changes: 51 additions & 0 deletions lldb/docs/use/tutorials/custom-frame-recognizers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Detecting Patterns With Recognizers

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 inaccessible, 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 implement the
`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:

```python3
class LibcFdRecognizer:
def get_recognized_arguments(self, frame: lldb.SBFrame):
if frame.name in ["read", "write", "close"]:
fd = frame.EvaluateExpression("$arg1").unsigned
target = frame.thread.process.target
value = 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:

```c++
(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':

```c++
(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
```
Loading
Loading