You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
38 KiB
302 lines
38 KiB
Frame and Thread Format
|
|
=======================
|
|
|
|
.. contents::
|
|
:local:
|
|
|
|
LLDB has a facility to allow users to define the format of the information that
|
|
generates the descriptions for threads and stack frames. Typically when your
|
|
program stops at a breakpoint you will get two lines that describes why your
|
|
thread stopped and where:
|
|
|
|
::
|
|
|
|
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
|
|
frame #0: test`main at test.c:5
|
|
|
|
Stack backtraces frames also have a similar information line:
|
|
|
|
::
|
|
|
|
(lldb) thread backtrace
|
|
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
|
|
frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19
|
|
frame #1: 0x0000000100000e40 a.out`start + 52
|
|
|
|
The two format strings that govern the printing in these output forms can
|
|
currently be set using the settings set command:
|
|
|
|
::
|
|
|
|
(lldb) settings set thread-stop-format STRING
|
|
(lldb) settings set frame-format STRING
|
|
|
|
The first of these is an abbreviated thread output, that just contains data
|
|
about the thread, and not the stop frame. It will always get used in situations
|
|
where the frame output follows immediately, so that information would be
|
|
redundant. The second is the frame printing.
|
|
|
|
There is another thread format used for commands like thread list where the
|
|
thread information isn't followed by frame info. In that case, it is convenient
|
|
to have frame zero information in the thread output. That format is set by:
|
|
|
|
::
|
|
|
|
(lldb) settings set thread-format STRING
|
|
|
|
|
|
Format Strings
|
|
--------------
|
|
|
|
So what is the format of the format strings? Format strings can contain plain
|
|
text, control characters and variables that have access to the current program
|
|
state.
|
|
|
|
Normal characters are any text that doesn't contain a ``{``, ``}``, ``$``, or
|
|
``\`` character.
|
|
|
|
Variable names are found in between a ``${`` prefix, and end with a ``}``
|
|
suffix. In other words, a variable looks like ``${frame.pc}``.
|
|
|
|
Variables
|
|
---------
|
|
|
|
A complete list of currently supported format string variables is listed below:
|
|
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| **Variable Name** | **Description** |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``file.basename`` | The current compile unit file basename for the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``file.fullpath`` | The current compile unit file fullpath for the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``language`` | The current compile unit language for the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.index`` | The frame index (0, 1, 2, 3...) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.no-debug`` | Evaluates to true if the frame has no debug info. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.pc`` | The generic frame register for the program counter. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.sp`` | The generic frame register for the stack pointer. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.fp`` | The generic frame register for the frame pointer. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.flags`` | The generic frame register for the flags register. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``frame.reg.NAME`` | Access to any platform specific register by name (replace ``NAME`` with the name of the desired register). |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.name`` | The name of the current function or symbol. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.name-with-args`` | The name of the current function with arguments and values or the symbol name. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.name-without-args`` | The name of the current function without arguments and values (used to include a function name in-line in the ``disassembly-format``) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.mangled-name`` | The mangled name of the current function or symbol. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.pc-offset`` | The program counter offset within the current function or symbol |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.addr-offset`` | The offset in bytes of the current function, formatted as " + dddd" |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.concrete-only-addr-offset-no-padding`` | Similar to ``function.addr-offset`` except that there are no spaces in the output (e.g. "+dddd") and the offset is computed from the nearest concrete function -- inlined functions are not included |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.changed`` | Will evaluate to true when the line being formatted is a different symbol context from the previous line (may be used in ``disassembly-format`` to print the new function name on a line by itself at the start of a new function). Inlined functions are not considered for this variable |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``function.initial-function`` | Will evaluate to true if this is the start of the first function, as opposed to a change of functions (may be used in ``disassembly-format`` to print the function name for the first function being disassembled) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``line.file.basename`` | The line table entry basename to the file for the current line entry in the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``line.file.fullpath`` | The line table entry fullpath to the file for the current line entry in the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``line.number`` | The line table entry line number for the current line entry in the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``line.start-addr`` | The line table entry start address for the current line entry in the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``line.end-addr`` | The line table entry end address for the current line entry in the current frame. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``module.file.basename`` | The basename of the current module (shared library or executable) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``module.file.fullpath`` | The basename of the current module (shared library or executable) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``process.file.basename`` | The basename of the file for the process |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``process.file.fullpath`` | The fullname of the file for the process |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``process.id`` | The process ID native to the system on which the inferior runs. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``process.name`` | The name of the process at runtime |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.id`` | The thread identifier for the current thread |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.index`` | The unique one based thread index ID which is guaranteed to be unique as threads come and go. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.name`` | The name of the thread if the target OS supports naming threads |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.queue`` | The queue name of the thread if the target OS supports dispatch queues |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.stop-reason`` | A textual reason why the thread stopped. If the thread have a recognized frame, this displays its recognized stop reason. Otherwise, gets the stop info description. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.stop-reason-raw`` | A textual reason why the thread stopped. Always returns stop info description. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.return-value`` | The return value of the latest step operation (currently only for step-out.) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``thread.completed-expression`` | The expression result for a thread that just finished an interrupted expression evaluation. |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``target.arch`` | The architecture of the current target |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``script.target:python_func`` | Use a Python function to generate a piece of textual output |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``script.process:python_func`` | Use a Python function to generate a piece of textual output |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``script.thread:python_func`` | Use a Python function to generate a piece of textual output |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``script.frame:python_func`` | Use a Python function to generate a piece of textual output |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``current-pc-arrow`` | Prints either ``->`` or `` `` if the current pc value is matched (used in ``disassembly-format``) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
| ``addr-file-or-load`` | Formats an address either as a load address, or if process has not yet been launched, as a load address (used in ``disassembly-format``) |
|
|
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
|
|
Control Characters
|
|
------------------
|
|
|
|
Control characters include ``{``, ``}``, and ``\``.
|
|
|
|
The ``{`` and ``}`` are used for scoping blocks, and the ``\`` character allows
|
|
you to desensitize control characters and also emit non-printable characters.
|
|
|
|
Desensitizing Characters in the Format String
|
|
---------------------------------------------
|
|
|
|
The backslash control character allows your to enter the typical ``\a``,
|
|
``\b``, ``\f``, ``\n``, ``\r``, ``\t``, ``\v``, ``\\``, characters and along
|
|
with the standard octal representation ``\0123`` and hex ``\xAB`` characters.
|
|
This allows you to enter escape characters into your format strings and will
|
|
allow colorized output for terminals that support color.
|
|
|
|
Scoping
|
|
-------
|
|
|
|
Many times the information that you might have in your prompt might not be
|
|
available and you won``t want it to print out if it isn``t valid. To take care
|
|
of this you can enclose everything that must resolve into a scope. A scope is
|
|
starts with ``{`` and ends with ``}``. For example in order to only display the
|
|
current frame line table entry basename and line number when the information is
|
|
available for the current frame:
|
|
|
|
::
|
|
|
|
"{ at {$line.file.basename}:${line.number}}"
|
|
|
|
|
|
Broken down this is:
|
|
|
|
- The start the scope: ``{`` ,
|
|
- format whose content will only be displayed if all information is available: ``at {$line.file.basename}:${line.number}``
|
|
- end the scope: ``}``
|
|
|
|
Making the Frame Format
|
|
-----------------------
|
|
|
|
The information that we see when stopped in a frame:
|
|
|
|
::
|
|
|
|
frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19
|
|
|
|
can be displayed with the following format:
|
|
|
|
::
|
|
|
|
"frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n"
|
|
|
|
This breaks down to:
|
|
|
|
- Always print the frame index and frame PC: ``frame #${frame.index}: ${frame.pc}``,
|
|
- only print the module followed by a tick if there is a valid module for the current frame: ``{ ${module.file.basename}`}``,
|
|
- print the function name with optional offset: ``{${function.name}{${function.pc-offset}}}``,
|
|
- print the line info if it is available: ``{ at ${line.file.basename}:${line.number}}``,
|
|
- then finish off with a newline: ``\n``.
|
|
|
|
Making Your own Formats
|
|
-----------------------
|
|
|
|
When modifying your own format strings, it is useful to start with the default
|
|
values for the frame and thread format strings. These can be accessed with the
|
|
``settings show`` command:
|
|
|
|
::
|
|
|
|
(lldb) settings show thread-format
|
|
thread-format (format-string) = "thread #${thread.index}: tid = ${thread.id%tid}{, ${frame.pc}}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${line.file.basename}:${line.number}}{, name = '${thread.name}'}{, queue = '${thread.queue}'}{, activity = '${thread.info.activity.name}'}{, ${thread.info.trace_messages} messages}{, stop reason = ${thread.stop-reason}}{\nReturn value: ${thread.return-value}}{\nCompleted expression: ${thread.completed-expression}}\n"
|
|
(lldb) settings show frame-format
|
|
frame-format (format-string) = "frame #${frame.index}:{ ${frame.no-debug}${frame.pc}}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${line.file.basename}:${line.number}}{${function.is-optimized} [opt]}\n"
|
|
|
|
When making thread formats, you will need surround any of the information that
|
|
comes from a stack frame with scopes ({ frame-content }) as the thread format
|
|
doesn't always want to show frame information. When displaying the backtrace
|
|
for a thread, we don't need to duplicate the information for frame zero in the
|
|
thread information:
|
|
|
|
::
|
|
|
|
(lldb) thread backtrace
|
|
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 2.1
|
|
frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19
|
|
frame #1: 0x0000000100000e40 a.out`start + 52
|
|
|
|
The frame related variables are:
|
|
|
|
- ``${file.*}``
|
|
- ``${frame.*}``
|
|
- ``${function.*}``
|
|
- ``${line.*}``
|
|
- ``${module.*}``
|
|
|
|
|
|
Looking at the default format for the thread, and underlining the frame
|
|
information:
|
|
|
|
::
|
|
|
|
thread #${thread.index}: tid = ${thread.id}{, ${frame.pc}}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n
|
|
|
|
|
|
We can see that all frame information is contained in scopes so that when the
|
|
thread information is displayed in a context where we only want to show thread
|
|
information, we can do so.
|
|
|
|
For both thread and frame formats, you can use ${script.target:python_func},
|
|
${script.process:python_func} and ${script.thread:python_func} (and of course
|
|
${script.frame:python_func} for frame formats) In all cases, the signature of
|
|
python_func is expected to be:
|
|
|
|
::
|
|
|
|
def python_func(object,unused):
|
|
...
|
|
return string
|
|
|
|
Where object is an instance of the SB class associated to the keyword you are
|
|
using.
|
|
|
|
e.g. Assuming your function looks like:
|
|
|
|
::
|
|
|
|
def thread_printer_func (thread,unused):
|
|
return "Thread %s has %d frames\n" % (thread.name, thread.num_frames)
|
|
|
|
And you set it up with:
|
|
|
|
::
|
|
|
|
(lldb) settings set thread-format "${script.thread:thread_printer_func}"
|
|
|
|
you would see output like:
|
|
|
|
::
|
|
|
|
* Thread main has 21 frames
|
|
|