符号文件

先不管什么是符号文件,先看看在没有符号文件支持时的情况,下面是VC8.0在没有符号文件支撑时的一个调用堆栈

>     DllTwo.dll!003d1cde()

      [下面的框架可能不正确和/或缺失,没有为 DllTwo.dll 加载符号]     

      MapTest.exe!004017f5()      

      MapTest.exe!00401169()     

      kernel32.dll!_BaseProcessStart@4()  + 0x23 字节   

下面是加载了PDB文件后的堆栈情况:

>     DllTwo.dll!CrashFun()  42 + 0x3 字节 C++

      MapTest.exe!wmain(int argc=1, wchar_t * * argv=0x00414c38)  17   C++

      MapTest.exe!__tmainCRTStartup()  594 + 0x17 字节  C

      kernel32.dll!_BaseProcessStart@4()  + 0x23 字节   

 

有没有发现最开始的稀奇古怪的十六进制符号都变成了函数名?这就是符号文件的魔力。

 

这里所说的“符号”就是“调试符号”,从软件调试的角度来讲,调试符号是将被调试的二进制程序和源程序联系起来的桥梁,很多重要的调试功能,例如源代码调试、栈回溯(如上表中的示例栈)、按名称显示函数或者变量名称等,都需要调试符号的支撑才能实现。

 

从编译器的角度来看,调试符号是编译器把源代码编译成二进制代码的过程中,为支持调试而摘录的调试信息,这些信息描述的目标对象主要包括:变量、变量类型、函数、标号(Label)、源代码行等。编译器或者其他专门的工具把这些信息收集提炼后输出到专门的文件中存储,这样的文件就是符号文件。

 

微软的编译器默认把这些符号信息保存在PDB文件中。PDB文件,是Program Database的缩写,从名字就知道,它专门用以描述(源)程序的数据库。其中的主要内容包括:

1)代码所定义Class的类名,类成员的名字和类型;

2 变量的名字和类型;

3 函数的名字,函数的所有参数的名字和类型以及返回值。

 

PDB文件是微软定义的一种格式,微软并没有公开此文件的格式,但是提供了一组接口来访问此文件,即DIAMicrosoft Debug Interface Acess)。下面是有人开发一个用来查看PDB文件内容的一个工具的截图:

符号文件 - 地线 - 别再让虚假消息充斥这本已混乱的世界

 

有了此PDB文件,当在调试器中试图读取某个内存地址的时候,调试器会尝试在对应的PDB文件中搜索,看这个内存地址是否有对应的符号。如果能够找到,调试器就会把这个符号显示出来,从而大大方便开发人员的调试。因此,在软件调试过程中,PDB文件是最为重要的信息,它比上面所说的map文件要重要的多。不过要使用PDB文件,需要专门的调试器的支持才行,例如VCWindbg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章