Windows调试符号学习
符号文件包含大量二进制文件在运行时不需要的数据。
符号可以包括变量名称、类型(如果适用)、存储地址或寄存器以及任何父符号或子符号。 符号示例包括变量名(本地和全局)、函数以及模块的任何入口点。
调试器从位于本地文件系统的或从远程符号服务器加载的符号文件中获取其有关符号的信息。 (PS:使用符号服务器时,调试器将自动使用正确的符号文件版本来匹配目标中的模块。)
不同模式下需要的符号信息:
1. 执行用户模式调试,则需要目标应用程序的符号。
2. 执行内核模式调试,则需要要调试的驱动程序的符号以及 Windows 公共符号。
获取Windows 公共符号的方法:
直接引用符号路径中的公共符号服务器。在cmd使用以下命令:
set _NT_SYMBOL_PATH=srv*DownstreamStore*https://msdl.microsoft.com/download/symbols
将公共符号存储追加到现有的符号路径。在dbgcmd使用以下命令(其中"C:\MySymbols"为现有符号路径):
.symfix+ C:\MySymbols
符号文件的格式:Windows扩展名 .pdb或.dbg 的文件
当链接器生成完整大小的 .pdb 或 .dbg 符号文件时,它包含两个不同的信息集合:私有符号表和公共符号表。
私有符号和公共符号的区别:
1.私有符号数据包括以下项:
-
函数
-
全局变量
-
局部变量
-
有关用户定义的结构、类和数据类型的信息
-
源文件的名称以及该文件中对应于每个二进制指令的行号
2.公共符号数据包括以下项:
-
函数 (声明为静态函数的函数除外)
-
指定为外部 变量的全局 (以及多个对象文件上可见的任何其他全局变量)
这两个数据集合在每个项包含的信息方面也有所不同。
私有符号数据中包含的每个项,通常包含以下信息:
-
项的名称
-
虚拟内存中项的地址
-
每个变量、结构和函数的数据类型
-
每个函数的参数类型和名称
-
每个局部变量的范围
-
与每个源文件中每一行关联的符号
-
帧指针省略 (FPO) 用于访问堆栈的每个函数的 FPO 记录
公共 符号表仅包含每个项的以下信息:
-
项的名称。
-
项在其模块的虚拟内存空间中的地址。 对于函数,这是其入口点的地址。
-
帧指针省略 (FPO) 每个函数的记录。
-
可以包含作为修饰的 符号前缀/后缀。
可以通过两种方式将公共符号数据视为私有符号数据的子集:它包含较短的项列表,并且包含的关于每个项的信息也较少。 例如,公共符号数据完全不包含局部变量。
每个局部变量仅包含在专用符号数据中,及其地址、数据类型和范围。 另一方面,函数同时包含在私有符号数据和公共符号表中,但虽然私有符号数据包括函数名称、地址、FPO 记录、输入参数名称和类型以及输出类型,但公共符号表仅包括函数名称、地址和 FPO 记录。
私有符号数据和公共符号表之间还有一个区别: 公共符号表中的许多项具有用前缀和/或后缀修饰的名称。 这些修饰由 C 编译器、C++ 编译器和 MASM 汇编程序添加。 典型前缀包括一系列下划线或字符串__imp_ (指定导入的函数) 。 典型的后缀包括一个或多个@符号, () 后跟 @ 地址或其他标识字符串。
关于去除符号文件
去除符号文件是一个较小的文件,仅包含公共符号表,在某些情况下,仅包含公共符号表的子集。 此文件有时称为公共 符号文件。