# 系统调试:深入
本节将更深入地讨论故障排除,特别关注具有适当调试输出和可选串行设置的更低级的调试。
注意:99%的用户不需要这种级别的调试,这只适用于核心或极端情况。
# EFI 设置
在大多数情况下,只需要相当小的更改。我们主要推荐的是DEBUG版本的OpenCore和所有的kext。这可以帮助您获得所有必要的数据,有关OpenCore调试的更多详细信息,请参阅这里: OpenCore调试
除了使用OpenCore和kexts的DEBUG版本,这些工具也可以提供很大的帮助:
DebugEnhancer.kext (opens new window)
- 极大地帮助内核调试,同时还修补了 kern.msgbuf to 10485760 (opens new window) ,并允许更大的内核日志。
- 注意这个kext不能与内核初始化一起启动,所以早期的日志不会被修补,直到kext在PCI配置阶段之前加载
-
- 启用ACPI表中的调试语句,帮助操作系统中的ACPI事件调试
- 注意你需要编译SSDT (opens new window)
# Config.plist 设置
对于串行设置,OpenCore实际上是非常直接的。
# Misc
# Serial
- Init: YES
- 从 OpenCore 初始化串口
- 需要将OpenCore日志发送到串口
# Debug
- Target:
67
- 启用OpenCore调试输出
Target
=75
添加额外的串行输出标志(0x08
),如果你计划使用串行- 你可以在这里计算你自己的值:OpenCore调试
# NVRAM
# boot-args
在这里,我们要设置一些变量来帮助我们调试输出,对于我们来说,我们将使用以下的boot-args:
-v keepsyms=1 debug=0x12a msgbuf=1048576
现在让我们来看看每个arg的作用:
- -v
- 启用详细输出
- keepsyms=1
- 确保在内核发生严重故障时保留符号,这对故障排除非常有帮助
- debug=0x12a
- Combination of
DB_PRT
(0x2),DB_KPRT
(0x8),DB_SLOG
(0x20), andDB_LOG_PI_SCRN
(0x100) - 最新版本XNU的完整列表可以在这里找到: debug.h (opens new window)
- Combination of
- msgbuf=1048576
- 设置内核的消息缓冲区大小,这有助于在启动期间获得正确的日志
- 1048576 is 1MB(/1024^2), 如果需要可以更大
- 注意:DebugEnhancer kext不需要,但是对于早期的内核日志,它仍然是必需的
其他有用的boot-args:
根据你正在调试的内容,你可能还会发现这些boot-args非常有用:
- -liludbgall
- 在Lilu和任何其他插件上启用调试,但请注意,这需要调试版本的kext
- io=0xff
- 启用IOKit调试,输出更大。请注意,此参数的日志量将非常大,并将降低系统的速度。尤其是在启动的时候。
- igdebug=0xff
- 开启iGPU相关的调试,在使用iGPU系统时很有用
- serial=5
- 将输出重定向到串行如果你计划使用串行
- 推荐用于PCI配置之前的早期内核输出
- acpi_layer=0x8
- 启用
ACPI_TABLES
调试,参见acoutput.h (opens new window) 了解更多信息 0xFFFFFFFF
也可以启用所有层
- 启用
- acpi_level=0x2
- 设置
ACPI_LV_DEBUG_OBJECT
调试,参见 acoutput.h (opens new window) 了解更多信息 0xFFFF5F
也可以表示ACPI_ALL_COMPONENTS
- 设置
# 串行设置(可选)
虽然是可选的,但串行仍然对抓取所有的信息超级有帮助。这也是正确记录超早期内核崩溃的唯一方法(例如在[EB|# log:EXITBS:START]
之后的事情)
对于这个设置,你需要一些东西:
- 测试机上的串行头/端口
- 串行到串行或串行到usb电缆
- 第二台机器接收串行日志记录(使用串行或USB)
- 软件监控串行输出
- 在本指南中,我们将使用 CoolTerm (opens new window) ,因为它支持macOS, Linux, Windows甚至树莓派
screen
和其他方法也支持
# 硬件设置
对于这个例子,我们将使用华硕X299-E Strix板,它有一个串行头。要确认您的单板是否自带串口,请查看单板的所有者或服务手册,并搜索串口/COM端口:
正如你所看到的,我们在主板的底部有一个COM端口,如果你不使用9/10引脚串行头到DB9适配器,甚至为我们手动连接我们的串行引脚提供了一个图表。
或者,一些机器在后IO上带有DB9串行端口,例如这台Dell Optiplex 780 SFF(注意VGA和串行不是同一个连接器):
对于我的X299设置,我使用一个简单的 串行头到DB9 (opens new window), 然后一个 DB9到USB RS 232适配器 (opens new window) 最后终止在我的笔记本电脑:
Serial header to DB9 | DB9 to USB RS 232 adapter |
---|---|
OpenCore手册通常建议CP21202-based UART设备:
要在引导期间获得日志,可以使用串口调试。在目标中打开串口调试,例如0xB表示onscreen with Serial。OpenCore使用115200波特率,8个数据位,无奇偶校验和1个停止位。对于macOS,最好的选择是基于cp2102的UART设备。将主板TX连接到USB UART RX,主板GND连接到USB UART GND。使用屏幕工具获取输出,或者下载GUI软件,比如CoolTerm。 注意:在一些主板(可能是USB UART加密狗)PIN命名可能不正确。GND与RX交换是非常常见的,因此您必须将主板“TX”连接到USB UART GND,并将主板“GND”连接到USB UART RX。
重要提醒:不要忘记在BIOS中启用串口,大多数主板默认情况下将禁用它
# CoolTerm 设置
现在让我们启动CoolTerm (opens new window)并设置一些选项。当您打开CoolTerm时,您可能会看到一个简单的窗口。在这里选择选项条目:
这里给出了很多选项,但我们主要关心的是:
- Port: 确保与您的串行控制器匹配。
- Baudrate = 115200
- Data Bits = 8
- Parity = 无
- Stop Bit = 1
接下来,保存这些设置,并选择Connect条目。这将为你提供一个来自serial的实时日志:
要记录,只需前往 Connections -> Capture to Text/Binary File -> Start...(Cmd+R)
:
# 内核调试工具包(可选)
内核调试工具包(kdk)是一种从内核和核心kext获取更多日志信息的好方法,kdk具体来说是苹果自己提供的macOS核心基础的调试版本。它们包括更多的日志记录和断言,允许您更直接地查看设置中的问题。但是请注意,我们不会讨论桥接调试或 lldb
的用法。
警告: 在工作机器上安装kdk可能会导致操作系统更新和安装出现问题。请在专用的macOS安装上调试,以避免数据丢失
首先,我们至少需要一个来自苹果的免费开发者帐户 (opens new window) 一旦您注册了最低限度的免费层,您现在可以从更多下载页面 (opens new window):
- 注:免费等级将仅限于发布kdk,只有测试版kdk提供给付费开发者帐户 (opens new window)
- 注2:苹果早在OS X 10.5和Leopard时就有kdk了,所以不用担心你的操作系统不受支持
要确定你需要哪个KDK版本的测试版,在终端中运行以下命令:
sw_vers | grep BuildVersion
为此,我将下载内核调试套件11.3 build 20E5186d。下载完成后,挂载磁盘镜像,就可以找到KDK安装程序了。默认情况下,KDK只会为了“执行双机调试”而安装自己,并且默认情况下不会为主机内核调试提供任何额外的好处。
# KDK在已安装的操作系统上
要在主机上启用调试,您需要执行以下操作:
- 运行 KDK 安装 pkg
- 关闭SIP协议(OS X 10.11+)
- 以可写方式挂载根分区(macOS 10.15+)
- 安装调试内核和kext
- 更新boot-args
- 重新启动并检查您的工作
# 1. 运行 KDK 安装 pkg
正常运行pkg即可:
安装完成后,你可以在/Library/Developer/KDKs
目录下找到KDK组件,例如调试内核:
# 2. 禁用SIP
- 适用于OS X 10.11, El Capitan和更新版本
禁用SIP,用户有两种选择:
通过恢复禁用
一般情况下,我们强烈建议恢复,以便通过NVRAM复位轻松恢复,但是一些用户可能需要通过NVRAM擦除禁用SIP。
对于前者,只需重新启动到macOS恢复,打开终端并运行以下命令:
csrutil disable
csrutil authenticated-root disable # Big Sur+
重新启动,SIP将进行相应的调整。你可以在终端中运行csrutil status
来验证它是否工作。
- 注意: 对于依赖OpenCore的ApECID功能 (opens new window)的用户,请注意此 必须 被禁用才能使用KDK。
# 3. 以可写方式挂载根分区
- 适用于macOS 10.15,卡特琳娜及更新版本
将根卷挂载为可写卷很容易,但是这个过程有点长:
# Big Sur+
# 首先,为您的驱动器创建一个挂载点
mkdir ~/livemount
# 接下来,找到您的系统卷
diskutil list
# 从下面的列表中,我们可以看到我们的系统卷是disk5s5
/dev/disk5 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +255.7 GB disk5
Physical Store disk4s2
1: APFS Volume Big Sur HD - Data 122.5 GB disk5s1
2: APFS Volume Preboot 309.4 MB disk5s2
3: APFS Volume Recovery 887.8 MB disk5s3
4: APFS Volume VM 1.1 MB disk5s4
5: APFS Volume Big Sur HD 16.2 GB disk5s5
6: APFS Snapshot com.apple.os.update-... 16.2 GB disk5s5s
# 安装驱动(即。disk5s5)
sudo mount -o nobrowse -t apfs /dev/disk5s5 ~/livemount
# 现在您可以自由地对系统卷进行任何编辑
# 仅限 Catalina
sudo mount -uw /
# 4. 安装调试内核和kext
现在我们将KDK安装到系统中:
# 将KDK安装到系统卷
# 确保替换<KDK版本>
# 对于10.15及以上版本,用/Volumes/<Target Volume>交换live挂载
sudo ditto /Library/Developer/KDKs/<KDK Version>/System ~/livemount/System
# 重建真实的内核缓存(大苏尔及更新版本)
sudo kmutil install --volume-root ~/livemount --update-all
# 重建内核缓存(卡特琳娜和更老的版本)
sudo kextcache -invalidate /Volumes/<Target Volume>
# 最后,一旦完成系统卷的编辑
# 我们要创建一个新的快照(大苏尔和更新的)
sudo bless --folder ~/livemount/System/Library/CoreServices --bootefi --create-snapshot
# 5. 更新boot-args
现在您已经完成了KDK的设置和安装,现在我们需要告诉boot.Efi使用哪个内核。你有两个选择:
kcsuffix=debug
(由Big Sur移除)kcsuffix=development
kcsuffix=kasan
development
参数将在Big Sur中设置新的默认调试内核,而kasan
是一个更注重日志记录的内核,包含AddressSanitizer (opens new window).
一旦你决定了哪个内核最适合你,在config.plist中将kc后缀arg添加到boot-args中
# 6. 重新启动并检查您的工作
假设一切都正确地完成了,现在要重新启动,检查是否引导了正确的内核:
sysctl kern.osbuildconfig
kern.osbuildconfig: kasan
正如我们所看到的,我们成功地启动了KASAN内核。
# 卸载KDK
卸载KDK相当简单,但是如果不小心,可能会有一点破坏性。
- 将根分区挂载为可写(macOS 10.15+)
- 删除调试内核和kext
- 重新启用SIP
- 清除引导参数
- 重新启动并检查您的工作
步骤:
# 1. 将根分区挂载为可写(macOS 10.15+)
# Big Sur+
# 首先,为您的驱动器创建一个挂载点
# 上次挂载卷时仍然存在的跳过
mkdir ~/livemount
# 接下来,找到您的系统卷
diskutil list
# 从下面的列表中,我们可以看到我们的系统卷是disk5s5
/dev/disk5 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +255.7 GB disk5
Physical Store disk4s2
1: APFS Volume Big Sur HD - Data 122.5 GB disk5s1
2: APFS Volume Preboot 309.4 MB disk5s2
3: APFS Volume Recovery 887.8 MB disk5s3
4: APFS Volume VM 1.1 MB disk5s4
5: APFS Volume Big Sur HD 16.2 GB disk5s5
6: APFS Snapshot com.apple.os.update-... 16.2 GB disk5s5s
# 挂载驱动(即.disk5s5)
sudo mount -o nobrowse -t apfs /dev/disk5s5 ~/livemount
# 仅限卡特琳娜
sudo mount -uw /
# 2. 删除调试内核和kext
# 恢复旧快照(Big Sur+)
sudo bless --mount ~/livemount --bootefi --last-sealed-snapshot
# 重置内核缓存(Catalina及更老版本)
sudo rm /System/Library/Caches/com.apple.kext.caches/Startup/kernelcache.de*
sudo rm /System/Library/PrelinkedKernels/prelinkedkernel.de*
sudo kextcache -invalidate /
# 3. 重新启用SIP
- 恢复命令(如果之前通过恢复更改):
csrutil enable
csrutil authenticated-root enable # Big Sur+
- config.plist更改(如果之前通过config.plist更改):
# 4. 清除引导参数
不要忘记在你的引导参数中删除kcsuffix=
# 5. 重新启动并检查您的工作
假设一切都正确地完成了,现在要重新启动,检查是否引导了正确的内核:
sysctl kern.osbuildconfig
kern.osbuildconfig: release
正如我们所看到的,我们成功地引导了一个KASAN内核。