大家好,又见面了,我是你们的朋友全栈君。
PDB 文件
什么是 PDB 文件
PDB (Program Data Base) 即程序的基本数据,是 VS 编译链接时生成的文件,每个程序集(EXE 或 DLL)都有一个与之对应的 PDB 文件。DPB 文件主要存储了 VS 调试程序时所需要的基本信息,主要包括源文件名、变量名、函数名、对应的行号等等。因为存储的是调试信息,所以一般情况下 PDB 文件是在 Debug 模式下才会生成。有了这个文件,我们才能对程序进行 断点调试 ,才能一步步执行程序。
为了直观地展示 PDB 文件的内容,我们来做一个小实验。创建一个 WPF 程序(取名为 CrashMe),在主窗体中放置一个按钮,在按钮的 Click 事件处理方法中编写如下代码。由于 DataContext 为空,所以会弹出一个 MessageBox 来显示异常堆栈。
private void CrashButton_OnClick(object sender, RoutedEventArgs e) {
try {
MessageBox.Show(new Window().DataContext.ToString()); } catch (Exception ex) {
MessageBox.Show(ex.StackTrace, "Exception"); } }
如果将生成的 CrashMe.exe 和 CrashMe.pdb 放一起,弹出的 MessageBox 内容如下左图所示;如果将 CrashMe.pdb 文件删除,内容如下右图所示。
对比两张图可以发现,带 CrashMe.pdb 的多了 文件位置 和 代码行号,说明这些信息是记录在 pdb 文件中的。


PDB 文件中都包含哪些内容
通过上一小节的例子,大家对 PDB 文件有了大概的了解,知道其中存储了 代码行号 等信息。对于 托管程序 和 非托管程序,其 PDB 文件中存储的信息不尽相同,由于 托管程序 的 Metadata 已经存储了 类型定义、函数签名 等信息,所以其 PDB 中的内容相对较少。
Native C++ PDB包含的信息public、private和static函数地址- 全局变量的名称和地址
- 参数和局部变量的名称以及它们在栈中的偏移量
class、structure和数据的类型定义Frame Pointer Omission数据,用来在x86上的native堆栈的遍历- 源代码文件的名称和行号
.NET PDB包含的信息- 源代码文件名称和行数
- 局部变量的名称和行数
PDB 是非公开的文件格式,我们不能直接获取其中的内容,只能通过微软提供的 Debug Interface Access SDK 来访问其中的信息。
PDB 的唯一性和重要性
每个程序集(PE 文件,EXE 或 DLL)都会有一个与之对应的 PDB 文件,并且每次编译生成的 PE\PDB 文件都不同。编译器会生成一个 GUID 存储在 PE\PDB 文件中,以此来映射 PE 文件和 PDB 文件。由于 PDB 文件具有唯一性,因此 PDB 文件和 PE 文件同等重要,一旦丢失就不能通过重新编译来获取。注意:即使是同一份代码,在同一台计算机上编译,每次的生成的 PDB 都是不同的,一定要保存好发布版本的 PDB 文件。

我们可以使用 DumpBin.exe 来从 PE 文件中获取 GUID 信息,在控制台中启动该程序,并传入 PDB文件 和 /headers参数 即可。如下 部分控制台输出 所示,其中的 BBF232AA-7586-4659-B391-E19B0150E69F 即为此 PE 文件的 GUID 信息,另外还输出了与其对应的 PDB 文件的位置。
D:\CrashMe\bin\Debug>dumpbin.exe CrashMe.exe /headers
.....
Debug Directories
Time Type Size RVA Pointer
-------- ------- -------- -------- --------
5AC1F73B cv 11C 00003838 1A38 Format: RSDS, {BBF232AA-7586-4659-B391-E19B0150E69F}, 1, C:\Users\Iron\Desktop\CrashMe\obj\Debug\CrashMe.pdb
......
接下来找到对应的 PDB 文件,检查其中 GUID 信息是否与 PE 一致,推荐使用 PdbInspector 来查看 PDB 文件的内部信息。

调试工具会通过路径和名字来查找 PDB 文件, 还会通过上面的 GUID 来确定 PDB文件 和 PE文件 是否真正匹配。
调试工具加载 PDB 文件的顺序:
PE文件所在的路径PE中hardcode记录的build目录,例如obj\debug\*.pdb- 根据
symbol server的设置,在本地的symbol server的cache中查找 - 远程的
symbol server中查找
参考资料
- PDB文件详解 – CSDN
- PDB Files: What Every Developer Must Know
- DUMPBIN Reference – MS
- How to Inspect the Content of a Program Database (PDB) File – CodeProject
- Symbols File Locator – CodeProject
- Converting a managed PDB into a XML file – MSDN
- Microsoft/microsoft-pdb – GitHub
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/137008.html原文链接:https://javaforall.net
