Use breakpoints

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.