PDB 文件

2022-09-05 11:03:40 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

PDB 文件


什么是 PDB 文件

PDB (Program Data Base) 即程序的基本数据,是 VS 编译链接时生成的文件,每个程序集(EXEDLL)都有一个与之对应的 PDB 文件。DPB 文件主要存储了 VS 调试程序时所需要的基本信息,主要包括源文件名、变量名、函数名、对应的行号等等。因为存储的是调试信息,所以一般情况下 PDB 文件是在 Debug 模式下才会生成。有了这个文件,我们才能对程序进行 断点调试 ,才能一步步执行程序。

为了直观地展示 PDB 文件的内容,我们来做一个小实验。创建一个 WPF 程序(取名为 CrashMe),在主窗体中放置一个按钮,在按钮的 Click 事件处理方法中编写如下代码。由于 DataContext 为空,所以会弹出一个 MessageBox 来显示异常堆栈。

代码语言:javascript复制
private void CrashButton_OnClick(object sender, RoutedEventArgs e) { 
     try { 
     MessageBox.Show(new Window().DataContext.ToString()); } catch (Exception ex) { 
     MessageBox.Show(ex.StackTrace, "Exception"); } } 

如果将生成的 CrashMe.exeCrashMe.pdb 放一起,弹出的 MessageBox 内容如下左图所示;如果将 CrashMe.pdb 文件删除,内容如下右图所示。 对比两张图可以发现,带 CrashMe.pdb 的多了 文件位置代码行号,说明这些信息是记录在 pdb 文件中的。

PDB 文件中都包含哪些内容

通过上一小节的例子,大家对 PDB 文件有了大概的了解,知道其中存储了 代码行号 等信息。对于 托管程序非托管程序,其 PDB 文件中存储的信息不尽相同,由于 托管程序Metadata 已经存储了 类型定义函数签名 等信息,所以其 PDB 中的内容相对较少。

  • Native C PDB 包含的信息
    • publicprivatestatic 函数地址
    • 全局变量的名称和地址
    • 参数和局部变量的名称以及它们在栈中的偏移量
    • classstructure 和数据的类型定义
    • Frame Pointer Omission 数据,用来在 x86上的 native 堆栈的遍历
    • 源代码文件的名称和行号
  • .NET PDB 包含的信息
    • 源代码文件名称和行数
    • 局部变量的名称和行数

PDB 是非公开的文件格式,我们不能直接获取其中的内容,只能通过微软提供的 Debug Interface Access SDK 来访问其中的信息。

PDB 的唯一性和重要性

每个程序集(PE 文件,EXEDLL)都会有一个与之对应的 PDB 文件,并且每次编译生成的 PEPDB 文件都不同。编译器会生成一个 GUID 存储在 PEPDB 文件中,以此来映射 PE 文件和 PDB 文件。由于 PDB 文件具有唯一性,因此 PDB 文件和 PE 文件同等重要,一旦丢失就不能通过重新编译来获取。注意:即使是同一份代码,在同一台计算机上编译,每次的生成的 PDB 都是不同的,一定要保存好发布版本的 PDB 文件。

我们可以使用 DumpBin.exe 来从 PE 文件中获取 GUID 信息,在控制台中启动该程序,并传入 PDB文件/headers参数 即可。如下 部分控制台输出 所示,其中的 BBF232AA-7586-4659-B391-E19B0150E69F 即为此 PE 文件的 GUID 信息,另外还输出了与其对应的 PDB 文件的位置。

代码语言:javascript复制
D:CrashMebinDebug>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:UsersIronDesktopCrashMeobjDebugCrashMe.pdb
......

接下来找到对应的 PDB 文件,检查其中 GUID 信息是否与 PE 一致,推荐使用 PdbInspector 来查看 PDB 文件的内部信息。

调试工具会通过路径和名字来查找 PDB 文件, 还会通过上面的 GUID 来确定 PDB文件PE文件 是否真正匹配。 调试工具加载 PDB 文件的顺序:

  • PE 文件所在的路径
  • PEhardcode 记录的 build 目录,例如 objdebug*.pdb
  • 根据 symbol server 的设置,在本地的 symbol servercache 中查找
  • 远程的 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.cn/137008.html原文链接:https://javaforall.cn

0 人点赞