UEFI开发探索27 – 用Vs2015建立UEFI调试环境

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

我使用AppPkg进行Uefi app和UEFI oprom的开发,这样很方便生成在实际硬件中运行的代码。

而在日常的开发调试,不可能有硬件环境,一般会使用UEFI中生成的模拟环境,其执行文件为SecMain.exe,是在Nt32Pkg中生成的。我一般是将生成文件拷贝到其同目录下,运行SecMain.exe,进入模拟UEFI Shell执行生成文件。

当然,调试的办法仍旧是使用Print()函数,打印出需要的信息。再加上一点点想象力,以及对代码的理解,解决遇到的问题。

网上找到的资料,大部分是以Nt32Pkg为例子搭建的环境来构建调试环境。很久以前我也曾经用VS2008搭建过,可以用来编译,调试则没有成功。当时项目时间比较紧,没有去深究,用古老的Print()大法进行调试,好歹是将项目完成了。

这几天在寻找建立UEFI调试环境的过程中,发现intel其实提供了调试工具,名为UDK Debugger Tool。配合windbg和Qemu,可以搭建完整的调试环境。看到windbg,我就被吸引住了。一直觉得自己用得不熟,正好借这个机会好好深入一下。

因此,我准备花点时间用windbg来搭建调试环境。

至于用VS2015自带的调试器,我个人觉得配合SecMain也是可以搭建起来的。在尝试的过程中发现了很多可能性,有些问题我还没有想到解决办法。估计会很花时间,我暂时放弃了。

不过经验难得,我把探索VS2015建立调试环境的过程记录下来了。

1 创建Makefile Project

第一步就遇到困难了。

具体来说,我使用VS2015 Community+UDK2018来进行开发。VS2015我用的是社区版,如图建立一个Makefile Project:

图1 创建Makefile Project

创建之后,遇到问题了。一般的VS2015 Enterprise,在建立Makefile Project之后,是这样的:

图2 VS2015 Enterprise – Makefile Project – Properties

而在我的VS2015 Community上创建的Makefile Project是这样的:

图3 VS2015 Community – Makefile Project – -Properties

我在微软的网站上找了很久,也没有找到一个说法,为什么社区版要把这个选项阉割掉?不过,IDE只是将很多配置文件可视化了,我们可以直接去修改配置文件。

这些修改选项一般都在*.vcxproj中。为了方便修改,在创建Makefile Project的时候,不要直接按Finish键,应该把Debug Configuration Settings的几个选项都填一下,包括Build command line、Clean commands和Rebuild command line。Release Configuration Settings与选择与Debug各项配制相同即可。

填什么都可以,主要是方便配置文件将这个选项对应的项建立起来,方便后续的修改。按照图中的示例,结合自己的开发环境,修改即可。具体可以看我放在百度云上的示例。

图4 修改配置文件

上述的配置是对NT32Pkg进行编译的,依次为Build、Clean和Rebuild,分别对应VS2015 IDE上的相应选项。

我的UDK中,target.txt中配置为编译AppPkg。所以上面的配置命令才写得这么详细,如果target.txt中本来就是为Nt32Pkg配置的,可以简化上面的命令。当然,如果只是希望针对某个module进行编译,可以用-m 命令指定相应的.inf文件。

直接选择”Build”命令,对代码进行编译。其结果与命令行编译的是一样的。

2 模拟环境下的调试

打开SecMain.c(C:\MyWorkspace\Nt32Pkg\Sec\)文件,在main函数中设定一个断点。 选择项目的Properties,对Debugging选项进行更改,如图所示。

图5 配置调试选项

注意,Working Directory的最后一个斜杠必须要保存,即必须是\IA32\,不能是\IA32。我尝试的时候没有注意,被这个小问题纠缠了一会。

F5启动调试,编SecMain.exe被启动了。程序将在指定位置中断,并定位到源代码上。

图6 TimDxe断点示意图

所有基于Nt32Pkg编译的代码,都可以用同样的方法定位。比如我在TimerDxe的函数CreateNtTimer上下断点,SecMain被中断后按”Continue”,程序将继续运行并中断到TimerDxe的CreateNtTimer上。如图:

3 AppPkg程序下断点

我开发的程序基本都在AppPkg下编译,上述的下断方法没有作用。

当然,如果进行汇编级别,而不是源代码级别的调试,还是可以的。主要步骤如下:

1) 在程序需要中断的地方加上嵌入式汇编代码: _asm int 3;
2) 代码编译成*.efi文件;
3) 将编译好的文件拷贝到上述SecMain.exe同一目录下;
4) 按上一节的方式,启动调试,调试目标仍旧为SecMain.exe;
5) F5进入调试状态,一直运行到UEFI Shell启动。运行需要调试的程序;
6) 程序将在指定位置中断,进入调试。

图中演示了中断的过程,我在Luo2.c的入口函数处加了中断,演示如下:

图7 Luo2.c(Display PCX示例用的代码)中断演示

这样就可以进行汇编级的调试了。

代码生成过程中,也生成了PDB文件。所以,我觉得理论上是可以进行源代码级的调试的。对VS的符号加载折腾了一番,没有成功。对PDB加载的原理,我还不是非常熟悉,只知道个大概。

如果想使用VS2015对AppPkg中生成的代码进行源代码级的调试,我估计要费不少精力和时间。

我还是想使用windbg来调试,VS的调试课题就暂时放一放吧,目前做到可以进行汇编调试就可以了。何况,以后也可以利用调试工具,一步步去跟踪Nt32Pkg的执行,解答我之前关于串口的疑惑,也算是一个比较大的进步了。

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
文件在 18 Debug-VS2015 Tools 下
/Nt32Debug.sln: Vs2015的工程文件,配置文件在./Nt32Debug中

2,722 total views, 1 views today

发表评论

电子邮件地址不会被公开。