Zxdb 提供脚本支持,可让您自动执行重复的调试任务、跳转到特定应用状态,并以自动方式验证调试器行为。脚本是纯文本文件,其中包含一系列 zxdb 命令及其预期输出。
运行脚本
如需在启动 zxdb 时从命令行运行脚本,请使用 -S 或 --script-file 选项。
- 使用
ffx debug:
ffx debug connect -- --script-file=my_script.script- 或者直接使用
zxdb(请注意,这仅适用于离线核心文件,例如 minidump,因此您的脚本应首先使用opendump命令加载核心文件。如需了解详情,请参阅help opendump):
zxdb --script-file=my_script.script脚本语法
脚本按行进行评估,通常会在输入命令和匹配输出行之间交替进行。
命令
以 [zxdb] 开头的行会被解读为要运行的命令。这些命令的执行方式与在交互式 zxdb 控制台中相同。
[zxdb] attach my_component.cm
您可以使用缩写和任何标准 zxdb 功能:
[zxdb] t * f
这相当于:
[zxdb] thread * frame
输出匹配
如果某行不是以 [zxdb] 开头,也不是注释,则会被视为与之前执行的命令的输出进行匹配的模式。
由于 zxdb 中的许多命令都是异步的,因此调试器需要知道命令何时实际完成输出,然后才能发出下一个命令。Zxdb 会等待输出与指定的行匹配,然后再继续执行下一个命令。这可确保您的脚本与调试器的异步事件保持同步。
[zxdb] attach cobalt.cm
Attached Process
Done.
如果您不关心命令的输出,则无需指定任何匹配行。您可以编写下一个 [zxdb] 命令,系统会允许上一个命令立即完成。
如果命令有任何依赖项,则可能会导致结果不稳定。例如:
[zxdb] b $main
Created Breakpoint 1 @ $main
[zxdb] run-component fuchsia-pkg://fuchsia.com/zxdb_e2e_inferiors#meta/async_rust_multithreaded.cm
Launched Process 1 state=Running koid=?? name=async_rust_multithreaded.cm component=async_rust_multithreaded.cm
🛑
[zxdb] until foo
# This might lead to flaky results
[zxdb] thread
thread 的结果可能是
▶ 7 #[fasync::run(2)]
8 async fn main() {
9 let _task_a = fasync::Task::spawn(async {});
🛑 on bp 1 async_rust_multithreaded::main() • async_rust_multithreaded.rs:7
[zxdb] until foo
[zxdb] thread
# state koid name
▶ 1 Blocked (Futex) 24769196 initial-thread
2 Blocked (Port) 24769684 executor_worker
3 Blocked (Port) 24769691 executor_worker
19 }
20
▶ 21 async fn foo(i: u64) {
22 fasync::Timer::new(std::time::Duration::from_secs(i)).await;
23 }
或
▶ 7 #[fasync::run(2)]
8 async fn main() {
9 let _task_a = fasync::Task::spawn(async {});
🛑 on bp 1 async_rust_multithreaded::main() • async_rust_multithreaded.rs:7
[zxdb] until foo
19 }
20
▶ 21 async fn foo(i: u64) {
22 fasync::Timer::new(std::time::Duration::from_secs(i)).await;
23 }
🛑 thread 2 async_rust_multithreaded::foo(u64) • async_rust_multithreaded.rs:21
[zxdb] thread
# state koid name
1 Suspended 24775467 initial-thread
▶ 2 Blocked (Exception) 24775973 executor_worker
3 Suspended 24775980 executor_worker
您可以手动快速输入命令或使用脚本运行程序来重现此结果。
这是因为 until 和 thread 命令是同时运行的。
为避免不稳定,建议使用暂停符号 (🛑) 作为预期输出。例如:
[zxdb] until foo
🛑
[zxdb] thread
通配符
如果您只想匹配行的部分内容,或者某行包含不可预测的数据(例如内存地址、进程 ID 或文件路径),则可以使用 ?? 通配符。它与行的任意部分(最多为整行)匹配。
[zxdb] frame
▶ 0 MyFunction() • my_file.cc:??
评论
以 # 开头的行是注释,会被忽略。注释对于记录脚本非常有用,但请注意,系统也支持 UTF-8 字符。
# This is a comment explaining what the next command does.
[zxdb] pause
# Wait for the stop event
🛑
无序输出
默认情况下,脚本会期望输出行以指定的精确顺序到达。如果命令生成的输出无法保证顺序,您可以在预期输出块中的任意位置添加 ## allow-out-of-order-output。这可确保所有指定的行都匹配,无论它们以何种顺序打印。此指令必须紧跟在 zxdb 命令行之后,并且在要匹配的任何预期输出之前,以便匹配算法正确考虑所有输出。
[zxdb] thread
## allow-out-of-order-output
1 State: Running
2 State: Suspended
退出脚本
脚本完成后,您将自动进入交互式 [zxdb] 命令行。
如果您希望 zxdb 在脚本结束时自动退出,则可以在文件末尾添加 quit 命令。但是,请确保之前的命令已指定匹配的输出,否则 quit 可能会在之前的命令完成之前执行。
[zxdb] quit --force
示例
捕获异步回溯
此脚本会附加到组件、暂停组件、打印异步回溯,并让您进入交互式控制台以进行进一步调查。
# Attach to the component
[zxdb] attach hwinfo.cm
Attached Process
Done.
# Pause execution
[zxdb] pause
🛑
# Output the tree of async tasks.
[zxdb] async-backtrace
打印所有线程的帧
此脚本会附加到组件、等待组件停止、打印所有线程的回溯,然后进入交互式控制台。
[zxdb] attach cobalt.cm
Attached Process
Done.
[zxdb] pause
🛑
# Output the backtraces of all threads of the current process.
[zxdb] thread * frame