Skip to content

调试与日志 ​

bring-up 需要四类证据:串口输出、屏幕诊断页、panic 屏幕和构建报告。把它们一起收集。

日志来源 ​

来源通道用途
UEFI 串口UART固件、UniXNU、DarwinBoot
内核串口由 serial= 选择的 UARTXNU 控制台和 panic 输出
诊断页framebuffer控制台停止后的实时状态
脉冲条framebuffer 底部诊断页占用面板时的心跳
panic 屏幕framebufferpanic 文本和寄存器
QEMU 日志文件UniXNU 和加载器测试
构建报告JSON输入哈希和阶段结果

串口 ​

把参数加入负载:

toml
[payload]
kernel_args = ["-v", "serial=3", "debug=0x14e"]

UniXNU 启动管理器写到第一个 EFI_SERIAL_IO_PROTOCOL,行以 UNIXNU: 开头。DarwinBoot 的行以 DARWINBOOT: 开头。

抓取串口:

sh
tio -b 115200 -d 8 -p none -s 1 /dev/tty.usbserial-0001 -L out/serial.log

其他工具:

sh
picocom -b 115200 /dev/tty.usbserial-0001
screen -L /dev/tty.usbserial-0001 115200
minicom -D /dev/tty.usbserial-0001 -b 115200

设备页面记录 UART 引脚和波特率。支持 USB device 模式的板子可以暴露 CDC ACM 串口。

常用的早期输出:

UNIXNU: UniXNU 0.1.0 starting as firmware boot option
UNIXNU: config: loaded \EFI\UniXNU\unixnu.toml
UNIXNU: driver ...: started
UNIXNU: menu: shown 2 entries, default 0
DARWINBOOT: loader v2 installed EL1
DARWINBOOT: ARM64 va=... pa=... args=... entry=... owned=...
DARWINBOOT: inputs validated; exiting boot services

屏幕诊断页 ​

诊断页是绘制到 XNU framebuffer 映射上的全屏文本覆盖层。启用方式:

boot-progress=1

级别 1 启动监视器。30 秒没有阶段或存储活动,或达到 120 秒观察上限时,页面冻结并保留屏幕,便于拍照。

boot-progress=2

级别 2 连续运行。超过时限只报告,系统继续运行。

页面使用 48 行、120 列。面板至少 2160x1400 时缩放为 3。

行区域内容
标题构建标签、live 或 stop 状态、原因
1时间、空闲、IRQ 计数、监视器计数、root 状态、进程数、空闲页
2存储请求、已验证块、失败、完整性计数
3 到 30阶段历史、进程状态、存储细节、最后 PC 和寄存器
31 到 47缓存存储输出、UFS 计时、内存、进程采样、UI trace、触控行
47独立脉冲条

给镜像加标签,拍照后可以确认构建:

sheng-build-tag=ks-001

标题栏会以 [ks-001] 开头。

用户态接管显示并停止扫描输出后,可以收回面板:

boot-diag-resume=10

10 秒没有 scanout 后页面重绘。新的有效 scanout 会再次让出面板。

页面字段:

字段含义
time监视器启动后的秒数
idle距上次阶段或 I/O 进展的秒数
IRQ监视器统计的中断入口数
monitor监视器线程迭代数
lost丢弃的记录更新数
rootowner root 接受状态
procs进程数
free空闲 4 KiB 页
requests存储请求
verified4K已验证 4 KiB 块
failures存储失败
integrity存储完整性失败
last PC最后中断入口 PC
TCR、TTBR、SCTLR翻译控制和页表基址寄存器

脉冲条 ​

脉冲条位于面板底部,高 32 像素,2 倍缩放,绿色文字,由独立高优先级监视线程每秒更新。

P<turn> I<irq> M<monitor>/<seconds> B<bind>:<result> d<depth> @<base> lock<busy>/<render> PC<pc>
字段含义
P脉冲轮次
I中断入口数
M监视器计数和距上次推进的秒数
Bframebuffer 绑定次数、结果和深度
@framebuffer 基址
lock记录器和渲染器忙碌标志
PC最后中断入口 PC

诊断页占用面板时脉冲条持续存在。OS 接管显示后它关闭。boot-diag-resume 会重新打开诊断页和脉冲条。

panic 屏幕 ​

负载可以把 panic 屏幕打进内核副本:

toml
[payload]
panic_screen = true

负载步骤运行:

sh
python3 scripts/patch-xnu-entry-probe.py <kernel> --panic-screen --no-reset

panic 屏幕把格式化后的 panic 消息和寄存器写到 framebuffer,并保持显示。--no-reset 停止自动复位,屏幕保留到拍照完成。

第一条 panic 消息也会复制到 boot_progress_panic_text。secondary core 上的 panic 只停住该 core,实时横幅在屏幕重绘后仍保留文本。

设备树 panic 区域需要:

CONFIG_XNU_DT_PANIC_REGION=y

内核读取 /chosen 的 embedded-panic-log-size 和区域的 reg 属性,映射前先校验。

用户态故障证据 ​

故障探针在异常投递前记录 EL0 breakpoint 和 abort 状态:

字段含义
pid、name进程
PC、LR、SP、FP故障时寄存器
ESR、FAR异常综合征和故障地址
slideshared region slide
x0 到 x28通用寄存器
frames最多 12 个返回地址

捕获在 trap 路径中完成,不分配内存。匹配的进程退出时,记录随信号打印。未捕获异常的原因会从退出进程的可写 malloc 区域中搜索并打印到崩溃行。

UI 栈追踪 ​

UI trace 采样指定进程,打印 PC、LR、FP 和栈切片:

boot-ui-focus=launchd
boot-ui-focus2=SpringBoard
boot-ui-focus3=backboardd
boot-ui-focus4=Setup
boot-ui-chrono=1

地址使用 64 进制字母表编码,以适配行宽。把抄录的行交给解码器:

sh
python3 scripts/decode-boot-ui-trace.py trace.txt

解码器为每个线程组输出一个 JSON 对象,包含 pc、lr、帧和错误码。

trace 每 8 秒轮换一页。间隔几秒拍三到四张照片,覆盖全部页面。

拍照 ​

诊断页按拍照场景设计。建议流程:

  1. 把 sheng-build-tag 设为简短的镜像标签。
  2. 冻结页面用 boot-progress=1,实时页面用 boot-progress=2。
  3. 用户态会清屏时设置 boot-diag-resume。
  4. 把设备放在支架上,相机与面板平行。
  5. 关闭闪光灯,从侧面打光,避免反射。
  6. 对标题栏锁定焦点和曝光。
  7. 让面板填满画面,包含四个角。
  8. 先拍标题栏,再拍整页。
  9. UI trace 页面间隔 8 秒拍三到四张。
  10. 拍底部脉冲条。
  11. 记录启动镜像 SHA-256 和拍摄时间。
检查项原因
标题栏可读构建标签和状态标识镜像
文字区域无眩光第 3 到 30 行承载阶段历史
四角可见确认完整面板和缩放
脉冲条可见显示拍摄时的心跳
至少两张变化的计数器说明屏幕在实时更新

相机照片是面板显示内容的证据。保留原始文件。只抄录需要的行,并把照片与抄录一起保存。

QEMU 抓取 ​

sh
python3 package/Scripts/qemu-run.py out/esp \
  --log out/qemu.log --screenshot out/qemu.png \
  --expect 'UNIXNU: menu: shown'

运行器把去掉 ANSI 的日志写到 out/qemu.clean.log。--screenshot 在菜单出现时截屏。--keys 在菜单后发送 QEMU 键码。

停止辅助脚本在指定符号处记录寄存器和内存:

sh
python3 scripts/qemu-entry/gdb-stop.py --help

调试参数 ​

参数用途
-v详细内核输出
serial=3串口控制台
debug=0x14e调试输出掩码
kextlog=0xfffkext 日志
boot-progress=1诊断页,30 秒停滞后冻结
boot-progress=2诊断页连续运行
sheng-build-tag=<tag>标题栏镜像标签
boot-diag-resume=<seconds>OS 停止 scanout 后收回面板
sheng-platform-stage=<n>在平台专家阶段停住
sheng-touch=<n>触控探针阶段
offline-legacy-phase=<n>显示探针阶段
-no_slto_panic关闭 SLTO panic
cs_debug=<mask>代码签名输出

证据包 ​

收集:

项目来源
串口日志UART 抓取文件
诊断照片标题栏、整页、trace 页、脉冲条
panic 照片panic 屏幕
启动报告out/<board>/boot/boot.json
负载报告out/<board>/payload/payload.json
构建日志out/<board>/logs/

每张照片都记录启动镜像哈希:

sh
shasum -a 256 out/<board>/boot/boot.img
jq . out/<board>/boot/boot.json

下一步 ​

Released under the BSD-2-Clause-Patent License.