分类 调试 下的文章

.dump (Create Dump File)

.dump命令创建一个用户模式或内核模式崩溃转储文件。

语法

.dump Options FileName 
.dump /? 

参数

Options
指定下面这些选项的一个或多个。
/o
覆盖具有相同名字的dump文件。如果没有使用该选项又存在一个相同名字的文件,则dump文件不会被写入。
/f
(内核模式:) 创建一个完整内存dump。

 (用户模式:) 创建一个完整用户模式dump。不管怎么称呼,最大的minidump文件实际比完整用户模式dump文件包含更多信息。例如,.dump /mf.dump /ma会创建比.dump /f创建更大更完整的文件。在用户模式下,.dump
/m
[MiniOptions] 总是比.dump /f更可取。

/m[MiniOptions]
创建一个小内存dump(内核模式)或者
minidump
(用户模式)。如果没有指定/f/m/m
是默认选项。

用户模式下,/m 后面可以跟附加的MiniOptions
用来指定dump文件中包含的数据。如果没有使用MiniOptions
,dump文件包含模块、线程和调用堆栈信息,但是没有其他附加信息。可以使用下面的任意MiniOptions
来改变dump文件的内容,它们区分大小写。


MiniOption作用
a 创建一个包含所有附加选项的minidump。/ma选项相当于/mfFhut
—它会在minidump中添加完整的内存数据、句柄数据、已卸载模块信息、基本内存信息和线程时间信息。
f 在minidump中包含完整内存数据。目标程序拥有的所有 可访问的已交付的页面(committed pages)都会包含进去。
F 在minidump中添加所有基本内存信息。这会将一个流加入到包含完整基本内存信息的minidump中,而不单是可使用的内存。这样可以使得调试器能够重建minidump生成时进程的完整虚拟内存布局。
h 在minidump中包含和目标进程相关的句柄信息。
u 在minidump中包含已卸载模块信息。仅在Windows Server 2003和之后版本的Windows中可用。
t 在minidump中包含附加的线程信息。包括可以在调试minidump时使用!runaway扩展命令或.ttime (Display Thread Times)命令进行显示的线程时间。
i 在minidump中包含次级内存(secondary
memory)。次级内存是由堆栈中的指针或备份存储(backing store)中引用到的任何内存,加上该地址周围的一小段区域。
p 在minidump中包含进程环境块(PEB)和线程环境块(TEB)。这在想访问程序的进程和线程相关的Windows系统信息时很有用。
w 将所有已交付的可读写的私有页面包含进minidump。
d 在minidump中包含可执行映像中所有可读写的数据段。
c 加入映像中的代码段。
r 从minidump中去掉对重建调用堆栈无用的堆栈和存储内存部分。局部变量和其他数据类型值也被删除。这个选项不会使得minidump变小(因为这些内存节仅仅是变成0),但是当想保护其他程序中的机密信息时有用。
R 在minidump中去掉完整的模块路径。仅包含模块名。如果想保护用户的目录结构时该选项有用。

这些MiniOptions 只能在创建用户模式minidump时使用。它们需要跟在 /m 修饰符后面。

/u
在dump文件名中添加日期、时间和PID。这可以确保dump文件名的唯一性。
/a
所有当前正在调试的进程创建dump。如果使用了/a,也必须使用/u
选项来保证每个文件有唯一的名字。
/b[a]
创建一个.cab 文件。如果包含该选项, FileName
会被当作CAB文件名,而不是dump文件名。会先创建一个临时的dump文件,然后将该文件打包为CAB,然后删除它。如果b后面跟了a,所有的符号和映像文件也会打包到CAB中。
/c "Comment"
指定要写入dump文件的注释字符串。如果Comment 中包含空格,则必须用双引号将它括起来。当dump文件加载时会显示这个Comment
字符串。
/xc Address
(仅用户模式minidump) 在dump文件中加入上下文记录。Address必须指定上下文记录的地址。
/xr Address
(仅用户模式minidump) 在dump文件中加入一个异常记录。Address 必须指定该异常记录开始的地址。
/xp Address
(仅用户模式minidumps) 在dump文件中加入一个上下文记录和异常记录。Address
必须指定一个包含上下文记录和异常记录指针的 EXCEPTION_POINTERS 结构的地址。
/xt ThreadID
(仅用户模式minidumps) 指定将会作为dump文件的异常线程的系统线程的ID。
/kpmf File
(仅创建内核模式完整内存dump) 指定一个包含物理内存页面数据的文件。
FileName
指定dump文件名。可以设置完整路径和文件名,或者只设置文件名。如果文件名中包含空格,则需要用引号将FileName
括起来。如果没有指定路径,会使用当前目录。
-?
显示该命令的帮助。在用户模式和内核模式下显示的文本是不同的。

环境

模式 用户模式、内核模式
目标 活动目标、崩溃转储
平台 所有

注释

该命令可以在各种情况下使用:

  • 进行用户模式活动调试时,该命令创建目标程序的dump文件,但是目标程序不会被结束。
  • 内核模式活动调试时,该命令创建目标机的dump文件,但是目标机不会崩溃。
  • 调试dump文件时,该命令从旧文件创建出一个新的dump文件。这在有一个大的dump文件但是又想创建一个更小的文件时有用。

可以控制dump文件的类型:

  • 内核模式下,使用/f选项来生成完整内存转储。使用/m选项(或不带选项)来生成小内存转储。.dump命令不能创建内核内存转储。
  • 用户模式下,使用.dump /m[MiniOptions] 是最好的选择。虽然"m" 代表着"minidump",但是使用MiniOption创建的dump文件可以很小也可以很大。通过指定合适的MiniOptions
    ,可以精确的控制包含的信息。例如,.dump /ma 产生包含大量信息的dumo文件。.dump /f命令产生大小适中的"标准dump"文件,并且不能进行自定义。

不能指定要转储的进程。所有运行中的进程都会转储下来。

/xc/xr/xp/xt
选项用来在dump文件中保存异常和上下文信息。这使得该dump文件可以使用
.ecxr (Display Exception Context Record)

下面的示例创建一个包含完整内存和句柄信息的用户模式minidump:

0:000> .dump /mfh myfile.dmp 

计算器

当你在调试,需要做一些从十六进制到十进制的简单转换,一些整数计算你不需要切换到calc.exe,你可以只使用windbg的表达式计算器。
假设你得到了一个十六进制的大小,比如说2e903000,您可以转换并执行如下计算:

0:000> ?2e903000
Evaluate expression: 781201408 = 2e903000

所以0x2e903000字节是781201408字节

获取MB数,你只要运行

0:000> ?2e903000/0n1024/0n1024
Evaluate expression: 745 = 000002e9

即除以0n1024两次(十进制数字以0n为前缀),得到745 MB。

聊天客户端

好吧,它不是一个真正的聊天客户端,但是,当您处于远程会话中时,即当有人用.server远程退出了调试会话,并且您想向他们指出一些东西时,您可以用*开始注释,调试器不会解析它,但是连接到远程的其他方会看到它。

0:000>***嘿,看看这个奇怪的东西。。。

与其他应用程序交互

如果需要对命令的输出进行一些处理,并且不想执行将结果复制到记事本、运行外部应用程序等过程,.shell命令是必须尝试的。如果您需要在调试器中对返回的结果进行一些处理,这将特别有用。

0:000> .shell -i - -ci "~* kb 2000" FIND /c "mscorwks!ThreadpoolMgr::WorkerThreadStart"
7
.shell: Process exited

 

!mapped_file

!mapped_file扩展命令显示指定地址所在的内存映射文件所关联的文件名字。

语法

!mapped_file Address 

参数

Address
指定映射文件的地址。如果Address不在内存映射文件中,则命令失败。

DLL

Windows 2000 Uext.dll
Windows XP和之后 Uext.dll

!mapped_file 扩展命令只能用于活动、非远程调试。

注释

这里有三个例子。前两个地址是从文件映射出来的,第三个地址不是。

0:000> !mapped_file 4121ec 
Mapped file name for 004121ec: '\Device\HarddiskVolume2\CODE\TimeTest\Debug\TimeTest.exe'

0:000> !mapped_file 77150000 
Mapped file name for 77150000: '\Device\HarddiskVolume2\Windows\System32\kernel32.dll'

0:000> !mapped_file 80310000 
No information found for 80310000: error 87

这是一个我经常遇到的问题,我们经常会遇到这样的情况:我们必须重新捕获内存转储,因为内存转储是以“错误”的方式捕获的。
简而言之:如果在64位计算机上执行32位进程,则需要使用允许创建32位转储的工具捕获转储。

怎么知道进程是32位的?

如果您在64位计算机上,可以检查任务管理器以查看您的进程正在使用的体系结构。

带*32的进程是32位的,其余的是64位的,因此在上面的示例中,我们可以看到QQ.exe正在执行32位代码。

为什么用正确的工具捕捉它们很重要?

如果使用捕获64位转储的工具捕获转储,您仍将获得内存转储,但您将获得syswow64的内存转储,这意味着许多扩展(如sos和psscor2)将无法读取数据。有些事情可能仍然有效,但它是非常有限的,你可能会得到错误或错误的调用堆栈等。
当您试图读取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 iisre

2、堆栈显示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位地址,即使这是一个32位的进程。

4、在尝试运行sos命令时会出现如下错误。
注意:如果没有正确设置符号,也会出现这些错误,因此这不是出现这些错误的唯一原因。

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 that matches your version of clr.dll is                
in the version directory            
3) or, if you are debugging a dump file, verify that the file                
mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.            
4) you are debugging on the same architecture as the dump file.                
For example, an IA64 dump file must be debugged on an IA64                 machine.

应该使用什么工具?

在此场景中捕获进程转储的最佳方法是使用32位版本的工具,如Debug Diag或adplus+cdb(用于windows的32位调试工具)。您可以在64位系统上安装这些工具的32位版本。在下一个版本的Debug Diag中,您将能够使用64位版本的Debug Diag捕获32位转储。
我之前提到过,可以使用Vista+上的任务管理器捕获内存转储,但如果在64位计算机上执行此操作,则会获得64位转储。但是,您可以使用位于C:\ Windows\SysWOW64\taskmgr.exe中的32位任务管理器来获取32位转储。如果要验证是否正在运行32位版本的任务管理器,可以检查任务管理器本身中是否列出了taskmgr.exe和*32。当然还有其他工具。

使用正确的“位”调试器加载转储文件是否重要?

是的,要读取32位转储,您应该使用32位windbg(在32位或64位操作系统上),而对于64位转储,您调试转储的计算机需要是运行64位windbg的64位计算机。

!cppexr

!cppexr扩展显示一个C++ 异常记录的内容。

语法

!cppexr Address 

参数

Address
指定要显示的C++ 异常记录的地址。

DLL

Windows 2000 Ext.dll
Windows XP 和之后 Ext.dll

注释

!cppexr扩展显示和目标遇到的C++ 异常相关的信息,包括发生异常处的代码、异常的地址和异常标志。必须是在Msvcrt.dll中定义的标准C++
异常。

一般可以使用!analyze -v命令来获得address参数。

!cppexr扩展用来查看C++异常的类型很有用。

附加信息

使用.exr命令来显示其它异常记录。