首页 > 其他分享 >学习笔记-PDB符号文件

学习笔记-PDB符号文件

时间:2022-11-05 15:14:54浏览次数:74  
标签:binary 路径 文件 符号 笔记 DEVPATH 模块 PDB

PDB符号文件


什么是 PDB 文件

  • PDB(Program Data Base),意即程序的基本数据,是 VS 编译链接时生成的文件。DPB 文件主要存储了 VS 调试程序时所需要的基本信息,主要包括源文件名、变量名、函数名、FPO(帧指针)、对应的行号等等。因为存储的是调试信息,所以一般情况下 PDB 文件是在 Debug 模式下才会生成。
  • PDB 文件是在我们编译工程的时候产生的,它是和对应的模块 (exe 或 dll) 一起生成出来的。pdb 文件包含了编译后程序指向源代码的位置信息,用于调试的时候定位到源代码,主要是用来方便调试的。

PDB 文件中记录了源文件路径的相关信息,所以在载入 PDB 文件的时候,就可以将相关调试信息与源码对应。这样可以可视化的实时查看调试时的函数调用、变量值等相关信息。模块当中记录的 PDB 文件是绝对路径。所以只要模块在当前电脑上载入,调试器自然地会根据模块当中的路径信息找到相应 PDB 文件并载入。同样 PDB 文件中记录的源文件路径也是绝对路径,所以 PDB 文件只要在当前电脑上载入,调试进入相应模块时,都能够匹配到记录的源文件,然后可视化地查看相应信息。

PDB 文件的调用过程

模块 (Module),EXE 和 DLL 都可以称之为模块,因为它们都有自已独立的 Stack,所以我们在调试程序时,可以在 Call Stack 窗口查看到所有调用的 Module Name。并且可以右键查看相应模块的 ybmol Load Information,即该模块调用的 PDB 文件路径的过程。

每个模块被载入的时候,其相同名字的 PDB 文件同时被载入。所以 Debug 模式下,不仅因为代码没有优化,同时因为要载入 PDB 文件,所以 Debug 模式下的程序执行速度非常慢。

每个模块只会生成一个相同名字的 PDB 文件,并且模块生成的同时,会校验 PDB 文件生成 GUID 记录在模块内。这是因为调试时,调试器强制要求每个模块必须和 PDB 文件保持一致。实验过程中,用之前生成的 PDB 文件替换当前生成的 PDB 文件时,Debug 窗口会显示 No symbols loaded. MSDN 也做了相应的说明:The debugger will load only a PDB for a binary that exactly matches the PDB that was created when the binary was built.

PDB 文件存储格式

PDB 的文件格式类似于磁盘的文件系统,每个磁盘会被划分成很多个大小一样的扇区,文件中的数据就存放在不同的扇区中,而且无需保证这些扇区在磁盘上是连续的。PDB 文件用 page 进行划分,类似于扇区,stream 就类似于文件,stream directory 类似于文件目录。

PDB 文件的内容

PDB 不是公开的文件格式,但是 Microsoft 提供了 API 来帮助从 PDB 中获取数据。

Native C++ PDB 包含了如下的信息:

  • public,private 和 static 函数地址;
  • 全局变量的名字和地址;
  • 参数和局部变量的名字和在堆栈的偏移量;
  • class,structure 和数据的类型定义;
  • Frame Pointer Omission 数据,用来在 x86 上的 native 堆栈的遍历;
  • 源代码文件的名字和行数;

.NET PDB 只包含了 2 部分信息:

  • 源代码文件名字和行数;
  • 和局部变量的名字;
  • 所有的其他的数据都已经包含在了. NET Metadata 中了;

PDB 文件的查找策略

  1. 文件被执行或者被载入的地址
  2. 就是硬编码在 PE 文件头中的那个地址。
  3. 如果配置了符号服务器,第二步以后应该先去符号服务器的缓存目录下找,如果找不到再去符号服务器上去找。找到的话就会下载到缓存目录。
  4. VS 中设置的一些符号查询的目录
  5. c:\Windows 文件夹。

PDB 如何工作

当你加载一个模块到进程的地址空间的时候,debugger 用 2 种信息来找到相应的 PDB 文件。

  • 一种是文件的名字,如果加载 zzz.dll,debugger 则查找 zzz.pdb 文件。
  • 在文件名字相同的情况下 debugger 还通过嵌入到 PDB 和 binay 的 GUID 来确保 PDB 和 binay 的真正的匹配。所以即使没有任何的代码修改,昨天的 binay 和今天的 PDB 是不能匹配的。可以使用 dempbin.exe 来查看 binary 的 GUID。

在 VisualStudio 中的 modules 窗口的 symbol file 列可以查看 PDB 的 load 顺序。第一个搜索的路径是 binary 所在的路径,如果不在 binary 所在的路径,则查找 binary 中 hardcode 记录的 build 目录,例如 obj\debug*.pdb, 如果以上两个路径都没有找到 PDB,则根据 symbol server 的设置,在本地的 symbol server 的 cache 中查找,如果在本地的 symbol server 的 cache 中没有对应的 PDB,则最后才到远程的 symbol server 中查找。通过上面的查找顺序我们可以看出为什么 PDB 查找不会冲突。

对于有时我们需要在别人的机器上 debug 的情况,需要将相应的 PDB 与 binary 一起拷贝,对于加入 GAC 的. NET 的 binary,需要将 PDB 文件拷贝到 C:\Windows\assembly\GAC_MSIL\Example\1.0.0.0__682bc775ff82796a 类似的 binary 所在的目录。另一个变通的方法是定义环境变量 DEVPATH,从而代替使用命令 GACUTIL 将 binary 放入 GAC 中。在定义 DEVPATH 后,只需要将 binary 和 PDB 放到 DEVPATH 的路径,在 DEVPATH 下的 binary 相当于在 GAC 下。使用 DEVPATH,首先需要创建目录且对当前 build 用户有写权限,然后创建环境变量 DEVPATH 且值为刚才创建的目录,然后在 web.config,app.config 或 machine.config 中开启 development 模式,启动对 DEVPATH 的使用

<configuration>
   <runtime>
      <developmentMode developerInstallation="true"/>
   </runtime>
</configuration>

在你打开了 development 模式后,如果 DEVPATH 没有定义或路径不存在的话会导致程序启动时异常 "Invalid value for registry"。而且如果在 machine.config 中开启 DEVPATH 的使用会影响其他的所有的程序,所以要慎重使用 machine.config。

最后开发人员需要知道的是源代码信息是如何存储在 PDB 文件中的。

  • 对于开发人员自己机器上生成的 build,在运行 source indexing tool 后,版本控制工具将代码存储到你设置的代码 cache 中。
  • 对于在公用的 build 机器上生成的 build,只是存储了 PDB 文件的全路径,例如在 c:\foo 下的源文件 mycode.cpp,在 pdb 文件中存储的路径为 c:\foo\mycode.cpp。使用虚拟盘来增加 PDB 对绝对路径的依赖,例如可以使用 subst.exe 将源代码路径挂载为 V:,在别人的机器上 debug 的时候也挂载 V:。

如何查看二进制文件和 PDB 的 GUID


Source & Reference

点击关注,共同学习!
安全狗的自我修养

github haidragon

https://github.com/haidragon

标签:binary,路径,文件,符号,笔记,DEVPATH,模块,PDB
From: https://www.cnblogs.com/haidragon/p/16860212.html

相关文章

  • 学习笔记-IPC$(Internet Process Connection)
    IPC$(InternetProcessConnection)IPC$的概念IPC$(InternetProcessConnection)是共享"命名管道"的资源,它是为了让进程间通信而开放的命名管道,可以通过验证用户名......
  • 第十周学习笔记
    第12章  块设备I/O和缓冲区管理一、主要内容1.块设备I/O缓冲区与内存访问相比,磁盘I/O速度较慢,所以不希望在每次执行读写文件操作时都执行磁盘I/O。因此,大多数文件系......
  • 学习笔记-WinRM
    WinRM什么是WinRMWindows远程管理(WinRM)是WS-ManagementProtocol的Microsoft实现。WS-Management协议是一种基于SOAP的防火墙友好协议,旨在用于系统查找和交换......
  • 学习笔记-Secure-Win
    Secure-Winwindows加固+维护+应急响应参考大纲文件可疑文件系统开机启动账号进程注册表日志系统日志日志工具第三方程序日志网络端口......
  • 学习笔记-PowerShell 笔记
    PowerShell笔记什么是PowerShellWindowsPowerShell是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用.NETFramework的强大功能.WindowsPowerS......
  • 学习笔记-Speed-Win
    Speed-Win大纲基础使用环境变量符号会话文件和目录查看创建删除查询修改链接网络管理IPC$查看网络信息网络排错工具RDP防火墙系统管......
  • SystemVerilog 中的 有符号比较 和 无符号比较
    当比较双方都是有符号时候,比较为有符号比较当有一方是无符号比较时,则是无符号比较可以使用$signed()来强制转换为有符号数答案来源:https://stackoverflow.com/questi......
  • 学习笔记- 角色权限
    角色权限用户帐户在Windowsvista或是windows7中,有两个级别的用户:标准用户和管理员.标准用户是计算机Users组的成员;管理员是计算机Administrators组的成员......
  • 学习笔记-内存管理
    内存管理注:笔记中拓扑图drawio源文件在其图片目录下更多内存相关知识点可见内存笔记Windows内存管理可概括为三大机制:虚拟地址空间管理;物理页面管理;......
  • 学习笔记-凭据
    凭据简介CredentialManager,中文翻译为凭据管理器,用来存储凭据(例如网站登录和主机远程连接的用户名密码)如果用户选择存储凭据,那么当用户再次使用对应的操作,系统......