NetRoc's Blog

N-Tech

 

WinDbg 文档翻译----69

cc682/NetRoc

http://netroc682.spaces.live.com/

!chksym

!chksym 扩展测试一个符号文件对某个模块的有效性。

语法

!chksym <Module> [Symbol

参数

Module

用名字或基地址指定模块。

Symbol

指定符号文件名。

DLL

Windows NT 4.0

不可用

Windows 2000

不可用

Windows XP

不可用

Windows Vista和之后

Dbghelp.dll

 

注释

如果没有指定符号,则测试已加载符号。另外,如果指定了一个.pdb 或者.dbg 符号路径,则测试已加载符号和已加载模块。

!chkimg

!chkimg 扩展通过比较可执行文件映像和符号存储或者其他地方的拷贝,来检测其中被改动过的内容。

语法

!chkimg [Options] [-mmw LogFile LogOptions] [Module

参数

Options

下面这些选项的任意组合:

-p SearchPath

在访问符号服务器之前先在SearchPath中递归搜索文件。

-f

修正映像中的错误。当检测到内存映像和符号存储中的文件有不同时,会将符号存储中的文件内容覆盖掉内存映像中的。如果在进行活动调试,可以在执行!chkimg -f 之前先创建一个dump文件。

-nar

避免符号服务器上文件的映射的映像被移动。默认情况下,当文件的拷贝位于符号服务器上并且被映射到内存中时,!chkimg 会移动符号服务器上的文件的映像。但是,如果使用了-nar 选项,则不会移动服务器上的文件映像。

已经在内存中的可执行映像(即被扫描的那个)会被移动,因为调试器总是会重定位它所加载的映像。这仅在操作系统已经移动了原始映像时有用。如果映像还没有被移动过,则!chkimg 和调试器会移动它。

一般都不需要使用这个开关。

-ss SectionName

将扫描限制在名字包含字符串SectionName 的节中。会扫描名字中包含该字符串的任何不可丢弃的节。SectionName 区分大小写,并且不能超过8个字符。

-as

扫描映像中除了可丢弃节之外的所有节。默认情况下,(如果没有使用-as或者-ss),扫描会跳过可写的节、不可执行的节、名字中有"PAGE"的节、以及可丢弃的节。

-r StartAddress EndAddress

将扫描限制在从StartAddress 开始,EndAddress 结尾的范围内。在该范围中,任何可以被扫描的节都会扫描。如果某个节和该范围只是部分重叠,则只扫描范围中的那部分。即使使用了-as或者-ss 开关,扫描还是被限制在指定范围中。

-nospec

使得扫描包括Hal.dllNtoskrnl.dll 中的保留节。默认情况下, !chkimg 不会检查这些文件的这部分节。

-noplock

显示相应的字节值分别为0x90(nop指令)和0xF0(lock指令)的位置。默认情况下,这些部位不会被显示出来。(详见注释部分,— 译者)

-np

使得被修改过的指令能被识别出来。Causes patched instructions to be recognized. .

-d

扫描时显示不匹配的区域的摘要信息。该摘要文本的详细信息,查看注释部分。

-db

以类似db 调试器命令的格式显示不匹配的区域。因此,每个显示行的开头是该行第一个字节的地址,后面跟最多16个16进制字节值。字节值后面跟相应的ASCII值。所有的不可打印字符,如回车和换行,都显示为点号(.)。不匹配的字节以星号(*)标识。

-lo lines

-d-db 显示的最大行数限制为lines

-v

显示详细信息。

-mmw

创建一个日志文件,并记录!chkimg 的活动情况。日志文件的每一行都对应单个不匹配的项。

LogFile

指定日志文件的完整路径。如果指定相对路径,则是相对于当前路径的。

LogOptions

指定日志文件的内容。LogOptions 是由各个字母组合起来的字符串。日志文件的每一行都包含由逗号分隔的几个列。这些列包含由选项字母指定的项,按照这些字母在LogOptions 中出现的顺序。可以包含下面这些选项多次,但是必须至少包含一个选项。

日志选项

日志文件中包含的信息

v

不匹配的内容的虚拟地址

r

不匹配内容在模块中的偏移(相对地址)

s

和不匹配内容地址对应的符号

S

包含不匹配内容的节的名字

e

不匹配位置的原始值

w

不匹配位置的当前值

 

LogOptions 也可以包含下面这些附加选项的一个、多个或者0个。

日志选项

作用

o

如果LogFile 名字的文件已经存在,则覆盖该文件。默认情况下,调试器会将新信息添加到已存在的文件末尾。

tString

在日志文件中添加一个额外的列。该列中每一项都包含StringtString 选项在将新信息添加到已存在的日志文件时,可以用来和旧的纪录区分开。在tString之间不能有空格。如果使用tIString选项,它必须是LogOptions 的最后一个选项,因为String包括下一个空格之前的所有字符。

 

例如,如果 LogOptionsrSewo,则日志中每一行包括不匹配项的相对地址、节名、该地址的原始值和实际值,并且任何先前的文件都会被覆盖。如果想创建多个具有不同选项的日志文件,可以使用-mmw多次。一次最多创建10个日志文件。

Module

指定要检查的模块。Module 可以是模块名、模块的开始地址,或者包含在模块中的任何地址。如果省略Module,调试器使用包含当前指令指针的模块。

DLL

Windows NT 4.0

Ext.dll

Windows 2000

Ext.dll

Windows XP和之后

Ext.dll

只能在基于x86的目标机上使用!chkimg 扩展命令。

注释

使用!chkimg时,它会比较内存中的可执行映像和符号存储中的文件拷贝。

文件中除了可抛弃的、可写得、不可执行的、名字中有"PAGE"的或者INITKDBG 中的节之外,所有节都会被比较。可以使用-ss-as、或-r 开关来改变这个行为。

!chkimg 会显示文件和内存映像中所有不匹配的地方,除了下面的例外:

  • 导入表(IAT)占用的地址不会检查。
  • Hal.dllNtoskrnl.exe 中的特定地址不会检查,因为这些节加载时会进行特定的改变。要检查这些地址,使用-nospec 选项。
  • 如果文件中的字节值为0x90,内存中的响应字节为0xF0(或者反过来),这种情况被认为是匹配的。一般来说,符号服务器保存单处理器版本和多处理器版本二进制文件中的一个。在x86处理器上,lock指令是0xF0,而在单处理器版本中响应的指令会是nop (0x90)。如果希望!chkimg 显示这种不匹配的项,使用-noplock 选项。

注意  如果使用了-f选项来修正不匹配的内容,!chkimg 仅修正被认为是不匹配的地方。例如,没有包含-noplock时,!chkimg不会将0x90改为0xF0。

包含-d选项时,!chkimg 显示扫描中遇到的不匹配内容的摘要。每个不匹配位置都显示为两行。第一行包含该位置的起始地址、大小、和起始地址对应的符号名和偏移、以及和上一个错误位置之间有多少个字节(圆括号中)。第二行用中括号括起来,包含原始的16进制值、一个冒号、以及当前映像中实际的16进制值。如果该区域大于8个字节,在冒号前后都只会显示8个字节。下面是一个例子。

be000015-be000016  2 bytes - win32k!VeryUsefulFunction+15 (0x8)
     [ 85 dd:95 23 ]

有时候,驱动程序会通过hook、重定向或其它方法改变Microsoft Windows内核的一部分。即使是不在堆栈上的驱动也可能改变内核。可以使用!chkimg 扩展作为文件比较工具来查看Windows内核(或任何其它映像)被某些驱动改变了,以及具体是怎么改变的。这种比较在完整dump文件上非常有效。

也可以将!chkimg!for_each_module 扩展一起使用来检查所有已加载模块的映像。下面是这种情况的示例。

!for_each_module !chkimg @#ModuleName 

例如,假设遇到了bug check,以使用!analyze开始。

kd> !analyze 
....
BugCheck 1000008E, {c0000005, bf920e48, baf75b38, 0}
Probably caused by : memory_corruption
CHKIMG_EXTENSION: !chkimg !win32k
....

例中 !analyze 的输出提示可能遇到了内存错误,并且包含了一个CHKIMG_EXTENSION 行提示被破坏的模块可能是Win32k.sys。(即使不存在这一行,也应该考虑可能调用堆栈顶部的模块被破坏了。)不带任何参数使用!chkimg ,如下。

kd> !chkimg win32k
Number of different bytes for win32k: 31

下面的例子说明确实有内存错误。使用!chkimg -d 来显示模块Win32k 中的所有错误。

kd> !chkimg win32k -d
    bf920e40-bf920e46  7 bytes - win32k!HFDBASIS32::vSteadyState+1f
        [ 78 08 d3 78 0c c2 04:00 00 00 00 00 01 00 ]
    bf920e48-bf920e5f  24 bytes - win32k!HFDBASIS32::vHalveStepSize (+0x08)
        [ 8b 51 0c 8b 41 08 56 8b:00 00 00 00 00 00 00 00 ]
Number of different bytes for win32k: 31

当尝试反汇编列出来的第二个被破坏的映像位置时,可能会有下面这样的输出。

kd> u  win32k!HFDBASIS32::vHalveStepSize
win32k!HFDBASIS32::vHalveStepSize:
bf920e48 0000             add     [eax],al
bf920e4a 0000             add     [eax],al
bf920e4c 0000             add     [eax],al
bf920e4e 0000             add     [eax],al
bf920e50 7808            js win32k!HFDBASIS32::vHalveStepSize+0x12 (bf920e5a)
bf920e52 d3780c           sar     dword ptr [eax+0xc],cl
bf920e55 c20400           ret     0x4
bf920e58 8b510c           mov     edx,[ecx+0xc]

然后,使用!chkimg –f来修正内存错误。

kd> !chkimg win32k -f
Warning: Any detected errors will be fixed to what we expect!
Number of different bytes for win32k: 31 (fixed)

现在可以反汇编正确的内容并且查看有些什么改变。

kd> u  win32k!HFDBASIS32::vHalveStepSize
win32k!HFDBASIS32::vHalveStepSize:
bf920e48 8b510c           mov     edx,[ecx+0xc]
bf920e4b 8b4108           mov     eax,[ecx+0x8]
bf920e4e 56               push    esi
bf920e4f 8b7104           mov     esi,[ecx+0x4]
bf920e52 03c2             add     eax,edx
bf920e54 c1f803           sar     eax,0x3
bf920e57 2bf0             sub     esi,eax
bf920e59 d1fe             sar     esi,1

!cppexr

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

语法

!cppexr Address 

参数

Address

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

DLL

Windows NT 4.0

Ext.dll

Windows 2000

Ext.dll

Windows XP和之后

Ext.dll

注释

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

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

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

附加信息

关于异常的更多信息,查看控制异常和事件、Windows Driver Kit (WDK)文档、 Windows SDK 文档、以及Mark Russinovich和David Solomon编写的Microsoft Windows Internals 。使用.exr 命令来显示其它异常记录。

!cpuid

!cpuid 扩展用来显示系统中的处理器的信息。

语法

!cpuid [Processor

参数

Processor

指定要显示信息的处理器。如果省略该参数,则显示所有处理器。

DLL

Windows NT 4.0

Ext.dll

Windows 2000

Ext.dll

Windows XP和之后

Ext.dll

注释

!cpuid 扩展可以在用户模式或者内核模式活动调试、本地内核调试和调试dump文件时使用。但是,用户模式minidump文件仅包含活动处理器的信息。

如果在用户模式下调试,!cpuid 扩展用于查看目标程序运行的计算机。在内核模式下调试时,用于查看目标机。

下面是该扩展的示例。

kd> !cpuid 
CP  F/M/S  Manufacturer        MHz 
 0  6,5,1  GenuineIntel        700 
 1  8,1,5  AuthenticAMD        700 

CP 列是处理器号。(这些数字总是连续的,以0开始)。 Manufacturer 列显示处理器厂商。MHz 列显示处理器的速度,如果可用的话。

对于x86处理器或者x64处理器, F 列显示处理器的家族号, M 列显示处理器模型号,S 列显示stepping size(流水线长度?)。

对于Itanium处理器,M列显示处理器模型号, R 列显示处理器修订编号(revision number),F列显示处理器家族号, A列显示架构修订编号。

附加信息

关于如何调试多处理器计算机的信息,查看多处理器语法

!cs

!cs 扩展显示一个或多个临界区(critical section)或者整个临界区树。

语法

!cs [-s] [-l] [-o
!cs [-s] [-o] [Address
!cs [-s] [-l] [-oStartAddress EndAddress 
!cs [-s] [-o-d InfoAddress 
!cs [-s-t [TreeAddress
!cs -? 

参数

-s

如果可能的话,显示每个临界区的初始堆栈回溯。

-l

仅显示锁定的临界区。

-o

对所有显示出来的已锁定的临界区,显示所有者的堆栈。

Address

指定要显示的临界区地址。如果省略该参数,调试器显示当前进程中所有临界区。

StartAddress

指定要搜索临界区的地址范围的开头。

EndAddress

指定要搜索临界区的范围的结束地址。

-d

显示和DebugInfo 关联的临界区。

InfoAddress

指示DebugInfo 的地址。

-t

显示临界区树。使用-t 选项之前,必须选择为目标进程激活应用程序验证器(Application Verifier)并且选中Check lock usage 选项。

TreeAddress

指定临界区树的根的地址。如果省略该参数或者指定0,调试器现实当前进程的临界区树。

-?

调试器命令窗口中显示该命令的帮助文本。

DLL

Windows NT 4.0

不可用

Windows 2000

不可用

Windows XP和之后

Exts.dll

注释

!cs 扩展要求被调试进程和Ntdll.dll的完整符号(包含类型信息)。如果没有Ntdll.dll的符号,查看安装Windows符号文件

下面是如何使用!cs的示例。这条命令显示0x7803B0F8地址处的临界区的信息和初始调用堆栈。

0:001> !cs -s 0x7803B0F8
Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
DebugInfo          = 0x6A262080
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

Stack trace for DebugInfo = 0x6A262080:

0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

下面的命令显示DebugInfo在0x7803B0F8处的临界区信息。

0:001> !cs -d 0x6A262080
DebugInfo          = 0x6A262080
Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

下面的信息显示当前进程中的所有活动临界区的信息。

0:001> !cs
-----------------------------------------
DebugInfo          = 0x6A261D60
Critical section   = 0x6A262820 (ntdll!RtlCriticalSectionLock+0x0)
LOCKED
LockCount          = 0x0
OwningThread       = 0x460
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x0
-----------------------------------------
DebugInfo          = 0x6A261D80
Critical section   = 0x6A262580 (ntdll!DeferedCriticalSection+0x0)
NOT LOCKED
LockSemaphore      = 0x7FC
SpinCount          = 0x0
-----------------------------------------
DebugInfo          = 0x6A262600
Critical section   = 0x6A26074C (ntdll!LoaderLock+0x0)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
-----------------------------------------
DebugInfo          = 0x77fbde20
Critical section   = 0x77c8ba60 (GDI32!semColorSpaceCache+0x0)
LOCKED
LockCount          = 0x0
OwningThread       = 0x00000dd8
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000
-----------------------------------------
...

下面的命令现实临界区树。

0:001> !cs -t

Tree root 00bb08c0

Level     Node       CS    Debug  InitThr EnterThr  WaitThr TryEnThr LeaveThr EnterCnt  WaitCnt

-----------------------------------------------------------------------------------------------

    0 00bb08c0 77c7e020 77fbcae0      4c8      4c8        0        0      4c8        c        0
    1 00dd6fd0 0148cfe8 01683fe0      4c8      4c8        0        0      4c8        2        0
    2 00bb0aa0 008e8b84 77fbcc20      4c8        0        0        0        0        0        0
    3 00bb09e0 008e8704 77fbcba0      4c8        0        0        0        0        0        0
    4 00bb0a40 008e8944 77fbcbe0      4c8        0        0        0        0        0        0
    5 00bb0a10 008e8824 77fbcbc0      4c8        0        0        0        0        0        0
    5 00bb0a70 008e8a64 77fbcc00      4c8        0        0        0        0        0        0
    3 00bb0b00 008e8dc4 77fbcc60      4c8        0        0        0        0        0        0
    4 00bb0ad0 008e8ca4 77fbcc40      4c8        0        0        0        0        0        0
    4 00bb0b30 008e8ee4 77fbcc80      4c8        0        0        0        0        0        0
    5 00dd4fd0 0148afe4 0167ffe0      4c8        0        0        0        0        0        0
    2 00bb0e90 77c2da98 00908fe0      4c8      4c8        0        0      4c8       3a        0
    3 00bb0d70 77c2da08 008fcfe0      4c8        0        0        0        0        0        0

!cs -t 的显示中有如下内容:

  • InitThr 是初始化临界区的线程的ID。
  • EnterThr 是最近一次调用EnterCriticalSection 的线程ID。
  • WaitThr 是最近一次因为其他线程拥有临界区而等待的线程的ID。
  • TryEnThr 是最近一次调用TryEnterCriticalSection 的线程的ID。
  • LeaveThr 是最近一次调用LeaveCriticalSection 的线程ID。
  • EnterCntEnterCriticalSection 的次数。
  • WaitCnt是出现争用的次数。

附加信息

关于其他可以显示临界区信息的命令和扩展,查看显示临界区。关于临界区的更多信息,查看Microsoft Windows SDK文档、the Windows Driver Kit (WDK)文档、以及Mark Russinovich 和David Solomon 编写的Microsoft Windows Internals

!cxr

!cxr 扩展命令已经废除。使用.cxr (Display Context Record)命令来替代。

posted on 2008-07-08 13:52 NetRoc 阅读(777) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。

导航

统计

常用链接

留言簿(6)

随笔档案(99)

文章分类(35)

文章档案(32)

Friends

Mirror

搜索

最新评论

阅读排行榜

评论排行榜