如果你还不清楚什么是转储文件,不知道什么时候需要转储文件,请参考转储文件系列文章的第一篇 —— 转储文件知多少。
前言
细心的小伙伴可能注意到了,我在上一篇介绍抓取转储文件的工具的文章 —— 你需要知道的 N 种抓取 dump 的工具 中提到了:
如果用
64
位的windbg
附加到32
位目标进程后,直接执行.dump
命令生成的转储文件会 “有问题”。
经常抓 dump
的小伙伴很可能遇到过这个问题。具体是什么问题呢?我们一起看看吧。
问题
还记得 N
年前,我用任务管理器抓取 32
位进程的转储文件后,使用 windbg
分析时,傻眼了!全是wow64
相关的栈帧,一个我关心的栈帧都没有。大概就像下图这样。(配图是我新截的,第一次分析时没保存截图)
我所指的 “有问题”,就是指的这个问题。你知道怎么解决吗?
小知识
在 x64
系统中,如果我们用系统自带的任务管理器为目标进程创建转储文件,不论目标进程是 32
位,还是 64
位,任务管理器将始终创建 64
位的转储文件。为 32
位进程创建的转储文件会包含 WoW64
子系统的信息,我们用 windbg
分析的时候,可能会遇到上文中提到的问题。下面是同一个 32
位进程的转储文件的调用栈截图。
第一张截图是直接使用 k
命令得到的结果。可以看到很诡异。
第二张截图是使用 .load
命令加载 wow64exts
扩展后,使用其 !sw
命令切换模式后,再使用 k
命令得到的结果。可以看到,结果很完美。
对,wow64exts
是我们的解决之道。如果你像曾经的我一样,不知道使用 wow64exts!sw
命令切换模式进行调试的话,是不是就 “有问题” 了?每次都手动加载 wow64exts
,然后用 !sw
命令切换模式岂不是很麻烦?我们可以在加载 wow64exts
模块后,直接使用 !wow64exts.k
查看调用栈,这里就不截图了。还有更省心的办法吗?如果用 k
命令能直接看到想看的调用栈岂不是更好?有,不过我们抓取转储文件的时候需要有讲究。
2020-01-11 更新:
群里大佬提醒,也可以使用 .effmach
命令来查看或切换调试器使用的处理器模式。我们可以使用 .effmach x86
来强制切换到 x86
模式下,然后再执行 k
命令。效果和 .load wow64exts; !sw; k
一样。 大家可以试一下。关于 .effmach
的帮助,请参考微软官方文档,或者直接参考下面的截图。
procdump
在 x64
位系统下,procdump
默认对 32
进程创建 32
位的转储文件。这样做的好处是,生成的转储文件中不包含 WOW64
子系统的相关信息。我们用 windbg
分析转储文件时,可以直接使用 k
系列命令查看调用栈,不需要借助 wow64exts
的帮助了,这样调试起来更简单直接。
为了更直观的感受 procdump
的好处,我专门录制了两段视频。第一段是使用 windbg
分析 procdump
为 32
位进程生成的转储文件,第二段是使用 windbg
分析任务管理器为同一个 32
位进程生成的转储文件。
相信大家可以直观的感受到,调试 procdump
生成的转储文件的时候,非常直接。调试任务管理器生成的转储文件的时候,需要借助 wow64exts
的帮助才可以看到正常的调用栈。
说明:
使用 procdump
默认选项生成的转储文件中不包含 WoW64
相关的信息。如果需要调试涉及 WoW64
子系统的故障,可以在运行 procdump
的时候加上 -64
选项,这样为 32
位进程生成的转储文件就包含 WoW64
子系统的信息了。我们绝大多数情况下不会调试 WoW64
子系统相关的故障,所以就使用默认选项吧。
总结
在
windbg
中,使用!
来调用扩展中的命令。使用
procdump
默认选项为32
位进程生成的转储文件不包含WoW64
信息,绝大多数情况下更便于我们调试。如果需要,在使用
procdump
抓取转储文件时,我们可以使用-64
选项为32
位进程抓取包含Wow64
相关信息的转储文件。调试包含
WoW64
信息的转储文件,可以使用.load
命令加载wow64exts
模块,并调用其!sw
命令切换模式,然后就可以正常调试了。直接使用
.effmach
命令可以显示当前的处理器模式,.effmach x86 | x64
可以显示切换模式。
参考资料
《Windows Sysinternals 实战指南》