mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 04:56:07 +00:00
742 lines
29 KiB
ReStructuredText
742 lines
29 KiB
ReStructuredText
Tutorial
|
|
========
|
|
|
|
This document describes how to use LLDB if you are already familiar with
|
|
GDB's command set. We will start with some details on LLDB command structure and
|
|
syntax.
|
|
|
|
Command Structure
|
|
-----------------
|
|
|
|
Unlike GDB's quite free-form commands, LLDB's are more structured. All commands
|
|
are of the form:
|
|
|
|
::
|
|
|
|
<noun> <verb> [-options [option-value]] [argument [argument...]]
|
|
|
|
The command line parsing is done before command execution, so it is the same for
|
|
all commands. The command syntax for basic commands is very simple.
|
|
|
|
* Arguments, options and option values are all white-space separated.
|
|
* Either single ``'`` or double-quotes ``"`` (in pairs) are used to protect white-spaces
|
|
in an argument.
|
|
* Escape backslashes and double quotes within arguments should be escaped
|
|
with a backslash ``\``.
|
|
|
|
This makes LLDB's commands more regular, but it also means you may have to quote
|
|
some arguments in LLDB that you would not in GDB.
|
|
|
|
There is one other special quote character in LLDB - the backtick `````.
|
|
If you put backticks around an argument or option value, LLDB will run the text
|
|
of the value through the expression parser, and the result of the expression
|
|
will be passed to the command. So for instance, if ``len`` is a local
|
|
``int`` variable with the value ``5``, then the command:
|
|
|
|
::
|
|
|
|
(lldb) memory read -c `len` 0x12345
|
|
|
|
Will receive the value ``5`` for the count option, rather than the string ``len``.
|
|
|
|
Options can be placed anywhere on the command line, but if the arguments begin
|
|
with a ``-`` then you have to tell LLDB that you are done with options for the
|
|
current command by adding an option termination: ``--``.
|
|
|
|
So for instance, if you want to launch a process and give the ``process launch``
|
|
command the ``--stop-at-entry`` option, yet you want the process you are about
|
|
to launch to be launched with the arguments ``-program_arg value``, you would type:
|
|
|
|
::
|
|
|
|
(lldb) process launch --stop-at-entry -- -program_arg value
|
|
|
|
We also tried to reduce the number of special purpose argument parsers, which
|
|
sometimes forces the user to be explicit about their intentions. The first
|
|
instance you willl see of this is the breakpoint command. In GDB, to set a
|
|
breakpoint, you might enter:
|
|
|
|
::
|
|
|
|
(gdb) break foo.c:12
|
|
|
|
To break at line ``12`` of ``foo.c``, and:
|
|
|
|
::
|
|
|
|
(gdb) break foo
|
|
|
|
To break at the function ``foo``. As time went on, the parser that tells ``foo.c:12``
|
|
from ``foo`` from ``foo.c::foo`` (which means the function ``foo`` in the file ``foo.c``)
|
|
got more and more complex. Especially in C++ there are times where there is
|
|
really no way to specify the function you want to break on.
|
|
|
|
The LLDB commands are more verbose but also more precise and allow for
|
|
intelligent auto completion.
|
|
|
|
To set the same file and line breakpoint in LLDB you can enter either of:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --file foo.c --line 12
|
|
(lldb) breakpoint set -f foo.c -l 12
|
|
|
|
To set a breakpoint on a function named ``foo`` in LLDB you can enter either of:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --name foo
|
|
(lldb) breakpoint set -n foo
|
|
|
|
You can use the ``--name`` option multiple times to make a breakpoint on a set of
|
|
functions as well. This is convenient since it allows you to set common
|
|
conditions or commands without having to specify them multiple times:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --name foo --name bar
|
|
|
|
Setting breakpoints by name is even more specialized in LLDB as you can specify
|
|
that you want to set a breakpoint at a function by method name. To set a
|
|
breakpoint on all C++ methods named ``foo`` you can enter either of:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --method foo
|
|
(lldb) breakpoint set -M foo
|
|
|
|
|
|
To set a breakpoint Objective-C selectors named ``alignLeftEdges:`` you can enter either of:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --selector alignLeftEdges:
|
|
(lldb) breakpoint set -S alignLeftEdges:
|
|
|
|
You can limit any breakpoints to a specific executable image by using the
|
|
``--shlib <path>`` (``-s <path>`` for short):
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --shlib foo.dylib --name foo
|
|
(lldb) breakpoint set -s foo.dylib -n foo
|
|
|
|
The ``--shlib`` option can also be repeated to specify several shared libraries.
|
|
|
|
Suggestions on more interesting primitives of this sort are also very welcome.
|
|
|
|
Just like GDB, the LLDB command interpreter does a shortest unique string match
|
|
on command names, so the following two commands will both execute the same
|
|
command:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]"
|
|
(lldb) br s -n "-[SKTGraphicView alignLeftEdges:]"
|
|
|
|
LLDB also supports command completion for source file names, symbol names, file
|
|
names, etc. Completion is initiated by hitting TAB. Individual options in a
|
|
command can have different completers, so for instance, the ``--file <path>``
|
|
option in ``breakpoint`` completes to source files, the ``--shlib <path>`` option
|
|
to currently loaded shared libraries, etc. You can even do things like if you
|
|
specify ``--shlib <path>``, and are completing on ``--file <path>``, LLDB will only
|
|
list source files in the shared library specified by ``--shlib <path>``.
|
|
|
|
The individual commands are pretty extensively documented. You can use the ``help``
|
|
command to get an overview of which commands are available or to obtain details
|
|
about specific commands. There is also an ``apropos`` command that will search the
|
|
help text for all commands for a particular word and dump a summary help string
|
|
for each matching command.
|
|
|
|
Finally, there is a mechanism to construct aliases for commonly used commands.
|
|
For instance, if you get annoyed typing:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --file foo.c --line 12
|
|
|
|
You can do:
|
|
|
|
::
|
|
|
|
(lldb) command alias bfl breakpoint set -f %1 -l %2
|
|
(lldb) bfl foo.c 12
|
|
|
|
LLDB has a few aliases for commonly used commands (e.g. ``step``, ``next`` and
|
|
``continue``) but it does not try to be exhaustive because in our experience it
|
|
is more convenient to make the basic commands unique down to a letter or two,
|
|
and then learn these sequences than to fill the namespace with lots of aliases,
|
|
and then have to type them all the way out.
|
|
|
|
If the alias abbreviation or the full alias command collides with another
|
|
existing command, the command resolver will prefer to use the alias over any
|
|
other command as far as there is only one alias command match.
|
|
|
|
However, users are free to customize LLDB's command set however they like, and
|
|
since LLDB reads the file ``~/.lldbinit`` at startup, you can store all your
|
|
aliases there and they will be generally available to you. Your aliases are
|
|
also documented in the ``help`` command so you can remind yourself of what you have
|
|
set up.
|
|
|
|
One alias of note that LLDB does include by popular demand is a weak emulator of
|
|
GDB's ``break`` command. It does not try to do everything that GDB's break command
|
|
does (for instance, it does not handle ``foo.c::bar``). But it mostly works, and
|
|
makes the transition easier. Also, by popular demand, it is aliased to ``b``. If you
|
|
actually want to learn the LLDB command set natively, that means it will get in
|
|
the way of the rest of the breakpoint commands. Fortunately, if you do not like
|
|
one of our aliases, you can easily get rid of it by running, for example:
|
|
|
|
::
|
|
|
|
(lldb) command unalias b
|
|
|
|
You can also do:
|
|
|
|
::
|
|
|
|
(lldb) command alias b breakpoint
|
|
|
|
So you can run the native LLDB breakpoint command with just ``b``.
|
|
|
|
The LLDB command parser also supports "raw" commands, where, after command
|
|
options are stripped off, the rest of the command string is passed
|
|
uninterpreted to the command. This is convenient for commands whose arguments
|
|
might be some complex expression that would be painful to backslash protect.
|
|
For instance, the ``expression`` command is a "raw" command for obvious reasons.
|
|
The ``help`` output for a command will tell you if it is "raw" or not, so you
|
|
know what to expect. The one thing you have to watch out for is that since raw
|
|
commands still can have options, if your command string has dashes in it,
|
|
you will have to indicate these are not option markers by putting ``--`` after the
|
|
command name, but before your command string.
|
|
|
|
LLDB also has a built-in Python interpreter, which is accessible by the
|
|
``script`` command. All the functionality of the debugger is available as classes
|
|
in the Python interpreter, so the more complex commands that in GDB you would
|
|
introduce with the ``define`` command can be done by writing Python functions
|
|
using the LLDB Python library, then loading the scripts into your running
|
|
session and accessing them with the ``script`` command.
|
|
|
|
Loading a Program Into LLDB
|
|
---------------------------
|
|
|
|
First you need to set the program to debug. As with GDB, you can start LLDB and
|
|
specify the file you wish to debug on the command line:
|
|
|
|
::
|
|
|
|
$ lldb /Projects/Sketch/build/Debug/Sketch.app
|
|
Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
|
|
|
|
Or you can specify it after the fact with the ``file`` command:
|
|
|
|
::
|
|
|
|
$ lldb
|
|
(lldb) file /Projects/Sketch/build/Debug/Sketch.app
|
|
Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
|
|
|
|
Setting Breakpoints
|
|
-------------------
|
|
|
|
We have discussed how to set breakpoints above. You can use ``help breakpoint set``
|
|
to see all the options for breakpoint setting. For instance, you could do:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --selector alignLeftEdges:
|
|
Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1
|
|
|
|
You can find out about the breakpoints you have set with:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint list
|
|
Current breakpoints:
|
|
1: name = 'alignLeftEdges:', locations = 1, resolved = 1
|
|
1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0
|
|
|
|
|
|
Note that setting a breakpoint creates a logical breakpoint, which could
|
|
resolve to one or more locations. For instance, break by selector would set a
|
|
breakpoint on all the methods that implement that selector in the classes in
|
|
your program. Similarly, a file and line breakpoint might result in multiple
|
|
locations if that file and line were inlined in different places in your code.
|
|
|
|
The logical breakpoint has an integer id, and its locations have an id within
|
|
their parent breakpoint (the two are joined by a ``.``, e.g. ``1.1`` in the example
|
|
above).
|
|
|
|
Also logical breakpoints remain live so that if another shared library were
|
|
to be loaded that had another implementation of the ``alignLeftEdges:`` selector,
|
|
the new location would be added to breakpoint ``1`` (e.g. a ``1.2`` breakpoint would
|
|
be set on the newly loaded selector).
|
|
|
|
The other piece of information in the breakpoint listing is whether the
|
|
breakpoint location was resolved or not. A location gets resolved when the file
|
|
address it corresponds to gets loaded into the program you are debugging. For
|
|
instance if you set a breakpoint in a shared library that then gets unloaded,
|
|
that breakpoint location will remain, but it will no longer be resolved.
|
|
|
|
One other thing to note for GDB users is that LLDB acts like GDB with:
|
|
|
|
::
|
|
|
|
(gdb) set breakpoint pending on
|
|
|
|
Which means that LLDB will always make a breakpoint from your specification, even if it
|
|
could not find any locations that match the specification. You can tell whether
|
|
the expression was resolved or not by checking the locations field in
|
|
``breakpoint list``, and LLDB reports the breakpoint as ``pending`` when you set it so
|
|
you can tell you have made a typo more easily, if that was indeed the reason no
|
|
locations were found:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set --file foo.c --line 12
|
|
Breakpoint created: 2: file ='foo.c', line = 12, locations = 0 (pending)
|
|
WARNING: Unable to resolve breakpoint to any actual locations.
|
|
|
|
You can delete, disable, set conditions and ignore counts either on all the
|
|
locations generated by your logical breakpoint, or on any one of the particular
|
|
locations your specification resolved to. For instance, if you wanted to add a
|
|
command to print a backtrace when you hit this breakpoint you could do:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint command add 1.1
|
|
Enter your debugger command(s). Type 'DONE' to end.
|
|
> bt
|
|
> DONE
|
|
|
|
By default, the breakpoint command add command takes LLDB command line
|
|
commands. You can also specify this explicitly by passing the ``--command``
|
|
option. Use ``--script`` if you want to implement your breakpoint command using
|
|
the Python script instead.
|
|
|
|
This is a convenient point to bring up another feature of the LLDB command
|
|
``help``. Do:
|
|
|
|
::
|
|
|
|
(lldb) help break command add
|
|
Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.
|
|
|
|
Syntax: breakpoint command add <cmd-options> <breakpt-id>
|
|
etc...
|
|
|
|
When you see arguments to commands specified in the ``Syntax`` section in angle brackets
|
|
like ``<breakpt-id>``, that indicates that that is some common argument type that
|
|
you can get further help on from the command system. So in this case you could
|
|
do:
|
|
|
|
::
|
|
|
|
(lldb) help <breakpt-id>
|
|
<breakpt-id> -- Breakpoint ID's consist major and minor numbers; the major etc...
|
|
|
|
Breakpoint Names
|
|
----------------
|
|
|
|
Breakpoints carry two orthogonal sets of information: one specifies where to set
|
|
the breakpoint, and the other how to react when the breakpoint is hit. The latter
|
|
set of information (e.g. commands, conditions, hit-count, auto-continue...) we
|
|
call breakpoint options.
|
|
|
|
It is fairly common to want to apply one set of options to a number of breakpoints.
|
|
For instance, you might want to check that ``self == nil`` and if it is, print a
|
|
backtrace and continue, on a number of methods. One convenient way to do that would
|
|
be to make all the breakpoints, then configure the options with:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint modify -c "self == nil" -C bt --auto-continue 1 2 3
|
|
|
|
That is not too bad, but you have to repeat this for every new breakpoint you make,
|
|
and if you wanted to change the options, you have to remember all the ones you are
|
|
using this way.
|
|
|
|
Breakpoint names provide a convenient solution to this problem. The simple solution
|
|
would be to use the name to gather the breakpoints you want to affect this way into
|
|
a group. So when you make the breakpoint you would do:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint set -N SelfNil
|
|
|
|
Then when you have made all your breakpoints, you can set up or modify the options
|
|
using the name to collect all the relevant breakpoints.
|
|
|
|
::
|
|
|
|
(lldb) breakpoint modify -c "self == nil" -C bt --auto-continue SelfNil
|
|
|
|
That is better, but suffers from the problem that when new breakpoints get
|
|
added, they do not pick up these modifications, and the options only exist in
|
|
the context of actual breakpoints, so they are hard to store and reuse.
|
|
|
|
An even better solution is to make a fully configured breakpoint name:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint name configure -c "self == nil" -C bt --auto-continue SelfNil
|
|
|
|
Then you can apply the name to your breakpoints, and they will all pick up
|
|
these options. The connection from name to breakpoints remains live, so when
|
|
you change the options configured on the name, all the breakpoints pick up
|
|
those changes. This makes it easy to use configured names to experiment with
|
|
your options.
|
|
|
|
You can make breakpoint names in your ``.lldbinit`` file, so you can use them to
|
|
can behaviors that you have found useful and reapply them in future sessions.
|
|
|
|
You can also make a breakpoint name from the options set on a breakpoint:
|
|
|
|
::
|
|
|
|
(lldb) breakpoint name configure -B 1 SelfNil
|
|
|
|
which makes it easy to copy behavior from one breakpoint to a set of others.
|
|
|
|
Setting Watchpoints
|
|
-------------------
|
|
|
|
In addition to breakpoints, you can use help watchpoint to see all the commands
|
|
for watchpoint manipulations. For instance, you might do the following to watch
|
|
a variable called ``global`` for write operation, but only stop if the condition
|
|
``(global==5)`` is true:
|
|
|
|
::
|
|
|
|
(lldb) watch set var global
|
|
Watchpoint created: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
|
|
declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
|
|
(lldb) watch modify -c '(global==5)'
|
|
(lldb) watch list
|
|
Current watchpoints:
|
|
Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
|
|
declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
|
|
condition = '(global==5)'
|
|
(lldb) c
|
|
Process 15562 resuming
|
|
(lldb) about to write to 'global'...
|
|
Process 15562 stopped and was programmatically restarted.
|
|
Process 15562 stopped and was programmatically restarted.
|
|
Process 15562 stopped and was programmatically restarted.
|
|
Process 15562 stopped and was programmatically restarted.
|
|
Process 15562 stopped
|
|
* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
|
|
frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
|
|
13
|
|
14 static void modify(int32_t &var) {
|
|
15 ++var;
|
|
-> 16 }
|
|
17
|
|
18 int main(int argc, char** argv) {
|
|
19 int local = 0;
|
|
(lldb) bt
|
|
* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
|
|
frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
|
|
frame #1: 0x0000000100000eac a.out`main + 108 at main.cpp:25
|
|
frame #2: 0x00007fff8ac9c7e1 libdyld.dylib`start + 1
|
|
(lldb) frame var global
|
|
(int32_t) global = 5
|
|
(lldb) watch list -v
|
|
Current watchpoints:
|
|
Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
|
|
declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
|
|
condition = '(global==5)'
|
|
hit_count = 5 ignore_count = 0
|
|
(lldb)
|
|
|
|
Starting or Attaching to Your Program
|
|
-------------------------------------
|
|
|
|
To launch a program in LLDB you will use the ``process launch`` command or one of
|
|
its built in aliases:
|
|
|
|
::
|
|
|
|
(lldb) process launch
|
|
(lldb) run
|
|
(lldb) r
|
|
|
|
You can also attach to a process by process ID or process name. When attaching
|
|
to a process by name, LLDB also supports the ``--waitfor`` option which waits for
|
|
the next process that has that name to show up, and attaches to it
|
|
|
|
::
|
|
|
|
(lldb) process attach --pid 123
|
|
(lldb) process attach --name Sketch
|
|
(lldb) process attach --name Sketch --waitfor
|
|
|
|
After you launch or attach to a process, your process might stop somewhere:
|
|
|
|
::
|
|
|
|
(lldb) process attach -p 12345
|
|
Process 46915 Attaching
|
|
Process 46915 Stopped
|
|
1 of 3 threads stopped with reasons:
|
|
* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
|
|
|
|
Note the line that says ``1 of 3 threads stopped with reasons:`` and the lines
|
|
that follow it. In a multi-threaded environment it is very common for more than
|
|
one thread to hit your breakpoint(s) before the kernel actually returns control
|
|
to the debugger. In that case, you will see all the threads that stopped for
|
|
some interesting reason listed in the stop message.
|
|
|
|
Controlling Your Program
|
|
------------------------
|
|
|
|
After launching, you can continue until you hit your breakpoint. The primitive commands
|
|
for process control all exist under the "thread" command:
|
|
|
|
::
|
|
|
|
(lldb) thread continue
|
|
Resuming thread 0x2c03 in process 46915
|
|
Resuming process 46915
|
|
(lldb)
|
|
|
|
At present you can only operate on one thread at a time, but the design will
|
|
ultimately support saying "step over the function in Thread 1, and step into the
|
|
function in Thread 2, and continue Thread 3" etc. When LLDB eventually supports
|
|
keeping some threads running while others are stopped this will be particularly
|
|
important. For convenience, however, all the stepping commands have easy aliases.
|
|
So ``thread continue`` is just ``c``, etc.
|
|
|
|
The other program stepping commands are pretty much the same as in GDB. You have got:
|
|
|
|
::
|
|
|
|
(lldb) thread step-in // The same as GDB's "step" or "s"
|
|
(lldb) thread step-over // The same as GDB's "next" or "n"
|
|
(lldb) thread step-out // The same as GDB's "finish" or "f"
|
|
|
|
By default, LLDB does defined aliases to all common GDB process control commands
|
|
(``s``, ``step``, ``n``, ``next``, ``finish``). If LLDB is missing any, please add
|
|
them to your ``~/.lldbinit`` file using the ``command alias`` command.
|
|
|
|
LLDB also supports the step by instruction versions:
|
|
|
|
::
|
|
|
|
|
|
(lldb) thread step-inst // The same as GDB's "stepi" / "si"
|
|
(lldb) thread step-over-inst // The same as GDB's "nexti" / "ni"
|
|
|
|
Finally, LLDB has a run until line or frame exit stepping mode:
|
|
|
|
::
|
|
|
|
(lldb) thread until 100
|
|
|
|
This command will run the thread in the current frame until it reaches line 100
|
|
in this frame or stops if it leaves the current frame. This is a pretty close
|
|
equivalent to GDB's ``until`` command.
|
|
|
|
One other useful thing to note about the lldb stepping commands is that they
|
|
are implemented as a stack of interruptible operations. Until the operation -
|
|
e.g. step to the next line - is completed, it will remain on the
|
|
stack. If the step over is interrupted and control returned to you,
|
|
any new stepping commands you issue won't replace the step-over, but instead
|
|
their operations will be pushed onto the stack after the original step over.
|
|
Then each of them will be retired as they are completed, finally returning to the
|
|
original step over operation.
|
|
|
|
Suppose, for instance, you ``step-over`` a source line with a function call.
|
|
If there is a breakpoint in that function, hitting the breakpoint will interrupt
|
|
the step over. At that point, you will likely want to examine the state at
|
|
the breakpoint, maybe stepping around in that frame, or stepping into other
|
|
functions, running some expressions, etc.
|
|
|
|
Because the original step-over has remained on the stack, when you've finished
|
|
your examinations, a simple ``continue`` will resume the original ``step-over``
|
|
operation, and you will arrive at the end of your starting source line in the
|
|
original frame.
|
|
|
|
This saves you from having to keep track of your original intention, and manually
|
|
issuing the requisite number of ``step-out`` commands to get back to the frame
|
|
you were stepping over. The stack maintains that information for you.
|
|
|
|
Hand-called functions using the ``expr`` command are also implemented by
|
|
operations on this same stack. So if you are calling some code with the ``expr`` command,
|
|
and hit a breakpoint during the evaluation of that code, you can examine
|
|
the state where you stopped, and when you're satisfied, issue a
|
|
``continue`` to finish the expression evaluation operation and print the function
|
|
result.
|
|
|
|
You can examine the state of the operations stack using the ``thread plan list``
|
|
command, and if, for instance, you decide you don't actually want that outermost
|
|
next to continue running, you can remove it with the ``thread plan discard``
|
|
command. If you are interested in following this process in more detail, the
|
|
``lldb step`` logging channel is useful source of information.
|
|
|
|
A process, by default, will share the LLDB terminal with the inferior process.
|
|
When in this mode, much like when debugging with GDB, when the process is
|
|
running anything you type will go to the ``STDIN`` of the inferior process. To
|
|
interrupt your inferior program, type ``CTRL+C``.
|
|
|
|
If you attach to a process, or launch a process with the ``--no-stdin`` option,
|
|
the command interpreter is always available to enter commands. It might be a
|
|
little disconcerting to GDB users to always have an ``(lldb)`` prompt. This allows
|
|
you to set a breakpoint, or use any other command without having to explicitly
|
|
interrupt the program you are debugging:
|
|
|
|
::
|
|
|
|
(lldb) process continue
|
|
(lldb) breakpoint set --name stop_here
|
|
|
|
There are many commands that won't work while running, and the command
|
|
interpreter will let you know when this is the case. Please file an issue if
|
|
it does not. This way of operation will set us up for a future debugging
|
|
mode called thread centric debugging. This mode will allow us to run all
|
|
threads and only stop the threads that are at breakpoints or have exceptions or
|
|
signals.
|
|
|
|
The commands that currently work while running include interrupting the process
|
|
to halt execution (``process interrupt``), getting the process status (``process status``),
|
|
breakpoint setting and clearing (``breakpoint [set|clear|enable|disable|list] ...``),
|
|
and memory reading and writing (``memory [read|write] ...``).
|
|
|
|
The question of disabling stdio when running brings up a good opportunity to
|
|
show how to set debugger properties. If you always want to run in
|
|
the ``--no-stdin`` mode, you can set this as a generic process property using the
|
|
LLDB ``settings`` command, which is equivalent to GDB's ``set`` command.
|
|
In this case you would say:
|
|
|
|
::
|
|
|
|
(lldb) settings set target.process.disable-stdio true
|
|
|
|
Over time, GDB's ``set`` command became a wilderness of disordered options, so
|
|
that there were useful options that even experienced GDB users did not know
|
|
about because they were too hard to find. LLDB instead organizes the settings
|
|
hierarchically using the structure of the basic entities in the debugger. For
|
|
the most part anywhere you can specify a setting on a generic entity (threads,
|
|
for example) you can also apply the option to a particular instance. You can
|
|
view the available settings with the command ``settings list`` and there is help
|
|
on the settings command explaining how it works more generally.
|
|
|
|
Examining Thread State
|
|
----------------------
|
|
|
|
Once you have stopped, LLDB will choose a current thread, usually the one that
|
|
stopped "for a reason", and a current frame in that thread (on stop this is
|
|
always the bottom-most frame). Many the commands for inspecting state work on
|
|
this current thread/frame.
|
|
|
|
To inspect the current state of your process, you can start with the threads:
|
|
|
|
::
|
|
|
|
(lldb) thread list
|
|
Process 46915 state is Stopped
|
|
* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
|
|
thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager
|
|
thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib`__workq_kernreturn + 10
|
|
|
|
The ``*`` indicates that Thread 1 is the current thread. To get a backtrace for
|
|
that thread, do:
|
|
|
|
::
|
|
|
|
(lldb) thread backtrace
|
|
thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
|
|
frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
|
|
frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
|
|
frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem _corePerformAction] + 365
|
|
frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 121
|
|
frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenu performKeyEquivalent:] + 272
|
|
frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication _handleKeyEquivalent:] + 559
|
|
frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplication sendEvent:] + 3630
|
|
frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474
|
|
frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364
|
|
frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
|
|
frame #10: 0x0000000100000f20, where = Sketch`start + 52
|
|
|
|
You can also provide a list of threads to backtrace, or the keyword ``all`` to see all threads:
|
|
|
|
::
|
|
|
|
(lldb) thread backtrace all
|
|
|
|
You can select the current thread, which will be used by default in all the
|
|
commands in the next section, with the ``thread select`` command:
|
|
|
|
::
|
|
|
|
(lldb) thread select 2
|
|
|
|
where the thread index is just the one shown in the ``thread list`` listing.
|
|
|
|
|
|
Examining Stack Frame State
|
|
---------------------------
|
|
|
|
The most convenient way to inspect a frame's arguments and local variables is
|
|
to use the ``frame variable`` command:
|
|
|
|
::
|
|
|
|
(lldb) frame variable
|
|
self = (SKTGraphicView *) 0x0000000100208b40
|
|
_cmd = (struct objc_selector *) 0x000000010001bae1
|
|
sender = (id) 0x00000001001264e0
|
|
selection = (NSArray *) 0x00000001001264e0
|
|
i = (NSUInteger) 0x00000001001264e0
|
|
c = (NSUInteger) 0x00000001001253b0
|
|
|
|
As you see above, if you do not specify any variable names, all arguments and
|
|
locals will be shown. If you call ``frame variable`` passing in the names of
|
|
particular local variables, only those variables will be printed. For instance:
|
|
|
|
::
|
|
|
|
(lldb) frame variable self
|
|
(SKTGraphicView *) self = 0x0000000100208b40
|
|
|
|
You can also pass in a path to some sub-element of one of the available locals,
|
|
and that sub-element will be printed. For instance:
|
|
|
|
::
|
|
|
|
(lldb) frame variable self.isa
|
|
(struct objc_class *) self.isa = 0x0000000100023730
|
|
|
|
The ``frame variable`` command is not a full expression parser but it does
|
|
support a few simple operations like ``&``, ``*``, ``->``, ``[]`` (no
|
|
overloaded operators). The array brackets can be used on pointers to treat
|
|
pointers as arrays:
|
|
|
|
::
|
|
|
|
(lldb) frame variable *self
|
|
(SKTGraphicView *) self = 0x0000000100208b40
|
|
(NSView) NSView = {
|
|
(NSResponder) NSResponder = {
|
|
...
|
|
|
|
(lldb) frame variable &self
|
|
(SKTGraphicView **) &self = 0x0000000100304ab
|
|
|
|
(lldb) frame variable argv[0]
|
|
(char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch"
|
|
|
|
The frame variable command will also perform "object printing" operations on
|
|
variables (currently LLDB only supports ObjC printing, using the object's
|
|
``description`` method. Turn this on by passing the ``-o`` flag to frame variable:
|
|
|
|
::
|
|
|
|
(lldb) frame variable -o self (SKTGraphicView *) self = 0x0000000100208b40 <SKTGraphicView: 0x100208b40>
|
|
You can select another frame to view with the "frame select" command
|
|
|
|
(lldb) frame select 9
|
|
frame #9: 0x0000000100015ae3, where = Sketch`function1 + 33 at /Projects/Sketch/SKTFunctions.m:11
|
|
|
|
You can also move up and down the stack by passing the ``--relative`` (``-r``) option.
|
|
We also have built-in aliases ``u`` and ``d`` which behave like their GDB equivalents.
|