| # 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: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| break main |
| ``` |
| |
| * {Member function} |
| |
| You can specify a member function or functions inside a specific namespace |
| or class: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| break {{"<var>my_namespace</var>"}}::{{"<var>MyClass</var>"}}::{{"<var>MyFunction</var>"}} |
| [zxdb] break ::{{"<var>OtherFunction</var>"}} |
| ``` |
| |
| * {Source and line} |
| |
| You can also specify a source file and the line number to break on: |
| |
| Note: Make sure to separate the source file name and line number with a colon. |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| break 23 |
| ``` |
| |
| * {Memory address} |
| |
| You can specify a memory address: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| break 0xf72419a01 |
| ``` |
| |
| * {Expression} |
| |
| You can specify an expression, see [Evaluate expressions][zxdb-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. |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| break --type=write *&foo |
| ``` |
| |
| ## List breakpoints |
| |
| To view all of the breakpoints, use `breakpoint`: |
| |
| Note: This is the `breakpoint` noun. You can also use `bp` to express |
| `breakpoint`. |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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`: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| breakpoint 3 rm |
| Removed Breakpoint 3 enabled=false @ machine.h:7 |
| ``` |
| |
| Key Point: **GDB users:** `delete <index>` is mapped to `breakpoint <index> rm`. |
| |
| ## Clear breakpoints |
| |
| To remove all breakpoints at a particular location, you do not need to specify |
| an index: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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. |
| |
| Key Point: **GDB users:** `clear <number>` behaves the same in GDB and zxdb. |
| |
| ## Disable a breakpoint |
| |
| For example, to disable breakpoint `3`: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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 }; |
| ``` |
| |
| Note: If you do not provide a breakpoint index, the last breakpoint that you hit |
| is used. |
| |
| To disable the current breakpoint: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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`: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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`: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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`: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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`: |
| |
| ```none {:.devsite-disable-click-to-copy} |
| [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 `execute`: |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| break --type=execute myfile.rs:123 |
| ``` |
| |
| A `watch` is the same as using `break --type=read-write`. See |
| [`watch` command](#watch-command). |
| |
| ### `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: |
| |
| Note: CPUs only support a limited number of hardware watchpoints, typically |
| around 4. |
| |
| ```none {: .devsite-terminal data-terminal-prefix="[zxdb]" } |
| 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. |
| |
| Key Point: **GDB Users**: `watch` evaluates the expression once and then sets a |
| breakpoint on the result. It won't re-evaluate the expression. In the above |
| example, it triggers when `bar` changes but not if `foo[5]` changes to point |
| to a different `bar`. |
| |
| ## 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. |
| |
| Note: This does not work in GCC Zircon builds. |
| |
| Clang has a built-in: |
| |
| ```cpp |
| __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. |
| |
| [zxdb-expressions]: /docs/development/debugger/exceptions.md |