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