3

用USB 3.0 + WinDbg开始你的调试之旅

 2 years ago
source link: https://zhuanlan.zhihu.com/p/405683773
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用USB 3.0 + WinDbg开始你的调试之旅

中央处理器 (CPU)话题下的优秀答主

Windows蓝屏相比Linux kernel panic相对好解决,一个重要原因是它有一个强大的debug工具:WinDbg。WinDbg十分的好用,起码比Linux GDB/KDB要好用的多。有了它,很多问题就可以迎刃而解,熟练的掌握了它,不但可以调试硬件/BIOS错误,还可以调试驱动,甚至应用程序。它可以独立使用,也可以仅仅作为前端,后端连接Intel ITP、GDB甚至是UEFI BIOS的debug agent,可谓是“居家旅行,杀人灭口的必备良药“。

我在前文介绍了一些发生蓝屏的离线CrashDump分析工具:

今天我们就进入正题,正式开启WinDbg之旅。

WinDbg + USB 3.0调试的准备工作

在《前目的地》电影中,John穿越到过去,和过去的自己,生下了自己。这种极度“内卷”的循环并不适用Window内核调试,尽管WinDbg可以调试本机的驱动和应用程序,但调试本机的Windows内核则非其力所能及。一般来讲,WinDbg调试内核需要两台机器:Host和Target

v2-92b1394dd8f5e6b049dbfa733ec141c7_720w.jpgWinDbg调试环境

Target机是我们的调试目标机,即发生了蓝屏的Windows机器,亦或其中是我们的BIOS,我们想要调试某段ACPI ASL代码等等。Host机是WinDbg跑的机器,也是我们操作的机器。两者之间用调试线连接在一起,这个调试线可以是串口、火线(1394)或者是USB线。

在以往的Debug实践中,除去几乎没有人用的1394线之外,串口和USB线都有自己的缺陷。先说串口,PCH中传统UART和High Speed UART(HSUART)设备有好多个,你现在用的搞不清楚是Windows认为的第几个COM口,而且成品机型的UART甚至没有连出来,给WinDbg造成很大不便。尽管可以有各种变通的办法,但在第一次使用时,总是会造成一些麻烦。USB 2.0引入debug功能,但在USB 2.0时代,只有port 0具有debug功能,主板上一堆USB口,哪个是port 0?主板到底引出来了没有?这都是问题。

USB 3.0和随后的USB 3.1/3.2的到来改变了这一切,USB 3.0所有的口都支持debug,不再调口了,十分方便。现在我们就来准备这三样吧:Host、Target和USB 3.0 debug cable。

我的Host是我日常用的NUC豆子峡谷:

Target是Intel最新的Alderlake (ADL)开发板:

从图中可以看到两者都插有一个USB连线,这个线是专用USB 3.0 debug线。USB 3.0 debug cable是一种内部做了遮蔽的A口公对公线,可以在淘宝上买到,我用的是这种[1]

其中附送一个转USB Type C的头,可以连接Type C口调试,十分方便。

Target机准备

目标机需要打开调试,输入msconfig打开系统配置工具。在引导>高级选项下面:

勾选调试,调试端口选择USB,USB目标名称随便写一个自己能记住的名字。将来Host和Target两端要靠这个名字进行匹配。关闭系统配置工具,系统提示要重新启动:

我们还要确定一件事,先不选择启动。

打开我之前推荐的HE工具

或者USBView工具。观看系统有几个xhci控制器,在我的系统里面只有一个:

这个是PCH内置的USB 3.2控制器。如果你是通过外插PCIe USB的方式调试,你可能会看到两个以上的xhci控制器。如果仅仅一个xhci(大多数情况),就什么都不用做了。如果是两个以上,你需要在HE里面找到它的PCI BDF号码(Bus、Device、Func),再用bcdedit配置USB控制器信息,具体可以参考[2]

好了,Target机准备完毕,我们可以看看Host端需要准备什么。

Host端软件准备

Host端需要安装WinDbg。目前有两种WinDbg,在Microsoft应用商店里面可以下载免费的WinDbg Preview,只要在应用商店里面搜索WinDbg,就可以下载安装,十分方便。

WinDbg Preview界面比较现代,但其中缺乏一些重要的内容。我推荐同时安装传统的Windbg工具,搜索Window 10 SDK,或者直接点击参考资料3[3]。Win10 SDK很大,不需要都装,只要安装“Debugging Tools for Windows”即可。

两个安装完毕后,还要做一些必要的准备工作。

首先要设置Symbols,也就是调试符号文件的路径。微软为了方便开发,会定期发布调试符号文件包,也有Symbols服务器,建议使用调试符号服务器。在传统的WinDbg里面打开

在WinDbg Preview里面在Setting的Debugging Settings里:

我的Symbols path是:“c:\MySymbols;srv*c:\MySymbols*https://msdl.microsoft.com/download/symbols

它是什么意思呢?就是Symbols要不在我的C盘MySymbols目录下;要不去微软Symbol服务器下载下来,存在C盘MySymbols下。这个c:\MySymbols不需要我们手动创建,下载的时候没有会自动创建。自动下载比较好,随着Win10不停地推送patch,内核的各个模块升级对应不同的symbol文件,他们会在模块名称下面不同的hash值目录下各自展开,互不干扰。这个内核模块,是目标机器的内核模块而不是Host的内核模块。这样你今天可以调试21H1的模块,明天可以调试20H3的模块,完全没有问题。唯一的问题是,调试的多了后,太多pdb文件可能需要定时清理

设置好了Symbol路径后,我们可以开始准备调试了。在WinDbg Preview中:

选择Attach to kernel,在调试目标中选择USB,注意Target 名字要和Target机器设置的完全一样。

好了。万事俱备了,开动!按下回车,WinDbg显示:

忽略这个error。Target机器选择重启,静待奇迹发生!可惜什么都没有发生,Target直接蓝屏重启了,哪里出错了呢?

USB debug cable驱动安装问题

这实际上是USB 3.0调试线的驱动没有装好的问题。打开设备管理器,发现一个大大的惊叹号:

那么驱动在哪里呢?这就是我为什么建议要安装传统WinDbg的原因,在Win10 SDK安装包里面有USB驱动,会随着“Debugging Tools for Windows”一起安装。右键点击这个设备选择更新驱动程序,在WinDbg目录下有个USB目录:

驱动就在这里。注意上面说的USBView也在根目录。

安装好USB驱动后,设备正常了:

注意如果你去网上搜索某些驱动安装包,因为驱动程序的兼容性问题,很可能出现发现设备但运行不正常的情况。这里强烈建议安装最新的Win10 SDK,驱动也可以选择最新的目录下驱动。

好了,再来一次。这次终于正常了:

由于我们选择的break at connection,所以在Windows 10的小点转圈的地方就停下来了。我们可以按下F10建,单步走几步:

我们来看看Win10跑到哪里了,选择Modules:

这时候Windows 10刚刚起来第一个模块ntkrnlmp.exe,这个就是OS的Kernel MP版本,ACPI等等统统没有准备好。如果我们键入!acpiinf,会发现ACPI表没有准备好呢。

还是让子弹再飞一会,输入g,继续跑。进到操作系统里面,再次键入!acpiinf

 kd> !acpiinf
ACPIInformation (fffff80515a03210)
  RSDT                     - fffff78c80004018
  FADT                     - fffff78c80050018
  FACS                     - ffffb100dc743000
  DSDT                     - ffffd78c36a02018
  GlobalLock               - ffffb100dc743010
  GlobalLockQueue          - F - fffff80515a03240 B - fffff80515a03240
  GlobalLockQueueLock      - 0000000000000000
  GlobalLockOwnerContext   - 0000000000000000
  GlobalLockOwnerDepth     - 0000000000000000
  ACPIOnly                 - FALSE
  PM1a_BLK                 - 0000000000000000 (N/A)
  PM1b_BLK                 - 0000000000000000 (N/A)
  PM1a_CTRL_BLK            - 0000000000000000 (N/A)
  PM1b_CTRL_BLK            - 0000000000000000 (N/A)
  PM2_CTRL_BLK             - 0000000000000000 (N/A)
  PM_TMR                   - 0000000000000000 (N/A)
  GP0_BLK                  - 0000000000000000 (N/A)
  GP0_ENABLE               - 0000000000000000 (N/A)
  GP0_LEN                  - 0000000000000020
  GP0_SIZE                 - 0000000000000010
  GP1_BLK                  - 0000000000000000 (N/A)
  GP1_ENABLE               - 0000000000000000 (N/A)
  GP1_LEN                  - 0
  GP1_SIZE                 - 0
  GP1_BASE_INDEX           - ffff
  GPE_SIZE                 - 10
  PM1_EN_BITS              - 4120
     20 - GBL_EN  100 - PWRBTN_EN  
  PM1_WAKE_MASK            - 0000
  C2_LATENCY               - 0
  C3_LATENCY               - 0
  ACPI_FLAGS               - 0
  ACPI_CAPABILITIES        - 0

键入!acpitable

kd> !acpitable
Dumping cached ACPI tables...
  XSDT @(fffff78c80004018) Rev: 0x1 Len: 0x0000f4 TableID: ADL
  DBGP @(fffff78c80005018) Rev: 0x1 Len: 0x000034 TableID: ADL
  MCFG @(fffff78c80006018) Rev: 0x1 Len: 0x00003c TableID: ADL
  FACP @(fffff78c80050018) Rev: 0x6 Len: 0x000114 TableID: ADL
  APIC @(fffff78c80051018) Rev: 0x5 Len: 0x0001dc TableID: ADL
  DMAR @(fffff78c80054018) Rev: 0x2 Len: 0x000088 TableID: ICL     
  HPET @(fffff78c800d7018) Rev: 0x1 Len: 0x000038 TableID: ADL
  FPDT @(ffffd78c34ef8128) Rev: 0x1 Len: 0x000044 TableID: ADL
  SSDT @(ffffd78c34fed018) Rev: 0x2 Len: 0x005ce0 TableID: CpuSsdt
  ECDT @(ffffd78c34ff2d28) Rev: 0x1 Len: 0x000069 TableID: ADL
  SSDT @(ffffd78c34ff3018) Rev: 0x2 Len: 0x008968 TableID: AdlS_Rvp
  SSDT @(ffffd78c34ffc018) Rev: 0x2 Len: 0x001f1a TableID: Ther_Rvp
  SSDT @(ffffd78c360c5018) Rev: 0x2 Len: 0x002a65 TableID: SaSsdt 
  SSDT @(ffffd78c360c8018) Rev: 0x2 Len: 0x003316 TableID: IgfxSsdt
  LPIT @(ffffd78c360cb358) Rev: 0x1 Len: 0x0000cc TableID: ADL
  WSMT @(ffffd78c360cb458) Rev: 0x1 Len: 0x000028 TableID: ADL
  SSDT @(ffffd78c360cc018) Rev: 0x2 Len: 0x002a83 TableID: PtidDevc
  SSDT @(ffffd78c360cf018) Rev: 0x2 Len: 0x002357 TableID: TbtTypeC
  DBG2 @(ffffd78c360d13f8) Rev: 000 Len: 0x000054 TableID: ADL
  NHLT @(ffffd78c360d1478) Rev: 000 Len: 0x00002d TableID: ADL
  SSDT @(ffffd78c34ffe018) Rev: 0x2 Len: 0x001919 TableID: UsbCTabl
  SSDT @(ffffd78c360d2018) Rev: 0x2 Len: 0x0012c7 TableID: xh_adls3
  SSDT @(ffffd78c367dd018) Rev: 0x2 Len: 0x003aea TableID: SocGpe 
  SSDT @(ffffd78c367e1018) Rev: 0x2 Len: 0x002b2a TableID: SocCmn 
  SSDT @(ffffd78c367e3b78) Rev: 0x2 Len: 0x000144 TableID: ADebTabl
  BGRT @(ffffd78c367e3ce8) Rev: 0x1 Len: 0x000038 TableID: ADL
  PHAT @(ffffd78c360d3308) Rev: 000 Len: 0x000669 TableID: ADL
  DSDT @(ffffd78c36a02018) Rev: 0x2 Len: 0x07e278 TableID: ADL

好了,一切正常,我们下次继续!

WinDbg命令很多,我们后面计划分成两个部分讲解:

1.ACPI ASL debug

2.蓝屏case study

再开始之前,建议大家购买前Intel员工——张工的《软件调试》,里面保罗万象,内容十分丰富。

欢迎大家关注本专栏和用微信扫描下方二维码加入微信公众号"UEFIBlog",在那里有最新的文章。

用微信扫描二维码加入UEFIBlog公众号


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK