| # Repeat Commands |
| |
| In LLDB's command line interface, pressing Enter (an empty command) repeats the |
| previous command. By default, the exact same command is re-executed. However, |
| several commands customize this behavior to implement paging or progressive |
| expansion, making it easy to explore data incrementally by pressing Enter |
| repeatedly. Repeat commands can be learned and discovered by pressing enter and |
| observing the result. |
| |
| In some instances, commands disable repeat commands, to prevent |
| accidentally triggering a destructive operation (e.g. `process launch`). |
| |
| This page documents the commands with custom repeat behavior. |
| |
| ## `thread backtrace` (`bt`) |
| |
| When `thread backtrace` is invoked with the `--count` (`-c`) option, the |
| repeat command pages through the backtrace by advancing the `--start` (`-s`) |
| option by the count each time. |
| |
| For example: |
| |
| ``` |
| (lldb) bt 5 |
| * thread #1, stop reason = breakpoint 1.1 |
| * frame #0: handle_request at server.cpp:50 |
| frame #1: parse_headers at http.cpp:12 |
| frame #2: read_socket at socket.cpp:30 |
| frame #3: accept_connection at listener.cpp:8 |
| frame #4: event_loop at reactor.cpp:100 |
| (lldb) |
| # repeats as: thread backtrace -c 5 -s 5 |
| * thread #1, stop reason = breakpoint 1.1 |
| frame #5: start_server at main.cpp:42 |
| frame #6: load_config at config.cpp:7 |
| ... |
| (lldb) |
| # repeats as: thread backtrace -c 5 -s 10 |
| ``` |
| |
| Each press of Enter shows the next 5 frames. If `--count` is not specified, |
| the full backtrace is displayed and there is no repeat command. |
| |
| ## `source list` (`list`) |
| |
| When `source list` is repeated, it shows the next block of source lines, |
| continuing from where the previous listing ended. This mimics paging behavior. |
| |
| If the `--reverse` (`-r`) option was given, the repeat command continues |
| listing in reverse (showing earlier source lines). |
| |
| ``` |
| (lldb) list # shows source around the current location |
| (lldb) # shows the next block of source lines |
| (lldb) # shows the next block after that |
| |
| (lldb) list -r # shows source in reverse |
| (lldb) # continues listing in reverse |
| ``` |
| |
| ## `memory read` |
| |
| When `memory read` is repeated, it continues reading from where the previous |
| read ended. The repeat command drops the address arguments and re-uses the same |
| format, size, and count options from the previous invocation. |
| |
| ``` |
| (lldb) memory read 0x1000 -c 32 |
| 0x1000: 48 8b 05 a9 3b 00 00 48 ... |
| (lldb) # continues reading the next 32 bytes from 0x1020 |
| (lldb) # continues reading from 0x1040 |
| ``` |
| |
| ## `memory region` |
| |
| When `memory region` is given an address, it displays the memory region |
| containing that address. Pressing Enter then shows the next memory region, and |
| so on, allowing you to walk through the process's entire memory map. |
| |
| ``` |
| (lldb) memory region 0x1000 |
| [0x0000-0x2000) rw- |
| (lldb) # shows the next region starting at 0x2000 |
| (lldb) # shows the next region after that |
| ``` |
| |
| ## `frame variable` (`v`) |
| |
| When `frame variable` is repeated, it re-runs the command with an incremented |
| `--depth` (`-D`) value. This progressively reveals deeper levels of nested |
| data structures with each press of Enter. |
| |
| If no `--depth` option was specified in the original command, the next repeat |
| starts at one level beyond the `target.max-children-depth` default setting. If |
| `--depth` was specified, it increments the given value by 1 each time. |
| |
| Consider a deeply nested configuration structure: |
| |
| ``` |
| (lldb) v config |
| (Config) config = { |
| server = { |
| network = { |
| tls = { |
| certificate = { |
| issuer = {...} |
| } |
| } |
| } |
| } |
| } |
| (lldb) # repeats as: frame variable --depth 6 config |
| (Config) config = { |
| server = { |
| network = { |
| tls = { |
| certificate = { |
| issuer = { |
| name = {...} |
| } |
| } |
| } |
| } |
| } |
| } |
| (lldb) # repeats as: frame variable --depth 7 config |
| ``` |
| |
| The default `target.max-children-depth` causes the first output to truncate at |
| `issuer`. Each press of Enter reveals one more level without having to |
| manually specify `--depth`. |
| |
| ## `thread trace dump instructions` |
| |
| When repeated, this command adds the `--continue` flag, which continues |
| dumping traced instructions from where the previous instruction dump left off. |
| |
| ``` |
| (lldb) thread trace dump instructions |
| ... first batch of instructions ... |
| (lldb) # continues dumping the next 20 instructions |
| ``` |