在windbg

时间:2016-04-12 20:28:08

标签: windows debugging windbg stack-trace symbols

我在Windows 10主机上安装了一台虚拟Windows 7 x64计算机,并使用windbg 10.0.10586.567对内核进行调试。我正在运行我自己的应用程序,我有完整的源代码和私有符号。每当我闯入并询问应用程序线程的堆栈跟踪时,当我的应用程序的某个二进制文件被击中时,回溯始终会停止。"

所以,例如,如果我闯入,切换到进程,并请求带有!thread [thread address] 1f的堆栈跟踪,我得到类似的东西(注意"早期"最后的零返回地址线):

fffff880`0534e870 fffff800`026d6992 nt!KiSwapContext+0x7a
fffff880`0534e9b0 fffff800`026d81a2 nt!KiCommitThreadWait+0x1d2
fffff880`0534ea40 fffff800`029c7a2e nt!KeDelayExecutionThread+0x186
fffff880`0534eab0 fffff800`026d08d3 nt!NtDelayExecution+0x59
fffff880`0534eae0 00000000`76e7165a nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffff880`0534eae0)
00000000`00276708 000007fe`fcf91203 ntdll!NtDelayExecution+0xa
00000000`00276710 00000001`410e7dd9 KERNELBASE!SleepEx+0xab
00000000`002767b0 00000000`00000000 MyApp!MainMessageLoop+0x4b1 [d:\whatever\path\myapplication.cpp @ 3024]

这看起来非常类似于在调试x64进程的用户模式转储(缺少展开数据)时缺少二进制文件,除非在这种情况下堆栈跟踪通常不会停止"这突然& #34;相反,它在那一点上误入歧途,并显示出虚假的价值。

我尝试了一些额外的信息/事情:

  • 我设置了正确的符号路径(Microsoft符号服务器和主机上具有匹配PDB的本地文件夹,即使堆栈跟踪不需要后者)
  • 我有一个二进制路径设置(.exepath),在主机上包含匹配的二进制文件(我已经完全确定了这一点;将二进制文件直接从guest虚拟机复制到主机)
  • 如果我在应用程序的某个导出的DLL函数中放置了一个断点,那么当调试器中断时,我会得到一个像这样的单行堆栈跟踪:0000000000274b40 0000000000000000 MyAppDLL!SomeExportedFunction+0x32 [d:\whatever\path\myapplicationDLL.cpp @ 232]
  • 我已经尝试了几乎所有命令组合来获取堆栈跟踪(.process /i.process /r /p!process -1 7.reload s,.reload /user s ,.reload /f MyApp.exe!thread [address] 1f等)没有成功
  • 尝试使用旧版本的windbg(6.11.0001.404),结果相同
  • 也尝试在Windows 8.1上作为具有相同二进制文件的访客,结果相同
  • !sym noisy输出(省略不相关的行):

    0: kd>.process /i [address] 0: kd>g 0: kd>.reload /user 0: kd> !process -1 2 0: kd> !thread [address] 1f [...] DBGHELP: d:\symbolcache\MyApp.pdb\76931C5A6C284779AD2F916CA324617E1\MyApp.pdb already cached DBGHELP: MyApp - private symbols & lines [...]

  • lmvm MyApp输出:

    [...] Loaded symbol image file: MyApp.exe Image path: C:\MyApp\MyApp.exe [...]

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

我偶然发现了一个解决了这个问题的链接器开关:/DEBUGTYPE带有PDATA参数。如果您将二进制文件与此开关链接,则展开信息将被复制到您的PDB中。

我使用/DEBUGTYPE:CV,PDATA重新编译/重新链接了相关应用程序(如果指定/DEBUGTYPE:CV/DEBUG是默认设置,请参阅documentation),现在一切都像魅力一样,我总是得到完整的调用栈。

这有一个奇怪的方面:windbg愉快地使用在PDB中找到的展开数据,但忽略了映射二进制文件中的相同数据(两者都在主机上)。

答案 1 :(得分:2)

这不是问题的完美解决方案(或任何解决方案,有人可能会说),但我提供了这个临时答案的解决方法。

您应该能够获得所需的信息,尽管使用dps @rsp L10之类的格式不是很好。

在x86-64中,您没有x86 ebp链的并行,但返回地址仍在堆栈中。这些将为您提供堆栈中的函数,它们之间的值将是传递给函数的参数(以及堆栈中保存的寄存器等)。一个random example from Google(因为我现在不在我的Windows机器上):

0:017> dps @rsp
00000000`1bb0fbb8  00000000`00000020
00000000`1bb0fbc0  00000000`00000000
00000000`1bb0fbc8  00000000`008bc6c6 Dolphin!ReadDataFromFifoOnCPU+0xb6 [d:\sources\comex\source\core\videocommon\fifo.cpp @ 245]
00000000`1bb0fbd0  00000000`1ba0ffeb
00000000`1bb0fbd8  00000000`00000020
00000000`1bb0fbe0  00000000`00000020
00000000`1bb0fbe8  00000000`00000800
00000000`1bb0fbf0  00000000`1ba0ffeb
00000000`1bb0fbf8  00000000`008c2ff5 Dolphin!InterpretDisplayListPreprocess+0x45 [d:\sources\comex\source\core\videocommon\opcodedecoding.cpp @ 87]
00000000`1bb0fc00  00000000`00000000
00000000`1bb0fc08  00000000`008bc041 Dolphin!RunGpu+0x81 [d:\sources\comex\source\core\videocommon\fifo.cpp @ 389]
00000000`1bb0fc10  00000000`8064cbc0
00000000`1bb0fc18  00000000`1bb0fcc0
00000000`1bb0fc20  00000000`00000000
00000000`1bb0fc28  00000000`008c2dda Dolphin!OpcodeDecoder_Preprocess+0x14a [d:\sources\comex\source\core\videocommon\opcodedecoding.cpp @ 326]
00000000`1bb0fc30  00000000`8064cbe0

鉴于您有符号,返回地址很容易区分。

答案 2 :(得分:2)

展开数据是为用户模式模块延迟加载的,因此除非有人需要,否则不会映射它。不幸的是,内核调试器并不强制为用户图像提供信息,因此有时您会遇到此行为。您可以通过转储PE头(!dh)并检查异常目录的状态(!pte imagename + offset)来查看数据是否已映射。

鉴于您拥有该应用程序,请尝试通过在应用程序中的某处执行堆栈遍历NOP来强制信息驻留:

PVOID stack[2];
(VOID)CaptureStackBackTrace(0, 2, (PVOID*)&stack, NULL);

这并不能保证整个目录都存在,但通常足够好。