粗略察看一 下.pdb 文件,会发现在其起始位置存放的是这样一个字符串“Microsoft C/C++ program database 2.00”。可以看出 PDB 是 Program Database 的首字母缩写。在 MSDN 中或 Internet 上搜索一下有关 PDB 内部结构的信息,你会发现没有任何有用的信息,唯一例外的是,在 微软的基础知识文章中,微软申明此种格式是它有的(Microsoft Corporation, 2000d)。就连 Windows 的老大 Matt Pietrek 也承认:
“ PDB符 号 表 的 格 式 并 没 有 公 开 的 文 档 。( 就 连 我 也 不 知 道 其 确 切 的 格 式 , 唯 一 知 道 的 是,它会随着 Visual C++ 的 更 新 而 更 新 。)”( Pietrek 1997a )
或许,pdb 格式会随着 Visual C/C++一起更新,不过针对当前版本的 Windows 2000 我 可以确切的告诉你 PDB 符号文件的结构。这或许是首次公开的 PDB 格式文档。但首先,还 是让我们检查一下.dbg 和.pdb 文件是如何链接到一起的。
Windows 2000 的.dbg 文件的一个显著特性是:它们包含的数据很少,几乎可以忽略它 们的 CodeView子节。下面示例给出了 ntsokrnl.exe 的.dbg 文件所包含的整个 CodeView数据, 只有区区 32 字节。

Address | 00 01 02 03-04 05 06 07 : 08 09 0A 0B-0C 0D 0E 0F | 0123456789ABCDEF
---------|-------------------------:-------------------------|-----------------
00006590 | 4E 42 31 30-00 00 00 00 : 20 7D 23 38-54 00 00 00 | NB10.... }#8T...
000065A0 | 6E 74 6F 73-6B 72 6E 6C : 2E 70 64 62-00 00 00 00 | ntoskrnl.pdb...

通常,子节总是以一个 CV_HEADER 结构开始,该结构中包 含 CodeView 的版本标识。这一次,该版本标识是 NB10MSDN(Microsoft 2000a)没能告 诉我们有关这个特殊版本的更多信息: “ NB10 ,可执行文件的这一标识表示,其调试信息保存在独立的 PDB文件中。相应的格式还有NB09或NB11。”( MSDN Library—April 2000\Specifications\Technologies and Languages\Visual C++ 5.0 Symbolic Debug Information Specification\Debug Information Format )
我并不知道 NB11 格式的内部细节,不过 PDB 格式和前面讨论的 NB09 格式一样几乎 什么也没有。第一句话很明确的说明了为什么 NB10 数据块是如此的小。所有相关的信息都 被移到了独立的文件中了,因此这个 CodeView 子节的主要作用就是提供指向实际数据的链 接。如示例 1-8 所暗示的,在 ntoskrnl.pdb 文件中一定可以找到实际的符号信息。
CV_HEADER 结构是自解释的。其后的两个成员的偏移量分别为:0x8 和 0xC,它们的 名字分别为:dSignature 和 dAge,在.dbg 和.pdb 文件链接的过程中它们将扮演重要角色。 dSignature 是一个 32 位的 UNIX 风格的时间戳,它保存了调试信息构建的日期和时间(自 01-01-1970 以来逝去的秒数)。w2k_img.dll 提供了两个函数:imgTimeUnpack()和 imgTimePack()用来将 dSignature 和 Windows 风格的时间格式进行相互的转化。我还不是非 常清楚 dAge 成员的确切含义。目前知道的是:dAge 成员的初始值为 1,每次修改 PDB 数 据后其值就会增一。dSignature 和 dAge 共同构成一个 64 位的 ID,调试器可以使用它来验 证给定的 PDB 文件是否与它引用的.dbg 文件相匹配。PDB 文件在它的一个数据流中包含着 两个值的一个副本,因此调试器可以拒绝处理不相匹配的.dbg/.pdb 文件。
 
无论你何时遇到格式未知的数据结构,你应该做的第一件事就是使用十六进制 Dump 浏览器察看这些结构。本书附带的w2k_dump.exe可很好的完成这一工作。通过检查Windows 2000 PDB 文件,如 ntoskrnl.pdb 或 ntfs.pdb,你会发现这些文件拥有如下一些共同特性: 

  • 这些文件似乎都被划分为多个大小固定的块,一般情况下,每个块的大小为 0x400 字节。
  • 某些块包含一长串 1,但偶而会被一小段连续的 0 打断。
  • 文件中的信息并不必须是连续的。有时,数据会在块的边界处突然结束,但又会在 文件的其它地方继续开始。
  • 有些数据块会在文件中反复出现。

CodeView 的 NB10 子节 
typedef
struct _CV_NB10 //PDB reference{
CV_HEADER Header;
DWORD dSignature;
//seconds since 01-01-1970 DWORD dAge; //1++ BYTEabPdbName[];//zero-terminated} CV_NB10,*PCV_NB10, **PPCV_NB10;#define CV_NB10_ sizeof(CV_NB10)

标签: none

添加新评论