Zircon作为一个谷歌新开发的微内核,对开发者来说调测机制和调测工具都是全新的,目前Zircon内核支持GDB调试,
内核程序支持Zxdb调试,程序异常退出支持堆栈打印和符号解析,进程间通信Fidl调测,内核命令行调测,内存调测,
OOM调测,网络调测,系统日志调测等机制,总体来说,Zircon调测手段较为丰富和成熟。
下文将对上述调测机制进行介绍。
基础命令
fx scp [$(fx get-device-addr)]:/tmp/filename.ppm /tmp/filename.ppm /* 从fuchisa拷贝到本地 */
GDB调试内核(2022.3 gdb debug不了)
使用qemu启动fuchsia虚拟机,GDB通过网络调试zircon内核镜像文件,对于内核启动流程调试十分便利。
编译
构建支持GDB调试,使用以下方式编译:
fx set <whatever>
fx build
运行
shell1 $ fx run -- -s -S (运行fuchisa并暂停等待gdb调试)
shell2 $ gdb out/default/kernel_x64/zircon.elf -x zircon/kernel/scripts/zircon.elf-gdb.py
shell2 (gdb) target extended-remote :1234 (进入gdb命令行后输入该命令)
之后可以使用gdb命令调试zircon内核
(gdb)b lk_main
(gdb) c
BACKTRACE调测(2022.3可用)
Fuchsia支持进程异常退出(如非法指针)后打印堆栈,
并可对堆栈进行符号解析,打印函数名,文件名,行号信息,对于进程异常退出后问题定位有很大帮助。
自动回溯
使用symbolize工具可以接收标准输入并对日志中的调用栈进行符号解析,然后在堆栈日志后打印解析符号后的函数调用栈。
运行如下命令等待系统日志和对函数调用栈解析:
shell1 $ fx run -N (加载fuchisa并支持网络)
shell2 $ fx serve (启动Zircon服务端)
shell3 $ fx shell <your-cmd> (运行可能会异常退出的程序)
shell4 $ ./scripts/fx syslog | ./scripts/fx symbolize (等待Fuchsia syslog日志并将日志作为标准输入给symbolize解析工具,实现日志自动回溯函数调用栈。原理:日志中记录了动态库起始地址,函数偏移等信息)
手动回溯
在代码的特定位置写入backtrace_request函数(用户态)或thread_print_backtrace函数(内核态),
实现线程特定位置堆栈打印,类似Linux内核的dump_stack()函数。
用户态进程
1 头文件依赖
#include <lib/backtrace-request/backtrace-request.h>
2 编译依赖
在修改文件目录BUILD.gn deps项增加路径”$zx/system/ulib/backtrace-request”
3 在希望打印堆栈处增加如下代码:
void my_function() {
...
backtrace_request();
...
}
解析堆栈
将带有堆栈的日志拷贝至文件bt-trace.txt,放置于fuchsia目录下,
执行 cat bt-trace.txt | ./scripts/fx symbolize 解析函数符号。
内核态进程
头文件依赖
#include <kernel/thread.h>
在希望打印堆栈处增加如下代码:
void my_function() {
thread_print_backtrace(get_current_thread(), __GET_FRAME(0));
}
ZXDB调测(2022.3可用)
Zxdb是Fuchsia内置一个调试工具,类似于GDB,可以对fuchsia内程序进行
如断点(break),单步调试(step/next),转储文件调试,进程调试(process),
汇编(disassemble),打印(print),堆栈(bt)等调试。
参考:https://fuchsia.dev/fuchsia-src/development/debugger/running
以编译workstation为例,core.x64也支持
fx set core.x64 --with //bundles:tools
fx build
调试
shell1 $ fx qemu -N /* 或者 fx emu -N */(加载fuchisa并支持网络)
shell2 $ fx serve-updates (启动Zircon服务端)
shell3 $ ffx debug connect (进入zxdb命令行)
在zxdb命令行输入:attach 进程名 (等待某个进程启动)
attach 进程号 (关联到正在运行进程)
break main (打断点,等待进程运行)
shell4$ fx shell (进入fuchsia命令行,或者在shell1中运行待调试程序)
执行应用程序 如crasher,此时shell3中程序执行到断点main,此后 shell3中可以使用类似GDB的单步调试命令:next,step,print argv[1],continue,quit等
一些小程序可以直接在zxdb控制台启动,无需attach。
break @main命令中“@main”符号将匹配进程的入口点,这对于Rust来说特别有用。
对于C/C++,它相当于“main”。
break/b lineNum/FuncName:设置一个断点
run/r ProcessName :运行程序
step/s:执行下一行代码
next/n:执行下一个函数
print/p:打印变量值
类似于gdb,zxdb也有一系列进程调试的命令。
attach:附加到进程
process:列出所附加的进程
job:列出附加的工作
thread:列出当前进程中的线程
thread n:切换到线程n
frame:列出当前线程的堆栈帧(需将线程pause)
pause:将线程暂停
continue:将线程恢复运行
bt:显示线程详细调用栈
FIDL调测(2022.3可用)
/* fidlcat需要--with //bundles:tools选项才能编译 */:
fx set core.x64 --with //bundles:tools --with //examples
fx build
运行fidlcat,需要在启用网络的情况下启动:
shell1 $ sudo ip tuntap add dev qemu mode tap user $USER && sudo ip link set qemu up
shell1 $ fx emu --headless -N // 或者fx qemu -N(/* 若fvm报错,export LANG=C */ /* -N加载fuchisa并支持网络 */)
shell2 $ fx serve-updates (启动Zircon服务端)
shell3 $ fx fidlcat --remote-pid=<pid>
在shell3中使用fx fidlcat --remote-pid=<pid>关联到正在运行的进程。
如果调试组件未运行,使用fidlcat启动程序:
fx fidlcat run fuchsia-pkg://fuchsia.com/echo_client_rust#meta/echo_client_rust.cmx
或者使用与构建已知的唯一URL匹配的bash正则表达式指定URL:
fx fidlcat run "echo_client_cpp_synchronous.*"
fx fidlcat run echo_client_cpp.cmx
也可以通过名字,关联到一个后续会启动的程序:
fx fidlcat --remote-name=echo_client
必选项
三个选项--remote-pid, --remote-name和run都可以一起使用。但是,run必须始终是最后一个。
当同时使用--remote-name和run时,仅监视与--remote-name匹配的进程。
示例(echo_server由echo_client启动):
运行并监视echo_client。sh fx fidlcat run echo_client_cpp.cmx
运行并监视echo_client。 sh fx fidlcat --remote-name=echo_client run echo_client_cpp.cmx
运行echo_client并监视echo_server。sh fx fidlcat --remote-name=echo_server run echo_client_cpp.cmx
运行echo_client并监视echo_client和echo_server。 sh fx fidlcat --remote-name=echo run echo_client_cpp.cmx
运行echo_client并监视echo_client和echo_server。 sh fx fidlcat --remote-name=echo_client --remote-name=echo_server run echo_client_cpp.cmx
可选项
--with-process-info : 在每一行显示名字,进程号,线程号,对于grep有用
--stack=<value>: 定义需要显示的堆栈帧
0 默认值,不显示
1 显示1-4帧堆栈
2 显示所有堆栈
如图为显示cowsay程序带--stack参数的fidl流量,黄色部分为详细堆栈。其他使用方法参考:fx fidlcat --help
使用示例
使用fidlcat工具监控ps命令的fidl消息:
shell1 $ fx run -N (加载fuchisa并支持网络)
shell2 $ fx serve (启动Zircon服务端)
shell3 $ fx fidlcat --remote-name=ps (fidlcat等待并监控ps命令)
shell4 $ fx shell ps (新开一个Fuchsia shell,执行ps命令)
此时shell 3中会打印ps命令所涉及的详细fidl流量。
trace(2022.3可用)
trace Fuchisa启动过程
shell $ ffx trace record --categories=kernel,kernel:retain --buffer-size=64 --duration=1s --stream
Trace Complete:
- trace-2022-03-11T10:38:47.fxt can be viewed using https://ui.perfetto.dev/
- trace-2022-03-11T10:38:47.json can be viewed using chrome://tracing
syslog
shell1 $ fx qemu -N (加载fuchisa并支持网络)
shell2 $ fx serve-updates (启动更新serve)
shell3 $ fx log (监听syslog系统日志或其他处理)/* fx klog 查看netsvc提供的内核日志 */
shell4 $ fx shell <cmd> (此时shell3中会打印<cmd>输出的日志)
也可以运行fx shell进入zircon命令行后,执行cmd
如图为使用syslog实时监控系统日志并过滤关键词crasher: