为什么 Windbg 的 pdb 文件校验和失败?

Why does the checksum fail for pdb files with Windbg?

我在 VS2015 中创建了一个模拟崩溃的简单控制台演示应用程序。我 运行 使用 windbg 的可执行文件来调试它以用于演示目的。应用程序 运行 并按预期崩溃。

但这是 windbg 很奇怪的时候。

我在同一台机器上构建时看不到调用堆栈函数对应的代码。调用堆栈旁边的源代码行不是源代码所在的位置,它几乎没有引用我的示例代码(单个 main.cpp 文件)。

0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 0036f7e8 77a18e12 ffffffff 00000000 00000000 ntdll!NtTerminateProcess+0x12
01 0036f804 756c79c4 00000000 77e8f3b0 ffffffff ntdll!RtlExitUserProcess+0x85
02 0036f818 0f4891b8 00000000 0036f840 0f48916c kernel32!ExitProcessStub+0x12
03 0036f824 0f48916c 00000000 0036f84c 0036f850 ucrtbased!exit_or_terminate_process+0x38 [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp @ 130]
04 0036f840 0f489452 00000000 00000000 00000000 ucrtbased!common_exit+0x5c [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp @ 265]
05 0036f854 00e42348 00000000 c0bb032f 00000000 ucrtbased!exit+0x12 [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp @ 278]
06 0036f8b0 00e421cd 0036f8c0 00e424e8 0036f8cc Project1!__scrt_common_main_seh+0x168 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 262]
07 0036f8b8 00e424e8 0036f8cc 756c336a 7efde000 Project1!__scrt_common_main+0xd [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 296]
08 0036f8c0 756c336a 7efde000 0036f90c 779f9902 Project1!wmainCRTStartup+0x8 [f:\dd\vctools\crt\vcstartup\src\startup\exe_wmain.cpp @ 17]
09 0036f8cc 779f9902 7efde000 7dbc800d 00000000 kernel32!BaseThreadInitThunk+0xe
0a 0036f90c 779f98d5 00e4134d 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
0b 0036f924 00000000 00e4134d 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b

当我运行lm Project1.exe时,它不理解Project1.exe

0:000> lm Project1.exe
Unknown option 'P'
Unknown option 'r'
Unknown option 'j'
                 ^ Syntax error in 'lm Project1.exe'

更有趣的是,当我执行 运行 lm 命令时,它在 Project1 模块旁边显示 C,这意味着校验和不匹配,但为什么呢?它是在同一台机器上构建的,符号文件应该 100% 匹配,但显然不是。

0:000> lm
start    end        module name
00e30000 00e51000   Project1 C (pdb symbols)          C:\Program Files (x86)\Windows Kits\Debuggers\x86\sym\Project1.pdbD98E9A3EDD4D4D8AE90DF76040737D1\Project1.pdb
0f000000 0f006000   detoured   (deferred)             
0f3d0000 0f546000   ucrtbased   (private pdb symbols)  C:\Program Files (x86)\Windows Kits\Debuggers\x86\sym\ucrtbased.pdb\D9FF3B7405474C158B4E3C2FBCC108362\ucrtbased.pdb

实际上它甚至没有为主要 Project1.exe 模块说 private pdb symbols 几乎就像找不到符号一样!?

校验和问题也反映在k命令中

0:000> k
 # ChildEBP RetAddr  
00 002df984 77a18e12 ntdll!NtTerminateProcess+0x12
01 002df9a0 756c79c4 ntdll!RtlExitUserProcess+0x85
02 002df9b4 608c91b8 kernel32!ExitProcessStub+0x12
03 002df9c0 608c916c ucrtbased!exit_or_terminate_process+0x38 [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp @ 130]
04 002df9dc 608c9452 ucrtbased!common_exit+0x5c [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp @ 265]
*** WARNING: Unable to verify checksum for Project1.exe
05 002df9f0 012a2348 ucrtbased!exit+0x12 [d:\rs1\minkernel\crts\ucrt\src\appcrt\startup\exit.cpp @ 278]
06 002dfa4c 012a21cd Project1!__scrt_common_main_seh+0x168 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 262]
07 002dfa54 012a24e8 Project1!__scrt_common_main+0xd [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 296]
08 002dfa5c 756c336a Project1!wmainCRTStartup+0x8 [f:\dd\vctools\crt\vcstartup\src\startup\exe_wmain.cpp @ 17]
09 002dfa68 779f9902 kernel32!BaseThreadInitThunk+0xe
0a 002dfaa8 779f98d5 ntdll!__RtlUserThreadStart+0x70
0b 002dfac0 00000000 ntdll!_RtlUserThreadStart+0x1b

当这个简单的项目在同一台机器上构建时,为什么 windbg 不能找到东西并且没有产生有意义的结果?

when I run lm Project1.exe, it doesn't understand Project1.exe

lm Project1.exe 命令失败有两个原因:

  1. 模块名称是 Project1 而不是 Project1.exe
  2. 该命令缺少另一个 m:lm m Project1

It actually doesn't even say private pdb symbols for the main Project1.exe module almost like it can't find the symbols!?

我认为这对于发布版本来说是正常的。隐私信息被剥离。

it shows C next to Project1 module which means checksum mismatched

关于校验和的C,帮助说:

The checksum is missing, not accessible, or equal to zero.

恕我直言,对于 PDB 的标识,时间戳足够可靠,不需要校验和。您可以使用 chkmatch 检查您的可执行文件是否与您的符号匹配。

我的 C# 程序在调试和发布版本中收到 C 警告,但我没有问题。

评论里你说:

I don't have even f:\dd folder on my system.

这可能是由链接器生成的。您使用静态链接,这会在您的可执行文件中嵌入一些 C++ 运行时内容,其中源代码由 Microsoft 编译。

还有人说:

It's loading the Project1 symbols from an unusual directory,

的确如此,但您的应用程序的符号可以存储在符号存储中,具体取决于符号路径配置。

参见 。在你的情况下应该是

.sympath C:\path\to\your\symbols
.symfix+ C:\microsoft\symbols
.reload

why can't windbg not able to find things

您希望找到什么?

and is not producing meaningful results?

输出的哪一部分对您没有意义?

您需要在项目中设置 /release 开关,以便将 chksum 设置为调试构建的默认值是 nochksum
发布 buikds 的默认值是 setchksum

Unable to verify checksum for exe

https://msdn.microsoft.com/en-us/library/h8ksa72a.aspx

要将 lm 与模块名称一起使用,您需要 -m 开关。

喜欢。 Lm -m pro*
您可以对 modname 使用通配符。 Windbg 将显示所有匹配模式的模块

的。 F:\dd 路径来自 crt 来源。它们在您的 vs src 文件夹中可用。因为它们是硬编码路径

您可能需要将 src 文件夹复制到本地计算机中的确切目录结构

Viz md f:\dd........\ 并将整个 src 文件夹复制到该路径。 Windbg 将选择来源

如果。你编译调试或发布你的 pdb 没有被剥离它们保持私有 pdb 除非你使用 pdbcopy 或 binplace 剥离私有符号

您的堆栈显示终止进程。它的意思是。通过您的用户代码,您可能需要手动打开源文件。使用。 Lsa ls 命令

从手机输入,所以我可能会进一步编辑以添加信息