UEFI开发探索28 – 用Windbg建立UEFI调试环境

最近的翻译计划和博客计划严重滞后。一方面是因为有两个案子在推进,业余时间也被占用;另外一方面,在尝试用windbg搭建调试环境的时候,遇到了一些阻碍。

大部分情况下,我都是使用win10的虚拟机,配合UDK2018开发的。对照文档,第一次尝试就失败了。

文档中建议的环境是Win 7/Win8 64位,UDK2010。搭建win7的虚拟机,安装Vs2008+UDK2010,再试,不行。

我怀疑虚拟机是不是会有影响,幸好公司到处都是Mini PC。下班后找了台实际机器搭建,还是不行。

在工作间隙和下班后,只要有时间,我就苦苦寻找可能性。各类操作系统,各类UDK,各版本Qemu和各版本windbg,组合起来起码也有20几种。

在我搭建这些环境的次数多到想吐,准备转到Linux下时,今天早上,竟然成功了!

冷静下来思考,发现自己有80%以上的工作,都是无用功。不过正如7个炊饼的故事一样,这些无用功才引导我尝试成功。收拾起心情,把这几天的无用功整理一下。

1 经验教训

我参考的文档主要来自UDK Debugger Tool的说明书,以及网上有位同行分享的博客。网址分别为:

https://firmware.intel.com/develop/intel-uefi-tools-and-utilities/intel-uefi-development-kit-debugger-tool
https://www.cnblogs.com/zhongts/p/5789686.html

另外,Ovmf的编译,在EDK的github上也能找到,网址就不再贴出了。

intel提供的调试工具版本为1.5,安装之前必须装好windbg。文档中使用的是WinDbg6.11.0001.404,我简单尝试了其他版本的windbg,之后就回到了文档建议的版本。

UDK2018是可以的,不一定非得UDK2010去编译。我的理解,只要SourceLevelDebugPkg的版本号高于0.85,就可以配合UDK Debugger tool v1.5工作。其版本号可以再dsc文件中查看,我的UDK2018中所用的版本号是0.95,工作得很好。

到了坑人的地方了:Qemu必须用0.13的版本!

我起码试了不下10个版本的Qemu,在上面的博客中,作者提醒过他用的是特定版本0.13,我并没有当回事。UDK Debugger Tool的文档中并没有特别提示此事,EDKII的文档中也没有相关内容。就是这个疏忽,让我折腾了整整一周!

开始搭建吧,我在实际机器上和虚拟机上都试过,都可以工作。用来示例的是虚拟机环境,主要软件配置为:Win10+VS2015+UDK2018,intel UDK Debugger Tool v1.5+Qemu 0.13.0,WinDbg6.11.0001.404,以及用来导入efi文件到img镜像的WinImage 8.0。

2 调试工具和Qemu安装

Windbg的安装比较简单,注意不要修改其安装的缺省路径,Intel UDK Debugger Tool(名字好长,就简称为Debugger吧,不会搞混就行了)会自动寻找它。 Debugger安装的时候,注意这个步骤,我们准备使用命名管道作为通信道路:

图1 安装UDK Debugger Tool

Debugger将搭建windbg与Qemu(实际应该是Ovmf)之间的通道,实现源码级的UEFI App/Driver调试。

Qemu的安装比较简单。不过,Qemu官网上,我没有找到0.13版本的软件。找起来确实麻烦,我把qemu和windbg放到百度云里了。

Qemu安装后,记得在系统Path中添加其目录。

图2 设定Qemu目录

3 编译OvmfPkg

我们需要一个Qemu支持的BIOS image,OvmfPkg就是为了实现这个目的而存在的。之前写的App,为了在TianoCore的模拟环境中运行,一般都是编译为32位的。因此,所需要的Ovmf镜像应该是32位的。根据需要,OvmfPkg 可以编译为32位或者64位。

32位的编译命令:
build -a IA32 OvmfPkg\OvmfPkgIa32.dsc -b NOOPT -D SOURCE_DEBUG_ENABLE
64位的编译命令:
build -a X64 OvmfPkg\OvmfPkgX64.dsc -b NOOPT -D SOURCE_DEBUG_ENABLE

编译出来的文件在\MyWorkspace\Build\OvmfIa32\NOOPT_VS2015x86\FV和\MyWorkspace\Build\OvmfX64\NOOPT_VS2015x86\FV下。

UDK2018集成得已经比较好了,需要注意的地方不多。主要是需要打开SOURCE_DEBUG_ENABLE的宏开关,使得镜像文件支持源码级调试。Debugger的文档中对此有很详细的说明,就不一一讨论了。

另外,在前面的博客《搭建环境3》中没有提到ASL工具的建立。编译的时候出错了,根据github上UDK2018搭建说明,找到asl的网址,下载软件并拷贝到相应目录,添加到Path中就可以了。

4 调试

1) 启动” Start WinDbg with Intel UDK Debugger Tool”,Debugger和windbg将会启动,如图:

图3 启动调试器

2) 把所需要的OVMF.fd文件以及其他镜像文件拷贝到同一个目录下(非必要,可以命令行指定各个文件,我主要是为了操作方便)。如图:

图4 准备调试需要的文件

其中,OVMF.fd是从32位编译的OvmfPkg中拷贝而来。

dos.img是我很久以前,为了开发Foxdisk而做的一个镜像文件,当时是为了在bochs中启动Dos而做的。Qemu本身也提供创建img的功能,可以按照帮助文档做一个。dos.img中是一个格式化为Fat32的硬盘,并且安装了DOS7.1。

lbdebug.img是一个软盘镜像,非常古老的东西了。里面也是个Dos启动盘,这次我们不需要使用它。

qemu-x86_64.bat是我从Qemnu 0.13的目录中拷贝过来的,并且根据自己的需要做了一些修改。注意看最后一行,指定了BIOS镜像,硬盘镜像以及串口的命名管道。

3) 一切就绪后,双击qemu-x86_64.bat,windbg很快就挂载上了:

图5 windbg第一次断点

输入’g’,windbg继续运行,同时会加载很多符号。

进入UEFI Shell中,FS0:为第一个硬盘,也是就我们之前指定的dos.img文件。

4) 调试UEFI app。

把之前显示PCX的例子拿来编译,注意指定TARGET = DEBUG。 将编译好的执行文件Luo2.efi拷贝至dos.img中。我是使用winimage来拷贝的:

图6 准备需要调试的执行文件

安装步骤3中的顺序,启动调试,进入UEFI Shell。执行Luo2.efi之前,Ctrl+Break中断执行,在windbg的命令行中下断点:bu Luo2!ShellAppMain,按’g’继续执行。

在UEFI shell中执行Luo2.efi,程序会被中断到指定位置,源码也会被调出:

图7 源代码级调试app

从图中可以看出,断点命中了。

开始调试的时候,我习惯性地给Luo2!UefiMain下断,始终命中不了。最后才发现是自己手误了,清除了这些断点后,才中断到我期望的地方。

5 一些小技巧

在尝试搭建调试环境时,文档翻来覆去地看,问题一个个解决。在这个过程中学会了一些小技巧,值得记录下来。

第一是Intel UDK debugger Tool的配置文件。在其开始菜单的软件目录下,有个”Change Configurations”的选项,打开后可以编辑SoftDebugger.ini,修改软件的配置文件。把这段加入:

[Debug]
Debug=1

这将启动对SourceLevelDebugPkg的版本检查。在调试UDK2010的时候,弹出图8的对话框,我才确定自己找对了方向。这是很好的调试信息,不知道为什么要隐藏起来。

图8 版本不对应的提示

第二是对命名管道的检查。最开始时,怎么都不成功。我看什么都有问题,也怀疑命名管道是不是创建成功,需要一个工具来检测。

我本想自己写个命名管道的枚举工具,但是似乎记得微软的Sysinternals工具集中提供了类似的工具。问了张佩,他告诉了我名字(感谢^_^):pipelist。我们调试的命名管道qemu_pipe_dbg是由qemu创建的,截图如下:

图9 pipelist

工具可以在微软的网站上下载:https://docs.microsoft.com/en-us/sysinternals/

6 细节未解

在安装调试环境的过程中,我下载了很多工具。比如在安装win7+vs2008+UDK2010的过程中,找不到Vs2008的完整版,只好用express版。发现编译工具中竟然少了ml.exe! 只好拷贝了之前环境中的软件过来,编译通过了。

类似这样的细节,实际上需要一个个去抠。大部分都是不需要深究的问题,解决了也就解决了,我记录在自己的有道云笔记上。不过有些问题还是值得研究一下。

我想象中需要深究的几个问题:

1) 只能支持Qemu0.13,到底是怎么回事?是因为Qemu后面的版本修改了什么,导致windbg无法挂上吗,还是Intel UDK Debugger Tool本身的原因?
2) 这种调试方式,似乎不能支持所有windbg的命令,虽然对我而言已经足够了,哪些命令不能支持,什么原因 ?
3) Intel UDK Debugger Tool的原理是什么,怎么通过命名管道让windbg跑起来的?windbg对此支持的机制是什么?
4) SourceLevelDebugPkg是如何运作的?之前串口读的问题没有解决,我觉得应该是使用Event,至于如何使用,从这个Pkg中估计能找到很多例子。

当然,还有其他很多各类问题,在后续的开发中慢慢学习吧。另外,也要找个时间,把Linux下的调试环境搭建起来。从intel网站上的时间来看,intel UDK debugger Tool的windows版更新时间为2015年,Linux版为2017年。看来Linux下的更新一些,也许BUG会少点。

这是之后的事情了,下篇开始,回到主干道上来,继续格UEFI APP和Option ROM。

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
文件在 X5 调试所需工具 下
工具不解释了,都是博客中所用过的工具。WinImage没有放入,因为是收费软件,可以到网上去下载。

80 total views, 1 views today

发表评论

电子邮件地址不会被公开。 必填项已用*标注