To list the current process’ threads (see “Interaction model” above for more):
[zxdb] thread # State Koid Name ▶ 1 Blocked 1323 initial-thread 2 Running 3462 worker-thread
Often when you attach to a process the thread will be “blocked”, meaning it is stopped on a system call. For asynchronous programs this will typically be some kind of wait.
Most thread control and introspection commands only work when a thread is suspended (not blocked or running). A thread will be suspended when it is stopped at a breakpoint or crashes. You can explicitly suspend a thread with the pause
command:
[zxdb] thread 2 pause 🛑 syscalls-x86-64.S:67 65 m_syscall zx_port_create 60 2 1 66 m_syscall zx_port_queue 61 2 1 ▶ 67 m_syscall zx_port_wait 62 3 0 68 m_syscall zx_port_cancel 63 3 1 69 m_syscall zx_timer_create 64 3 1
When a thread is paused the debugger will show the current source code location. Often threads will be in a system call that will resolve to the location in the assembly-language macro file that generated the system call as shown in the above example.
Running pause
by itself with no context will pause all threads of all processes currently attached:
[zxdb] pause
Unpause a thread with continue
. As before, continue
with no context will resume all threads:
[zxdb] continue
Or continue a specific thread:
[zxdb] thread 1 continue
A stack frame is a function call. When a function calls another function, a new nested frame is created. So listing the frames of a thread tells you the call stack. You can only see the stack frames when a thread is suspended (see “Working with threads” above).
To list the current thread’s stack frames (the f
abbreviation will also work).
[zxdb] frame ▶ 0 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:203 1 fxl::CommandLineFromArgcArgv() • command_line.h:224 2 main() • main.cc:174
And to select a given frame as the default:
[zxdb] frame 2
Frames are numbered with “0” being the top of the stack. Increasing numbers go backwards in time.
You can use the up
and down
commands to navigate the frame list:
[zxdb] up 1 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:204 [zxdb] down 0 fxl::CommandLineFromIteratorsFindFirstPositionalArg<const char *const *>() • command_line.h:185
For more context, you can use the backtrace
command. This is identical to frame
but gives more detailed address information as well as function parameters. This command can be abbreviated bt
:
[zxdb] bt ▶ 0 fxl::CommandLineFromIteratorsFindFirstPositionalArg<const char *const *>() • command_line.h:185 IP = 0x10f982cf2ad0, BP = 0x66b45a01af50, SP = 0x66b45a01af38 first = (const char* const*) 0x59f4e1268dc0 last = (const char* const*) 0x59f4e1268dc8 first_positional_arg = (const char* const**) 0x0 1 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:204 IP = 0x10f982cf2ac0, BP = 0x66b45a01af50, SP = 0x66b45a01af40 first = <'first' is not available at this address. > last = <'last' is not available at this address. > ...
Each stack frame has a code location. Use the list
command to look at source code. By itself, it lists the source code around the current stack frame’s instruction pointer:
[zxdb] list 183 inline CommandLine CommandLineFromIteratorsFindFirstPositionalArg( 184 InputIterator first, InputIterator last, ▶ 185 InputIterator* first_positional_arg) { 186 if (first_positional_arg) 187 *first_positional_arg = last;
You can list code around the current instruction pointer of other stack frames, too:
[zxdb] frame 3 list
Or you can list specific things like functions:
[zxdb] list MyClass::MyFunc
File/line numbers:
[zxdb] list foo.cc:43
Or whole files:
[zxdb] list --all myfile.cc:1
When a thread is suspended (see “Threads” above) you can control its execution:
next
/ n
: Advances to the next line, stepping over function calls.
[zxdb] n
step
/ s
: Advances to the next line. If a function call happens before the next line, that function will be stepped into and execution will stop at the beginning of it. You can also supply an argument, which is a substring to match of a specific function call. Function names not containing this substring will be skipped and only matching ones will be stepped into:
[zxdb] s [zxdb] s MyFunction
ss
: List function calls on the current line and step in to the call selected, automatically completing any of the other calls that happen to occur first.
[zxdb] ss 1 std::string::string 2 MyClass::MyClass 3 HelperFunctionCall 4 MyClass::~MyClass 5 std::string::~string quit >
finish
/ fi
: Exits the function and stops right after the call.
[zxdb] finish
until
/ u
: Given a location (the same as breakpoints, see above), continues the thread until execution gets there. For example, to run until line 45 of the current file:
[zxdb] u 45
jump
: Move the instruction pointer to a new address.
[zxdb] jump 22 // Line number [zxdb] jump 0x87534123 // Address
To run until execution gets back to a given stack frame:
[zxdb] frame 2 until