使用断点

当执行代码时,断点会停止执行。如需创建断点,请使用 break 命令并为其指定中断位置。

例如,如需在 main 函数上创建断点,请执行以下操作:

break main
Breakpoint 3 (Software) on Global, Enabled, stop=All, @ main
   180
 ◉ 181 int main(int argc, char**argv) {
   182     fbl::unique_fd dirfd;

您可以通过多种方式在 zxdb 中表达断点。例如:

函数名称

您可以指定与任何命名空间中的函数名称匹配的函数名称:

break main

成员函数

您可以在特定命名空间或类中指定一个或多个成员函数:

break my_namespace::MyClass::MyFunction
[zxdb] break ::OtherFunction

来源和线条

您还可以指定要中断的源文件和行号:

break mymain.cc:22

行号

您可以指定当前帧的当前源文件中的行号。在逐步执行代码时,此功能非常有用:

break 23

内存地址

您可以指定内存地址:

break 0xf72419a01

表达式

您可以指定一个表达式,如需详细了解 zxdb 中的表达式,请参阅评估表达式。以 * 为前缀会将后面的输入视为可评估为特定地址的表达式。当您使用硬件断点时,此功能非常有用。

break --type=write *&foo

列出断点

如需查看所有断点,请使用 breakpoint

breakpoint
  # scope  stop enabled type     #addrs hit-count location
▶ 3 global all  false   software      1         0 machine.h:7

移除断点

如需移除特定断点,请将相应断点索引作为 breakpoint <index> rm 的上下文提供。

例如,如需清除 breakpoint 3,请运行以下命令:

breakpoint 3 rm
Removed Breakpoint 3 enabled=false @ machine.h:7

清除断点

如需移除特定位置的所有断点,您无需指定索引:

clear

当您创建或停止在断点处时,该断点会自动成为默认断点。每当您在未指定特定索引的情况下运行 clear 时,该命令都会清除您命中的最新断点。

clear 还可以像 break 命令一样采用可选的位置。这样一来,它会尝试清除该位置的所有断点,并忽略默认的断点上下文。

停用断点

例如,如需停用断点 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 };

如需停用当前断点,请执行以下操作:

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),

启用断点

停用断点后,您可能需要重新启用已停用的断点。

例如,如需启用断点 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 };

设置和获取断点属性

您还可以使用 getset 命令修改断点属性。

例如,如需从断点 4 中检索 location 属性,请执行以下操作:

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

例如,如需将 location 属性从断点 4 设置为 machine.h:8,请执行以下操作:

breakpoint 4 set location = machine.h:8
Set breakpoint 4 location = machine.h:8

条件断点

您还可以配置带条件的断点。条件是计算结果为 truefalse 的表达式。设置条件后,除非该条件为 true,否则断点不会触发停止。

例如,如果您要调试 cobalt.cm 组件:

例如,如需添加条件断点位置 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.";

硬件数据断点

在 zxdb 中,硬件断点作为一种断点公开,而不是作为单独的监视点

处理器可以设置为在读取或写入特定地址时中断执行。这有助于跟踪内存损坏。

当您为 break 命令的 type 属性使用以下任一值时,可以创建硬件断点。

  • execute
  • write
  • read-write

例如,如需设置类型为 execute 的断点,请执行以下操作:

break --type=execute myfile.rs:123

watch 与使用 break --type=read-write 相同。请参阅 watch 命令

watch 命令

作为一种快捷方式,watch 命令会获取变量的内容或表达式的结果,并在其范围内设置数据写入断点:

watch i
[zxdb] watch foo[5]->bar

如果您在堆栈上 watch 了一个变量,但没有人触及它,那么当堆栈内存被重新使用时,您通常会在程序的另一部分看到它。如果您意外命中了断点,请检查执行是否仍在您预期的帧中。

程序化断点

在某些情况下,您可能希望捕获代码中的特定条件。为此,您可以在代码中插入硬编码的断点。

Clang 具有内置的:

__builtin_debugtrap();

如果 zxdb 已附加到进程,它将停止,就像命中了普通断点一样。然后,您可以从此处stepcontinue。如果调试器尚未附加,这会导致崩溃。