即时调试

概览

即时调试 (JITD) 可让 Fuchsia 挂起崩溃的进程, 相关方可以稍后进行调试/处理。这允许有趣的流程,例如 将 zxdb 复制到在未连接/未运行调试程序时于夜间崩溃的程序。

这是通过将进程存储在异常位置名为“Process Limbo”的特殊位置来实现的。这个 将使这些进程保持暂停状态,直到有其他客服人员过来并释放它们为止。

请参阅实现,详细了解其工作原理。

如何启用

Process Limbo 的一大好处是能够捕获 而无需运行调试程序。这对于以下情况尤为有用 无法运行调试程序的位置,例如驱动程序启动。对于此类情况, Process Limbo 可以提供宝贵的调试信息来源。

启用 Process Limbo 的方法有两种:

手动激活

ffx 插件可让用户查询 limbo 的当前状态:

$ ffx debug limbo --help
Usage: ffx debug limbo <command> [<args>]

control the process limbo on the target

Options:
  --help            display usage information

Commands:
  status            query the status of the process limbo.
  enable            enable the process limbo. It will now begin to capture
                    crashing processes.
  disable           disable the process limbo. Will free any pending processes
                    waiting in it.
  list              lists the processes currently waiting on limbo. The limbo
                    must be active.
  release           release a process from limbo. The limbo must be active.

See 'ffx help <command>' for more information on a specific command.

启动时启用

仅当您能向系统发送命令时,才能手动激活。但一些开发 环境会更早运行用户可交互(或运行调试程序)的软件。推动因素 就是一个很好的例子对于此类情况,从一开始就让 Process Limbo 处于活跃状态,您可以捕获 司机在旋转时发生崩溃,这通常是最难解决的问题 调试。

为此,必须在 build 中设置一项配置:

fx set <YOUR CONFIG> --with-base //src/developer/forensics:exceptions_enable_jitd_on_startup

或者,将此标签添加到 build 参数中的 base_package_labels。您仍然可以使用 使用 Limbo CLI 工具停用和操纵 limbo。然后,您需要推送更新 您的设备,以使此更改生效。

注意:驱动程序初始化很复杂,冻结的崩溃过程可能会使系统处于 未定义的状态和“挂起”因此,使用该功能时,您收获的成效可能会有所不同,尤其是对于 早期驱动因素。

使用方式

zxdb

JITD 的主要用户是 zxdb,它能够附加到在 limbo 中等待的进程。时间 启动 zxdb,它会自动附加到处于 limbo 等待状态的进程:

$ ffx debug connect
Connecting (use "disconnect" to cancel)...
Connected successfully.
👉 To get started, try "status" or "help".
Processes attached from limbo:
  48487: crasher
Type "detach <pid>" to send back to Process Limbo if attached,
type "detach <pid>" again to terminate the process if not attached, or
type "process <process context #> kill" to terminate the process if attached.
See "help jitd" for more information on Just-In-Time-Debugging.
Process "crasher" (48487) crashed and has been automatically attached.
Type "status" for more information.
Attached Process 1 state=Running koid=48487 name=crasher component=sshd-host.cm
Loading 9 modules for crasher Done.
   23
   24 int blind_write(volatile unsigned int* addr) {
 ▶ 25   *addr = 0xBAD1DEA;
   26   return 0;
   27 }
════════════════════════════════════════════════════════════════════════════
 Data fault writing address 0x0 (translation fault level 2) (second chance)
════════════════════════════════════════════════════════════════════════════
 Process 1 (koid=48487) thread 1 (koid=48489)
 Faulting instruction: 0x642ff060

🛑 blind_write(volatile unsigned int*) • crasher.c:25

[zxdb] thread
  # state                koid name
▶ 1 Blocked (Exception) 58692 initial-thread

[zxdb] frame
▶ 0 blind_write(…) • crasher.c:25
  1 main(…) • crasher.c:356
  2…4 «libc startup» (-r expands)

[zxdb] list
   20   int (*func)(volatile unsigned int*);
   21   const char* desc;
   22 } command_t;
   23
   24 int blind_write(volatile unsigned int* addr) {
 ▶ 25   *addr = 0xBAD1DEA;
   26   return 0;
   27 }
   28
   29 int blind_read(volatile unsigned int* addr) { return (int)(*addr); }
   30
   31 int blind_execute(volatile unsigned int* addr) {
   32   void (*func)(void) = (void*)addr;
   33   func();
   34   return 0;
   35 }

在 zxdb 中,您也可以通过执行 help jitd 来详细了解如何使用它。

处理 Limbo FIDL 服务

Process Limbo 提供 FIDL 服务,这是 Process Limbo CLI 工具的功能, zxdb 使用。FIDL 协议在 //sdk/fidl/fuchsia.exception/process_limbo.fidl 中定义。

实现

崩溃服务

当进程抛出异常时,Zircon 会生成关联的 exception handle。它会 然后看看是否有任何相关的异常渠道中是否有监听器感兴趣 处理该异常。这就是 zxdb 等调试程序在运行时如何获取异常的 过程。如需了解详情,请参阅异常处理

但是,由于已经没有任何异常处理程序,或者由于已经全部退出了, 决定传递处理它时,根作业有一个名为 crashsvc 的独占处理程序。触发 异常崩溃,应了解该异常已“崩溃”并且没有任何程序 处理的。然后,崩溃服务会将崩溃堆栈轨迹转储到日志, 将异常传递给 Exception Broker

异常代理

异常代理负责决定如何处理崩溃异常, 具体取决于实际系统配置。它可能会决定创建一个小型转储文件, 崩溃报告、将异常发送到 Process Limbo 或终止该进程。

异常代理了解流程 Limbo 及其是否处于活动状态。收到 异常时,系统将检查 Process Limbo 是否已启用。如果包含,则会传递异常 处理它。这与 FIDL 服务公开的 Process Limbo 相同。