Breakpoints stop execution when code is executed. To create a breakpoint, use
the break
command and give it a location to break.
For example, to create a breakpoint on the main
function:
break main
Breakpoint 3 (Software) on Global, Enabled, stop=All, @ main
180
◉ 181 int main(int argc, char**argv) {
182 fbl::unique_fd dirfd;
There are several ways to express a breakpoint in zxdb. For example:
Function name
You can specific a function name which matches functions with the name in any namespace:
break main
Member function
You can specify a member function or functions inside a specific namespace or class:
break my_namespace::MyClass::MyFunction
[zxdb] break ::OtherFunction
Source and line
You can also specify a source file and the line number to break on:
break mymain.cc:22
Line number
You can specify a line number within the current frame’s current source file. This is useful when you are stepping through code:
break 23
Memory address
You can specify a memory address:
break 0xf72419a01
Expression
You can specify an expression, see Evaluate expressions
for more information on expressions in zxdb. Prefixing with *
treats the
input that follows as an expression that evaluates to a specific address.
This is useful when you work with hardware breakpoints.
break --type=write *&foo
List breakpoints
To view all of the breakpoints, use breakpoint
:
breakpoint
# scope stop enabled type #addrs hit-count location
▶ 3 global all false software 1 0 machine.h:7
Remove a breakpoint
To remove a specific breakpoint, give that breakpoint index as the context for
the breakpoint <index> rm
.
For example, to clear breakpoint 3
:
breakpoint 3 rm
Removed Breakpoint 3 enabled=false @ machine.h:7
Clear breakpoints
To remove all breakpoints at a particular location, you do not need to specify an index:
clear
When you create or stop on a breakpoint, that breakpoint becomes the default
automatically. Whenever you run clear
without a specific index, the command
clears the latest breakpoint that you hit.
clear
can also take an optional location just like a break
command. In this
way, it will try to clear all breakpoints at that location and ignore the
default breakpoint context.
Disable a breakpoint
For example, to disable breakpoint 3
:
breakpoint 3 disable
Disabled Breakpoint 3 enabled=false @ machine.h:7
35 static constexpr SizeType InitialStackPointer(SizeType base, SizeType size) {
36 // Stacks grow down on most machines.
◯ 37 return (base + size) & -kStackAlignment<SizeType>;
38 }
39 };
To disable the current breakpoint:
disable
Disabled Breakpoint 2 enabled=false @ main.rs:5
24
25 enum Services {
◯ 26 ComponentRunner(frunner::ComponentRunnerRequestStream),
27 StarnixManager(fstarnixrunner::ManagerRequestStream),
28 AttributionProvider(fattribution::ProviderRequestStream),
Enable a breakpoint
After you have disabled a breakpoint, you may want to re-enable the disabled breakpoint.
For example, to enable breakpoint 3
:
breakpoint 3 enable
Enabled Breakpoint 3 @ machine.h:7
35 static constexpr SizeType InitialStackPointer(SizeType base, SizeType size) {
36 // Stacks grow down on most machines.
◉ 37 return (base + size) & -kStackAlignment<SizeType>;
38 }
39 };
Set and get breakpoint properties
You can also modify breakpoint properties with the get
and set
commands.
For example, to retrieve the location
property from breakpoint 4
:
breakpoint 4 get location
location (locations)
The location (symbol, line number, address, or expression) where this
breakpoint will be set. See "help break" for documentation on how to specify.
location = machine.h:7
For example, to set the location
property from breakpoint 4
to machine.h:8
:
breakpoint 4 set location = machine.h:8
Set breakpoint 4 location = machine.h:8
Conditional breakpoints
You can also configure a breakpoint to have conditionals. A conditional is an
expression that evaluates to either true
or false
. When you set a
conditional, the breakpoint does not trigger a stop unless the this conditional
is true
.
For example, if you are debugging the cobalt.cm
component:
For example, to add a conditional breakpoint location of main.cc:352
:
[zxdb] b main.cc:352 if command_line.has_argv0 == false
Created Breakpoint 1 condition="command_line.has_argv0 == false" @ ../../src/myapp/bin/app/main.cc:352
351 }
◉ 352 inspector.Health().Ok();
353 loop.Run();
354 FX_LOGS(INFO) << "Cobalt will now shut down.";
Hardware data breakpoints
In zxdb, hardware breakpoints are exposed as a type of breakpoint rather than as a separate watchpoint.
The processor can be set to break execution when it reads or writes certain addresses. This can be useful to track down memory corruption.
You can create a hardware breakpoint when you use any of the following values
for the type
property of a break
command.
execute
write
read-write
For example, to set a breakpoint of type execution
:
break --type=execution myfile.rs:123
A watch
is the same as using break --type=read-write
. See
watch
command.
watch
command
As a shortcut, the watch
command takes the contents of a variable or the
result of an expression and set a data write breakpoint over its range:
watch i
[zxdb] watch foo[5]->bar
If you watch
a variable on the stack and nobody touches it, you will often
see it hit in another part of the program when the stack memory is re-used.
If you get a surprising breakpoint hit, check that execution is still in the
frame you expect.
Programmatic breakpoints
In some cases you may want to catch a specific condition in your code. To do this you can insert a hard coded breakpoint in your code.
Clang has a built-in:
__builtin_debugtrap();
If zxdb is already attached to the process, it will stop as if a normal
breakpoint was hit. You can then step
or continue
from there. If the
debugger is not already attached, this will cause a crash.