在X64位机器上捕捉32位程序的进程的内存镜像文件要点

X64位机器上捕捉32位程序的进程的内存镜像文件要点

Capturing memory dumps for 32-bit processes on an x64 machine

                                                翻译:Baal Lin

                        我们经常会遇到的一类问题是,很多人在做内存镜像文件抓取的时候,需要重新的来抓一次,第一次往往不会成功,那是因为我们使用了“错误”的方法来抓取,从而导致了失败。

                故事场景是这样:如果在一个x64系统上运行一个x32位的程序,例如在x64位系统上运行的IIS为例,我们需要一个能抓取到32位进程的内存镜像文件的工作,而不是简单的拿一个调试工具双击来运行,你要确保的是了解该工具是否能在32 64位环境下正确工作。

如何知道一个进程是32位的?

如果你在一个64位的系统上,你可以通过任务管理器来查看某个进程是32位还是64位。

那些带有*32 字样的进程是32位程序的进程,其余的都是64位的。所以我们从图上可以看到w3wp.exe是一个32位进程。

为什么要用正确的工具来抓取那些进程?

如果你用一个抓取64位进程内存镜像文件的工具来抓取32位进程的内存镜像,你仍然会得到一个内存镜像文件,但你得到的是一个64位地址空间的镜像文件,但sospsscor2工具都无法正确的解析,部分的功能还是会有效,但功能会限制,它可能会报很多错误,或者返回一个错误的堆栈。

                通常,如果读取一个32位进程的64位内存镜像文件,你会得到一些类似下面的错误:       

                1、类似下面的警告:

 WARNING: wkscli overlaps srvcli

 ..............WARNING: wship6 overlaps dnsapi

 .WARNING: IPHLPAPI overlaps dsrole

 ...WARNING: FWPUCLNT overlaps rasadhlp

 WARNING: FWPUCLNT overlaps dnsapi

 .....WARNING: compstat overlaps iisres

                2、堆栈显示64位进程的方法,带有wow64cpu

0:000> kp 
   Child-SP          RetAddr           Call Site 
   00000000`000ce728 00000000`73a22bcd wow64cpu!CpupSyscallStub+0x9 
   00000000`000ce730 00000000`73a9d07e wow64cpu!Thunk0ArgReloadState+0x1a 
   00000000`000ce7f0 00000000`73a9c549 wow64!RunCpuSimulation+0xa 
   00000000`000ce840 00000000`76d684c8 wow64!Wow64LdrpInitialize+0x429 
   00000000`000ced90 00000000`76d67623 ntdll!LdrpInitializeProcess+0x17e2 
   00000000`000cf290 00000000`76d5308e ntdll! ?? ::FNODOBFM::`string'+0x2bea0 
   00000000`000cf300 00000000`00000000 ntdll!LdrInitializeThunk+0xe

 

                3、可以看到所有的地址都是64位长度的,例如00000000`76d5308e 而不是 76d5308e,虽然是32位的进程,但依然用64位空间地址来表示。

                4、当用sos命令时,提示下面的错误信息:(如果使用了错误的symbol文件,也有可能得到类似的信息,导致如下信息的错误原因不仅仅是因为本文主题所讲的原因)

0:000> !eeheap -gc

Failed to load data access DLL, 0x80004005

Verify that 1) you have a recent build of the debugger (6.2.14 or newer) 2) the file mscordacwks.dll       

你可以使用 .cordll命令来控制调试器来加载mscordacwks.dll 命令:.cordll –ve –u –l 会进行一个冗长的加载过程。如果成功,sos命令会尝试重新工作。如果你抓取的是精简镜像文件,要确保可执行路径指向clr.dll路径。

应该使用什么工具?

在这类场景中,最好的抓取进程内存镜像文件的方式是使用32位的调试工具,例如32位的Debug Diag 或者32位的adplus+cdb。可以在64位系统上安装32位的工具,在下一个版本的Debug Diag中,64位的Debug Diag可以抓取32位进程的内存镜像文件。

以前曾今提到过,在Vista系统以上的版本,可以通过任务管理器来抓取内存镜像文件,但是如果是在64位的系统上,用任务管理器来抓取的话得到的还是一个64位的内存镜像文件。可以使用32位的任务管理器来抓取,位置是C:\Windows\SysWOW64\taskmgr.exe ,可以通过在任务管理器中检查taskmgr.exe 进程是否带有*32标记来判断该进程是否是32位的。

对于其他第三方的工具,你也首先阅读帮助文档来确认是否是32位版本。例如procmon 可以在后面带上 /run32参数。

让调试器用正确的“位”来加载内存镜像文件重要吗?

                当然重要,无论是在32位或者64os系统上,当加载32位的内存镜像,你必须用32位的windbg,针对64位的内存镜像,当然是在运行64位的os上用64位的windbg来抓取,(32位系统上,抓取不到64位内存镜像文件哦)。

                记住,如果在调试一个64位内存镜像文件,你也必须保证组成该调试工具各个部分,例如64位的sos64位的psscor264位的sosex或其他64位的扩展工具都是64位版本的。

 

 

 

原文地址:http://blogs.msdn.com/b/tess/archive/2010/09/29/capturing-memory-dumps-for-32-bit-processes-on-an-x64-machine.aspx

 

posted @ 2011-01-20 20:24  softfair  阅读(3449)  评论(0编辑  收藏  举报