When you use zxdb, you can control the execution of threads to help you debug. As you debug you can control execution through the use of the following:
Thread
A thread is a unit of execution within a process. It represents a single sequence of instructions that can be executed independently.
To control execution through threads in zxdb, see Threads.
Stack frame
A stack frame is a section of the call stack that is allocated when a function is called. It stores information needed for the function's execution, such as:
To control execution through stack frames in zxdb, see Stack Frames.
In zxdb, a thread
is a noun that you can use with zxdb verbs.
To list the threads in the current process:
Note: This is the thread
noun. You can also use t
to express thread
.
thread # State Koid Name ▶ 1 Blocked 1323 initial-thread 2 Running 3462 worker-thread
In some cases, you may notice that a thread is marked as Blocked
which means that the thread is stopped on a system call. Typically, when you are debugging an asynchronous application this may also indicate a wait time.
Thread control commands only work on a suspended thread, not blocked or running threads. There are several ways to suspend a thread:
pause
command.pause
a threadFor example, to suspend thread 2
with the pause
command:
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 zxdb shows the current source code location. If a thread is in a system call, like the example above, the source code location resolves to the location in the assembly-language macro file that generated the system call.
If you run pause
without any additional context, zxdb pauses all threads of all processes that are currently attached.
For example:
pause 508 const zx_port_packet_t* packet)) 509 ▶ 510 BLOCKING_SYSCALL(port_wait, zx_status_t, /* no attributes */, 3, (handle, deadline, packet), 511 (_ZX_SYSCALL_ANNO(use_handle("Fuchsia")) zx_handle_t handle, zx_time_t deadline, 512 zx_port_packet_t* packet)) 🛑 $elf(SYSCALL_zx_port_wait) + 0x7 • syscalls.inc:510
continue
a threadAfter you have paused a thread and started debugging an issue, you may want to continue
the thread. Continuing means resuming execution until your program completes normally.
For example, to continue
thread 1
:
thread 1 continue
If you run continue
without any additional context, zxdb continues all the threads of all attached processes.
For example:
continue
When a thread is paused you can control its execution. You can use any of these commands:
Note: For more information on pausing a thread, see pause
a thread.
finish
(fi
)
Exits the function and stops right after the call.
finish
next
(n
)
Advances to the next line, stepping over function calls.
next
nexti
Advances to the next instruction, but steps over call instructions for the target architecture.
Note: In this context, a call instruction is call
on x64 and bl
on arm64. This does not work for all cases. For example, a manually set up call frame and a jump
may result stepping into a new stack frame.
nexti
ss
List function calls on the current line and step in to the call selected. This automatically completes any of the other calls that happen to occur first.
ss 1 std::string::string 2 MyClass::MyClass 3 HelperFunctionCall 4 MyClass::~MyClass 5 std::string::~string quit >
step
(s
)
Advances to the next code line. If a function call happens before the next line, that function is stepped into and execution stops at the beginning of that function.
You can also supply an argument substring to match a specific function call. Function names that do not contain the argument substring are skipped and only matching functions are stepped into.
step [zxdb] step MyFunction
stepi
Advances exactly one machine instruction.
stepi
until
(u
)
Given a line location, continues the thread until execution gets there. For example, to run until line 45
of the current file:
until 45
You can also run until execution gets back to a given stack frame:
frame 2 until
A stack frame is a function call. When a function calls another function, a new frame is created. Listing the frames of a thread returns the call stack.
Note: You can only see the stack frames when a thread is suspended. See pause
a specific thread.
To list the stack frames in the current thread:
Note: This is the frame
noun. You can also use f
to express frame
.
frame ▶ 0 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:203 1 fxl::CommandLineFromArgcArgv() • command_line.h:224 2 main() • main.cc:174
When you work with stack frames, 0
indicates the top of the stack, which indicates the end of the execution. The bottom of the stack, which is the highest stack frame number, indicates the start of the execution.
You can use the up
and down
commands to navigate the frame list.
For example, use up
to navigate from the current frame 0
to frame 1
:
up 1 fxl::CommandLineFromIterators<const char *const *>() • command_line.h:204
For example, use down
to navigate from the current frame 1
to frame 0
:
[zxdb] down 0 fxl::CommandLineFromIteratorsFindFirstPositionalArg<const char *const *>() • command_line.h:185
You can also navigate to a specific frame by using the frame
command with a frame number:
frame 1
backtrace
for additional detailsIn some cases, you may want to see additional address information that stack frames don't provide. The backtrace
command is identical to frame
but gives you more detailed address information as well as function parameters.
Note: This is the backtrace
verb. You can also use bt
to express backtrace
.
To list the stack frames in the current thread, but with more detailed information, use backtrace
:
backtrace ▶ 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. > ...
list
to look at source codeEach stack frame has a code location. Use the list
command to look at the source code.
You can list code around the instruction pointer of specific stack frames.
For example, to list
the source code around the instruction pointer of stack frame 3
:
frame 3 list
When you use list
without context, zxdb lists the source code around the instruction pointer of the current stack frame:
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;
list
Additionally, you can use list
to list specific things:
{Functions}
Use list
to list functions:
list MyClass::MyFunc
{Files}
Use list
to list specific files:
list --all myfile.cc:1
{File with line numbers}
Use list
to list specific files with specific line numbers:
list foo.cc:43