WinDBG的大多数功能是以命令方式工作的, 本系列将介绍WinDBG的三类命令, 标准命令, 元命令和扩展命令.
标准命令
===============
标准命令用来提供适用于所有调试目标的基本调试功能.
所有基本命令都是实现在WinDBG内部的, 执行这些命令时不需要加载任何扩展模块. 大多数标准命令是一两个字符或者符号, 只有version等少数命令除外. 标准命令的第一个字符是不分大小写的, 第二个字符可能区分大小写. 迄今为止, WinDBG调试器共实现了130多条标准命令, 分为60多个系列. 为了便于记忆, 可以根据功能将标准命令归纳为如下18个子类.
控制调试目标执行
功能 | 命令 | 描述/助记 | 补充信息 |
恢复运行 | g | Go | ~123g, ~#g, ~*g |
跟踪执行 | t | Trace | |
单步执行 | p | Step | |
追踪监视 | wt | Trace and Watch Data |
寄存器相关
功能 | 命令 | 描述/助记 | 补充信息 |
观察和修改通用寄存器 | r | Registers | |
读写MSR寄存器 | rdmsr和wrmsr | Read MSR and Write MSR | |
设置寄存器显示掩码 | rm | Register Mask |
IO端口读写
功能 | 命令 | 描述/助记 |
读IO端口 | ib, iw, id | Input from port (byte, word, double word) |
写IO端口 | ob, ow, od | Output to port (byte, word, double word) |
内存控制
功能 | 命令 | 描述/助记 | 补充信息 |
观察内存 | d系列 | Display Memory | d, da, db, dc, dd, dD, df, dp, dq, du, dw, dW, dyb, dyd |
编辑内存 | e系列 | Enter Values | e, ea, eb, ed, eD, ef, ep, eq, eu, ew, eza, ezu |
搜索内存 | s | Search Memory | sb, sw, sd, sq, sa, su |
栈
功能 | 命令 | 描述/助记 | 补充信息 |
观察栈 | k系列 | Display Stack Backtrace | k, kb, kc, kd, kp, kP, kv |
设置维护断点
功能 | 命令 | 描述/助记 |
软件断点 | bp, bu, bm | Set Breakpoint, Set Unresolved Breakpoint, Set Symbol Breakpoint |
硬件断点 | ba | Break on Access |
管理断点 | bl | Breakpoint List |
清除,禁止,重新启用断点 | bc, bd, be | Breakpoint Clear, Breakpoint Disable, Breakpoint Enable |
线程
功能 | 命令 | 描述/助记 |
显示控制线程 | ~ | Thread Status |
进程
功能 | 命令 | 描述/助记 |
显示进程 | | | Process Status |
表达式
功能 | 命令 | 描述/助记 |
评估表达式 | ? | Evaluate Expression |
评估C++表达式 | ?? | Evaluate C++ Expression |
汇编, 反汇编
功能 | 命令 | 描述/助记 |
汇编 | a | Assemble |
反汇编 | u | Unassemble |
段
功能 | 命令 | 描述/助记 |
显示段的选择子 | dg | Display Selector: shows the segment descriptor for the specified selector |
执行命令文件
功能 | 命令 | 描述/助记 | 补充信息 |
运行命令脚本文件 | $ | Run Script File | $<, $><, $$<, $$><, $$>a< |
配置命令
功能 | 命令 | 描述/助记 | 补充信息 |
异常发生或者某事件发生时debuger的处理方式 | sx系列 | Set Exceptions | sx, sxd, sxe, sxi, sxn, sxr, sx- |
启用与禁止静默模式 | sq | Set Quiet Mode | sq sq{ e|d} |
设置内核debugging选项 | so | Set Kernel Debugging Options | |
设置符号后缀 | ss | Set Symbol Suffix | ss [a|w|n] |
版本与系统信息
功能 | 命令 | 描述/助记 |
显示调试器和调试目标版本 | version | Show Debugger Version |
显示调试目标所在系统的信息 | vertarget | Show Target Computer Version |
检查符号
功能 | 命令 | 描述/助记 |
检查符号 | x | Examine Symbols |
源程序
功能 | 命令 | 描述/助记 | 补充信息 |
控制和显示源程序 | ls系列 | List Source Lines | ls, lsa, lsp, lsc, lsf |
调试符号
功能 | 命令 | 描述/助记 |
加载调试符号 | ld | Load Symbols |
搜索相邻符号 | ln | List Nearest Symbols |
显示模块列表 | lm | List Loaded Modules |
调试会话
功能 | 命令 | 描述/助记 |
结束调试会话 | q | Quit |
结束远程调试 | Quit | |
结束调试会话并分离调试目标 | qd | Quit and Detach |
在命令编辑框中输入一个问号(?), 可以显示出主要的标准命令和每个命令的简单介绍.
元命令(Meta-Command)用来提供标准命令没有提供的常用调试功能, 与标准命令一样, 元命令也是内建在调试器引擎或者WinDBG程序文件中的. 所有元命令都已一个点(.)开始, 所以元命令也被称为点命令(Dot Command).
按照功能, 可以把元命令分成如下几类.
- 显示和设置调试会话和调试器选项.
- 用于符号选项的.symopt- Set Symbol Options
- 用于符号路径的.sympath- Set Symbol Path, 和.symfix- Set Symbol Store Path.
- 用于程序源文件的.srcpath- Set Source Path, .srcnoisy- Noisy Source Loading,.srcfix- Use Source Server
- 用于扩展命令模块路径的.extpath- Set Extension Path
- 用于匹配扩展命令的.extmatch- Display All Matching Extensions
- 用于可执行文件的.exepath- Set Executable Path
- 设置反汇编选项的.asm- Change Disassembly Options
- 控制表达式评估器的.expr- Choose Expression Evaluator
- 控制调试会话或者调试目标.
- 重新开始调试会话的.restart- Restart Kernel Connection(Kernel Mode) 或 Restart Target Application(User Mode)
- 放弃用户态调试目标(进程)的.abandon- Abandon Process
- 创建新进程的.create- Create Process
- 附加到存在进程的.attach- Attach to Process
- 打开转储文件的.opendump- Open Dump File
- 分离调试目标的.detach- Detach from Process
- 用于杀掉进程的.kill- Kill Process
- 管理扩展命令模块
- 加载模块的.load- Load Extension DLL
- 卸载模块.unload- Unload Extension DLL和.unloadall- Unload All Extension DLLs
- 显示已加载模块的.chain- List Debugger Extensions
- 管理调试器日志文件
- 显示信息 .logfile- Display Log File Status
- 打开 .logopen- Open Log File
- 追加 .logappend- Append Log File
- 关闭 .logclose- Close Log File
- 远程调试
- 用于启动remote.exe服务的.remote- Create Remote.exe Server
- 用于启动调试引擎服务器的.server- Create Debugging Server
- 列出可用服务器的.servers- List Debugging Servers
- 用于向远程服务器发送文件的.send_file- Send File
- 用于结束远程进程服务器的.endpsrv- End Process Server
- 用于结束引擎服务器的.endsrv- End Debugging Server
- 控制调试器
- 让调试器睡眠一段时间的.sleep- Pause Debugger
- 唤醒处于睡眠状态的调试器的.wake- Wake Debugger
- 启动另一个调试器来调试当前调试器的.dbgdbg- Debug Current Debugger
- 编写命令程序
- 包括一系列类似C语言关键字的命令, 如
- .if, .else, .elsif, .foreach, .do, .while. .continue, .catch, .break, .continue, .leave, .printf, .block. 在<软件调试>一书第30章的第18节有介绍命令程序的编写方法.
- 包括一系列类似C语言关键字的命令, 如
- 显示或者转储调试目标数据
- 产生转储文件的.dump- Create Dump File
- 将原始内存数据写到文件的.writemem- Write Memory to File
- 显示调试会话时间的.time- Display System Time
- 显示线程时间的.ttime- Display Thread Times
- 显示任务列表的.tlist- List Process IDs
- 以不同格式显示数字的.formats- Show Number Formats
- 可以列出所有元命令和每个命令的简单说明的.help- Meta-Command Help
扩展命令(Extension Command)用于实现针对特定调试目标的调试功能. 与标准命令和元命令是内建在WinDBG程序文件中不同, 扩展命令式实现在动态加载的扩展模块(DLL)中的.
利用WinDBG的SDK, 用户可以自己编写扩展模块和扩展命令. WinDBG程序包中包含了常用的扩展命令模块. 存放在以下几个子目录中.
- NT4CHK: 调试目标为Windows NT 4.0 checked版本时的扩展命令模块.
- NT4FRE: 调试目标为Windows NT 4.0 free 版本时的扩展命令模块.
- W2KCHK: 调试目标为Windows 2000 checked 版本时的扩展命令模块.
- W2KFRE: 调试目标为Windows 2000 free 版本时的扩展命令模块.
- WINXP: 调试目标为Windows XP 或者更高版本时版本时的扩展命令模块.
- WINEXT: 适用于所有Windows版本的扩展命令模块.
扩展模块 | 路径 | 描述 |
ext.dll | WINEXT | 适用于各种调试目标的常用扩展命令 |
kext.dll | WINEXT | 内核态调试时的常用扩展命令 |
uext.dll | WINEXT | 用户态调试时的常用扩展命令 |
logexts.dll | WINEXT | 用于监视和记录API调用(Windows API Logging Extensions) |
sos.dll | WINEXT | 用于调试托管代码和.Net程序 |
ks.dll | WINEXT | 用于调试内核流(Kernel Stream) |
wdfkd.dll | WINEXT | 调试使用WDF(Windows Driver Foundation)编写的驱动程序 |
acpikd.dll | WINXP | 用于ACPI调试,追踪调用ASL程序的过程,显示ACPI对象 |
exts.dll | WINXP | 关于堆(!heap)、进程/线程结构(!teb/!peb)、安全信息(!token、!sid、!acl)和应用程序验证(!avrf)等的扩展命令 |
kdexts.dll | WINXP | 包含了大量用于内核调试的扩展命令 |
fltkd.dll | WINXP | 用于调试文件系统的过滤驱动程序(FsFilter) |
minipkd.dll | WINXP | 用于调试AIC78xx小端口(miniport)驱动程序 |
ndiskd.dll | WINXP | 用于调试网络有关驱动程序 |
ntsdexts.dll | WINXP | 实现了!handle、!locks、!dp、!dreg(显示注册表)等命令 |
rpcexts.dll | WINXP | 用于RPC调试 |
scsikd.dll | WINXP | 用于调试SCSI有关的驱动程序 |
traceprt.dll | WINXP | 用于格式化ETW信息 |
vdmexts.dll | WINXP | 调试运行在VDM中的DOS程序和WOW程序 |
wow64exts.dll | WINXP | 调试运行在64位Windows系统中的32位程序 |
wmitrace.dll | WINXP | 显示WMI追踪有关的数据结构、缓冲区和日志文件 |
执行扩展命令式, 应该以叹号( ! )开始, 叹号在英文中被称为bang, 因此扩展名伶也被称为Bang Command. 执行扩展命令的完整格式是:
![扩展模块名].<扩展命令名> [参数]
其中, 扩展模块名可以省略, 如果省略, WinDBG会自动在已经加载的扩展模块中搜索指定的命令.
因为扩展命令是实现在动态加载的扩展模块(DLL)中的, 所以执行时需要加载对应的扩展模块. 当调试目标被激活(debuggee activation)时, WinDBG会根据调试目标的类型和当前的工作空间自动加载命令空间中指定的扩展模块. 用户也可以使用一下方法手动加载扩展模块.
- 使用.load命令加上扩展模块的名称或者完成路径来加载它. 如果没有指定路径, 那么WinDBG会在扩展模块搜索路径(EXTPATH)中寻找这个文件.
- 使用.loadby命令加上扩展模块的名称和一个已经加载的程序模块的名称. 这时WinDBG会在指定的程序模块文件所在目录中寻找和加载扩展命令模块. 例如, 在调试托管程序是, 可以使用.loadby sos mscorwks命令让WinDBG在mscorwks模块所在的目录中加载SOS扩展模块, 这样可以确保加载正确版本的sos模块.
当使用"!扩展模块名.扩展命令名"的方式执行扩展命令时, 如果指定的扩展模块还没有加载, 那么WinDBG会自动搜索和加载这个模块.
使用.chain命令可以列出当前加载的所有扩展模块, 使用.unload和.unloadall命令可以卸载指定的或者全部扩展模块. 大多数扩展模块都支持help命令来显示这个模块的基本信息和所包含的全部命令, 例如执行!ext.help可以显示ext模块中的所有扩展命令.
SOS Debugging Extension (SOS.dll) 可以在WinDgb.exe和Visual Studio中通过提供CLR内部环境信息的方式, 帮助你debug托管程序.
这里的命令列表在WinDbg的帮助中是找不到的. 列在下面, 备查.
Command | Description |
BPMD [<module name> <method name>] [-md <MethodDesc>] | Creates a breakpoint at the specified method in the specified module. If the specified module and method have not been loaded, this command waits for a notification that the module was loaded and just-in-time compiled before creating a breakpoint. |
CLRStack [-a] [-l] [-p] | Provides a stack trace of managed code only. The -p option shows arguments to the managed function. The -l option shows information on local variables in a frame. The SOS Debugging Extension cannot retrieve local names, so the output for local names is in the format <local address>= <value>. The -a (all) option is a shortcut for -l and-p combined. The SOS Debugging Extension does not display Transition Frames on x64 and IA-64-based platforms. |
COMState | Lists the COM apartment model for each thread and a Context pointer, if available. |
DumpArray [-start <startIndex>] [-length <length>] [-details] [-nofields] <array object address> -or- DA [-start <startIndex>] [-length <length>] [-detail] [-nofields] array object address> | Examines elements of an array object. The -start option specifies the starting index at which to display elements. The -length option specifies how many elements to show. The -detail option displays details of the element using the DumpObj and DumpVC formats. The -nofields option prevents arrays from displaying. This option is available only when the-detail option is specified. |
DumpAssembly <Assembly address> | Displays information about an assembly. The DumpAssembly command lists multiple modules, if they exist. You can get an assembly address using the DumpDomain command. |
DumpClass <EEClass address> | Displays information about the EEClass structure associated with a type. The DumpClass command displays static field values but does not display nonstatic field values. Use the DumpMT, DumpObj, Name2EE, orToken2EE commands to get anEEClass structure address. |
DumpDomain [<Domain address>] | Enumerates each object loaded within the specified object address. When called with no parameters, the DumpDomain command lists allAppDomain objects in a process. |
DumpHeap [-stat] [-min <size>][-max <size>] [-thinlock] [-mt <MethodTable address>] [-type <partial type name>][start [end]] | Displays information about the garbage-collected heap and collection statistics about objects. The DumpHeap command displays a warning if it detects excessive fragmentation in the garbage collector heap. The -stat option restricts the output to the statistical type summary. The -min option ignores objects that are less than the size parameter, specified in bytes. The -max option ignores objects that are larger than the size parameter, specified in bytes. The -thinlock option reports ThinLocks. For more information, see theSyncBlk command. The -mt option lists only those objects that correspond to specified theMethodTable structure. The -type option lists only those objects whose type name is a substring match of the specified string. The start parameter begins listing from the specified address. The end parameter stops listing at the specified address. |
DumpIL [<DynamicMethod address>] [<DynamicMethodDesc address>] [<MethodDesc address>] | Displays the intermediate language (IL) associated with a managed method. Note that dynamic IL is emitted differently than IL loaded from an assembly. Dynamic IL refers to objects in a managed object array rather than to metadata tokens. |
DumpLog [<Filename>] | Writes the contents of an in-memory stress log to the specified file. If you do not specify a name, this command creates a file called Stresslog.txt in the current directory. The common language runtime provides an in-memory stress log that helps you diagnose stress failures. The log allows you to diagnose failures without using locks or I/O. To enable the stress log, set the following registry keys under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework: (DWORD) StressLog = 1 (DWORD) LogFacility = 0xffffffff (DWORD) StressLogSize = 65536 |
DumpMD <MethodDesc address> | Displays information about a MethodDesc structure at the specified address. You can use the IP2MD command to get the MethodDesc structure address from a managed function. |
DumpMT [-MD] <MethodTable address> | Displays information about a method table at the specified address. Specifying the-MD option displays a list of all methods defined with the object. Each managed object contains a method table pointer. |
DumpMethodSig <sigaddr> <moduleaddr> | Displays information about a MethodSig structure at the specified address. |
DumpModule [-mt] <Module address> | Displays information about a module at the specified address. The -mt option displays the types defined in a module and the types referenced by the module You can use the DumpDomain or DumpAssembly commands to retrieve a module's address. |
DumpObj <object address> -or- DO <object address> | Displays information about an object at the specified address. The DumpObj command displays the fields, theEEClass structure information, the method table, and the size of the object. You can use the DumpStackObjects command to retrieve an object's address. Note that you can run the DumpObj command on fields of type CLASS because they are also objects. |
DumpRuntimeTypes | Displays the runtime type objects in the garbage collector heap and lists their associated type names and method tables. |
DumpStack [-EE] [top stack [bottom stack]] | Displays a stack trace. The -EE option causes the DumpStack command to display only managed functions. Use thetop andbottomparameters to limit the stack frames displayed on x86 platforms. On x86 platforms, the DumpStack command creates a verbose stack trace. On x64 and IA-64-based platforms, the DumpStack command mimics the debugger'sK command. Thetop andbottom parameters are ignored on x64 and IA-64-based platforms. |
DumpSig <sigaddr> <moduleaddr> | Displays information about a Sig structure at the specified address. |
DumpStackObjects [-verify] [top stack [bottom stack]] -or- DSO [-verify] [top stack [bottom stack]] | Displays all managed objects found within the bounds of the current stack. The -verify option validates each non-static CLASS field of an object field. Use the DumpStackObject command with stack tracing commands such as theK command and theCLRStack command to determine the values of local variables and parameters. |
DumpVC <MethodTable address> <Address> | Displays information about the fields of a value class at the specified address. The MethodTable parameter allows the DumpVC command to correctly interpret fields. Value classes do not have a method table as their first field. |
EEHeap [-gc] [-loader] | Displays information about process memory consumed by internal common language runtime data structures. The -gc and -loader options limit the output of this command to garbage collector or loader data structures. The information for the garbage collector lists the ranges of each segment in the managed heap. If the pointer falls within a segment range given byEEHeap -gc, the pointer is an object pointer. |
EEStack [-short] [-EE] | Runs the DumpStack command on all threads in the process. The -EE option is passed directly to the DumpStack command. The-short parameter limits the output to the following kinds of threads: 1. Threads that have taken a lock. 2. Threads that have been stalled in order to allow a garbage collection. 3. Threads that are currently in managed code. |
EEVersion | Displays the common language runtime version. |
EHInfo [<MethodDesc address>] [<Code address>] | Displays the exception handling blocks in a specified method. This command displays the code addresses and offsets for the clause block (the try block) and the handler block (the catch block). |
FinalizeQueue [-detail] | Displays all objects registered for finalization. The -detail option displays additional information about any SyncBlocks that await cleanup and extra information about any RuntimeCallableWrappers (RCWs) that await cleanup. Both data structures are cached and cleaned up by the finalizer thread. |
FindAppDomain <Object address> | Determines the application domain of an object at the specified address. |
GCHandles [-perdomain] | Displays statistics about garbage collector handles in the process. Passing the -perdomain option arranges the statistics by application domain. Use the GCHandles command to find memory leaks caused by garbage collector handle leaks. For example, a memory leak occurs when code retains a large array because a strong garbage collector handle still points to it, and the handle is discarded without freeing it. |
GCHandleLeaks | Searches memory for any references to strong and pinned garbage collector handles in the process and displays the results. If a handle is found, theGCHandleLeaks command displays the address of the reference. If a handle is not found in memory, this command displays a notification. |
GCInfo <MethodDesc address> <Code address> | Displays data that indicates when registers or stack locations contain managed objects. If a garbage collection occurs, the collector must know the locations of references to objects so it can update them with new object pointer values. |
GCRoot [-nostacks] <Object address> | Displays information about references (or roots) to an object at the specified address. The GCRoot command examines the entire managed heap and the handle table for handles within other objects and handles on the stack. Then, each stack is searched for pointers to objects and the finalizer queue is also searched. This command does not determine whether a stack root is valid or is discarded. Use theCLRStack andU commands to disassemble the frame that the local or argument value belongs to in order to determine if the stack root is still in use. The -nostacks option restricts the search to garbage collector handles and freachable objects. |
help [<command>] [<faq>] | Displays all available commands when no parameter is specified or displays detailed help information about the specified command. The faq parameter displays answers to frequently asked questions. |
IP2MD <Code address> | Displays the MethodDesc structure at the specified address in code that has been just-in-time (JIT) compiled. |
MinidumpMode [0] [1] | Prevents running unsafe commands when using a minidump. Pass 0 to disable this feature or 1 to enable this feature. By default, theMinidumpMode value is set to0. Minidumps created with the .dump /m command or .dump command have limited CLR-specific data and allow you to run only a subset of SOS commands correctly. Some commands may fail with unexpected errors because required areas of memory are not mapped or are only partially mapped. This option protects you from running unsafe commands against minidumps. |
Name2EE <module name> <type or method name> -or- Name2EE <module name>!<type or method name> | Displays the MethodTable structure and EEClass structure for the specified type or method in the specified module. The specified module must be loaded in the process. To get the proper type name, browse the module using the . You can also pass * as the module name parameter to search all loaded managed modules. The module name parameter can also be the debugger's name for a module, such asmscorlib orimage00400000. This command supports the Windows debugger syntax of <module>!<type>. The type must be fully qualified. |
ObjSize [<Object address>] | Displays the size of the specified object. With no parameters, the ObjSize command displays the size of all objects found on managed threads, displays all garbage collector handles in the process, and totals the size of any objects pointed to by those handles. The ObjSize command includes the size of all child objects in addition to the parent. |
PrintException [-nested] [<Exception object address>] -or- PE [-nested] [<Exception object address>] | Displays and formats fields of any object derived from the class at the specified address. If you do not specify an address, thePrintException command displays the last exception thrown on the current thread. The -nested option displays details about nested exception objects. You can use this command to format and view the _stackTrace field, which is a binary array. |
ProcInfo [-env] [-time] [-mem] | Displays environment variables for the process, kernel CPU time, and memory usage statistics. |
RCWCleanupList <RCWCleanupList address> | Displays the list of runtime callable wrappers at the specified address that are awaiting cleanup. |
SaveModule <Base address> <Filename> | Writes an image, which is loaded in memory at the specified address, to the specified file. |
StopOnException [-derived] [-create | -create2] <Exception> <Pseudo-register number> | Causes the debugger to stop when the specified exception is thrown, but to continue running when other exceptions are thrown. The -derived option catches the specified exception and every exception that derives from the specified exception. |
SyncBlk [-all | <syncblk number>] | Displays the specified SyncBlock structure or all SyncBlock structures. If you do not pass any arguments, theSyncBlk command displays theSyncBlock structure corresponding to objects that are owned by a thread. A SyncBlock structure is a container for extra information that does not need to be created for every object. It can hold COM interop data, hash codes, and locking information for thread-safe operations. |
ThreadPool | Displays information about the managed thread pool including the number of work requests in the queue, the number of completion port threads, and the number of timers. |
Token2EE <module name> <token> | Turns the specified metadata token in the specified module into a MethodTable structure orMethodDesc structure. You can pass * for the module name parameter to find what that token maps to in every loaded managed module. You can also pass the debugger's name for a module, such asmscorlib orimage00400000. |
Threads [-live] [-special] | Displays all managed threads in the process. The Threads command displays the debugger shorthand ID, the common language runtime thread ID, and the operating system thread ID. Additionally, theThreads command displays a Domain column that indicates the application domain in which a thread is executing, an APT column that displays the COM apartment mode, and an Exception column that displays the last exception thrown in the thread. The -live option displays threads associated with a live thread. The -special option displays all special threads created by the CLR. Special threads include garbage collection (GC) threads (in concurrent GC and server GC), Debugger helper threads, Finalizer threads,AppDomain Unload threads, and Threadpool timer threads. |
TraverseHeap [-xml] <filename> | Writes heap information to the specified file in a format understood by the CLR Profiler. The-xml option causes theTraverseHeap command to format the file as XML. You can download the CLR Profiler from: |
U [-gcinfo] [-ehinfo] <MethodDesc address> | <Code address> | Displays an annotated disassembly of a managed method specified by a MethodDesc structure pointer for the method or by a code address within the method body. TheU command displays the entire method from start to finish, with annotations that convert metadata tokens to names. The -gcinfo option causes the U command to display theGCInfo structure for the method. The -ehinfo option displays exception information for the method. You can also obtain this information with theEHInfo command. |
VerifyHeap | Checks the garbage collector heap for signs of corruption and displays any errors found. Heap corruptions can be caused by platform invoke calls that are constructed incorrectly. |
VMMap | Traverses the virtual address space and displays the type of protection applied to each region. |
VMStat | Provides a summary view of the virtual address space, ordered by each type of protection applied to that memory (free, reserved, committed, private, mapped, image). The TOTAL column displays the result of the AVERAGE column multiplied by the BLK COUNT column. |
SOS Debugging Extension (SOS.dll)
如何在WinDBG里获得关于命令的帮助?
标准命令帮助
============
?
? /D
元命令帮助
============
.help
.help /D .help /D a*
扩展命令帮助
=============
!help
!help savemodule
在命令行中开启WinDBG的chm帮助
=============
.hh
.hh lm
参考资料:
Windows Debuggers: Part 1: A WinDbg Tutorial
Common WinDbg Commands (Thematically Grouped)
如何在WinDBG里保存运行过的命令的历史记录?
命令举例如下:
.write_cmd_hist c:\WindbgCmdHistory.txt
1 !address eax查看对应内存页的属性
2 vertarget 显示当前进程的大致信息 3 !peb 显示process Environment Block 4 lmvm 可以查看任意一个dll的详细信息 例如:0:026 lmvm msvcrt (deferred)表示察看msvcrt.dll的信息,但是没有加载 symbol可以通过.reload命令来加载 5.reload /!sym 加载符号文件 6 lmf 列出当前进程中加载的所有dll文件和对应的路径 0:018> lmf 7 r 命令显示和修改寄存器上的值 r命令显示和修改寄存器上的值 0:018> r 显示寄存器的值 0:018> r eax=0 修改了寄存器,把eax的值修改为0x0 8 d命令显示esp寄存器指向的内存 如下 0:018>d esp 用dd命令直接指定054efc14地址 0:018>dd 054efc14 注意:第二个d表示DWORD格式,此外还有db(byte),du(Unicode),dc(char)等等。 数据查看指令 d{a|b|c|d|D|f|p|q|u|w|W} d{b|c|d|D|f|p|q}分别是显示: byte&ASCII, double-word&ASCII,double-word,double-precision,float,pointer-sized,quad-word数据; DA用于显示ASCII,DU用于显示UNICODE; BYB,BYD,显示binary和Byte及binary和DWORD 补充一个DV,用于查看本地变量用的 9 e命令可以用来修改内存地址 跟d命令一样,e命令后面也可以跟类型后缀,比如ed命 令表示用DWORD的方式修改。下面的命令把054efc14地址上的值修改为11112222。 0:018>ed 054efc14 11112222 修改后可以用dd命令来查看内存。 0:018>dd 0543fc14 L4 L4参数指定内存区间的长度为4个DWORD,这样输出只有1行, 而不是8行了。 10s 命令用来搜索内存具体见help文档 11!runaway 可以显示每一个线程的cpu消耗 0:018> !runaway 结果如下: 0:83c 0 days 0:00:00.406 13:bd4 0 days 0:00:00.046 10:ac8 0 days 0:00:00.046 24:4f4 0 days 0:00:00.031 上面输出的第一列是线程的编号和线程ID,后一列对应的是该线程在用户态模式中的 总的繁忙时间。 在该命令加上f参数,还可以看到内核态的繁忙时间,当进程内存占用率比较高的时候 ,通过该命令可以方便的找到对应的繁忙线程。 12 ~ 命令是用来切换目标线程 0:018> ~ 可以显示线程的信息 0:018> ~0s把当前的线程切换到0号线程,也就是主线程,切换后提示符会变为0:000. 13 ~* 命令列出当前进程中的所有线程的详细信息 14~*kb命令列出所有线程的堆栈 15 k 命令用来显示当前线程的堆栈,如下 0:018> k 跟d命令一样,k后面也可以跟很多后缀,比如kb kp,kn,kv,kl等,这些后缀控制了 显示的格式和信息。 栈指令k[b|p|P|v] 这四条指令显示的内容类似,但是每个指令都有特色,KB显示三个参数,Kp显示所有的参数,但需要Full Symbols或Private PDBSymbols支持。KP与Kp相似,只是KP将参数换行显示了。Kv用于显示FPO和调用约定,KD,用于显示Stack的Dump,在跟踪栈时比较有用。 这些指令区分大小。 16 u命令把指定地址上的代码翻译成汇编输出 0:018> u 7739d023 USER32!NtUserWaitMessage: 7739d023 b84a120000 mov eax,0x124a 7739d028 ba0003fe7f mov edx,0x7ffe0300 7739d02d ff12 call dword ptr [edx] 7739d02f c3 ret 如果符号文件加载正确,可以用uf命令直接反汇编整个函数,比如uf USER32! NtUserWaitMessage 17 x 查找符号的二进制地址如下 0:018> x msvcr!printf 77bd27c2 msvcrt!printf = 上面的命令找到了printf函数的入口地址在77bd27c2 0:001> x ntdll!GlobalCounter 7c99f72c ntdll!GlobalCounter = 上面的命令表示ntdll!GlobalCounter这个变量保存的地址是7c99f72c。 注意:符号对应的是变量和变量所在的地址,不是变量的值,上面只是找到GlobalCounter这个变量的值是7c99f72,要找到变量的值,需要用d命令读取内存地址来获取。 X命令还支持通配符,比如x ntdll !*命令列出ntdll模块中的所有的符号,以及对应的二进制地址。 18 dds 打印内存地址上的二进制值 同时自动搜索二进制值对应的符号。 比如要看看当前**中保存了那些函数地址,就可以检查ebp指向的内存 0:018>dds ebp 0013ed98 0013ee24 0013ed9c 75ecb30f BROWSEUI!BrowserProtectedThreadProc+0x44 0013eda0 00163820 0013eda4 0013ee50 0013eda8 00163820 0013edac 00000000 0013edb0 0013ee10 0013edb4 75ece83a BROWSEUI!__delayLoadHelper2+0x23a 0013edb8 00000005 0013edbc 0013edcc 0013edc0 0013ee50 0013edc4 00163820 0013edc8 00000000 0013edcc 00000024 0013edd0 75f36d2c BROWSEUI!_DELAY_IMPORT_DESCRIPTOR_SHELL32 0013edd4 75f3a184 BROWSEUI!_imp__SHGetInstanceExplorer 0013edd8 75f36e80 BROWSEUI!_sz_SHELL32 0013eddc 00000001 0013ede0 75f3726a BROWSEUI!urlmon_NULL_THUNK_DATA_DLN+0x116 0013ede4 7c8d0000 SHELL32!_imp__RegCloseKey (SHELL32+0x0) 0013ede8 7c925b34 SHELL32!SHGetInstanceExplorer 这里dds命令从ebp指向的内存地址0013ed98开始打印,第一列是内存地址的值,第二列是地址上对应的二进制数据,第三列是二进制对应的符号。上面的命令自动找到了75ecb390f对应的符号是BROWSEUI!BrowserProtectedThreadProc +0x44. Com interface 和c++ vtable里面的成员函数都是顺序排列的。所以,dds命令可以方便的找到虚函数表中的具体的函数地址,比如用下面的命令可以找到OpaqueDatinfo类型中虚函数的实际函数地址。 首先通过x命令找到OpaqueDataInfo虚函数地址 0:000> x ole32!OpaqueDataInfo::vftable’ 7768265c ole32!OpaqueDataInfo::`vftable'' = 77682680 ole32!OpaqueDataInfo::`vftable'' = 接下来dds命令可以打印出虚函数表中的函数名字 0:000> dds 7768265c 19 .frame 命令在栈中切换以便检查局部变量 要查看局部变量的需要如下: 1查看线程的callstack 0:018>knl 00 0012f7a0 7c821c94 ntdll!KiFastSystemCallRet 01 0012f7a4 7c836066 ntdll!NtRequestWaitReplyPort+0xc 02 0012f7c4 77eaaba3 ntdll!CsrClientCallServer+0x8c 03 0012f8bc 77eaacb8 kernel32!ReadConsoleInternal+0x1b8 04 0012f944 77e41990 kernel32!ReadConsoleA+0x3b 第一列的号称为Frame num,通过.frame命令就可以切换到对应的函数中检查局部变量,比如我们检查kernel32!ReadConsoleA,这个函数的frame num是4,于是,我们如下 2 iframe切换到指定行号的函数中 0:018> .frame 4 3然后调用x显示当前frame的局部变量,比如这个函数中有两个局部变量pcls和rawptr 0:018> x 0012fced pcls = 0x0039ba80 0012fcd8 rawptr = 0x0039ba80 20 dt 格式化显示资料 Dt命令格式化显示变量的资料和结构 0:000> dt pcls Local var @ 0x12fce4 Type MyCls* 0x0039ba80 +0x000 str : 0x00416648 'abcd' +0x004 inobj : inner 上面的命令打印出pcls的类型是MyCls指针,指向的地址是0x0039ba80,其中的两个class成员的偏移分别在+0和+4,对应的值在第2列显示。加上-b -r参数可以显示inner class和数组的信息: 0:000> dt pcls -b -r Local var @ 0x12fce4 Type MyCls* 0x0039ba80 +0x000 str : 0x00416648 'abcd' +0x004 inobj : innner +0x000 arr : 'abcd' [00] 97 ''a'' [01] 98 ''b'' [02] 99 ''c'' [03] 100 ''d'' [04] 0 '''' [05] 0 '''' [06] 0 '''' [07] 0 '''' [08] 0 '''' [09] 0 '''' 对于任意的地址,也可以手动指定符号类型来格式化显示。比如把0x0039ba80地址上的数据用MyCls类型来显示: 0:000> dt 0x0039ba80 MyCls +0x000 str : 0x00416648 'abcd' +0x004 inobj : innner 21bp设定调试断点 比如可以这样写:0:018>bp notepad!WinMain 在notepade的winmain函数处下断点 断点的位置可以用符号来表示,如上,也可以直接用地址以及windbg的Pseudo_Register(虚拟寄存器)。比如,我们用$exentry表示进程的入口,那么可以用bp @$exentry在进程的入口设置断点,如果notepade的winmain的入口地址为01006420,那么断点也可以这么写 Bp 01006420 bp mysource.cpp:143` 'j (poi(MyVar)”0n20) ''''; ''g'' ' 意思就是:当myvar的值等于0x20时,g命令继续执行 下面一个设置条件断点 0:001> bp exceptioninject!foo3 “k; .echo ‘breaks’ ; g” 在exceptioninject!foo3上设置断点后,每次断下来后,先用k显示callstack,然后用.echo命令输出简单的字符串‘breaks’,最后g命令继续执行。 下面看一个更复杂的设置条件断点的例子: ba w4 execptioninject!i ”j(poi(exceptioninject!i)<0n40) ‘.printf//”exceptioninject!i value is :%d//”,poi(exceptioninject!i); g’ ; ‘.echo stop!’ ” 首先ba w4 exceptioninject!i 表示在修改exceptioninject!i这个全局变量的时候,停下来, j(judge)命令的作用就是对后面的表达式作条件判断如果为true,执行第一个单引号里面的命令,否则执行第2个单引号里面的命令。 条件表达式是(poi(exceptioninject!i)<0n40),在windbg中excepioninject!i符号表示符号所在的内存地址,而不是符号的数值,相当于c语言的&操作符的作用,poi命令就是取这个地址上的值,相当于c语言的*操作符。所以这个条件判断的意思就是判断exceptioninject!i的值,是否小于十进制的40。如果为真,就执行第一个单引号,‘.printf//”exceptioninject!i value is :%d//”,poi(exceptioninject!i); g’,如果为假,就执行第二个单引号‘.echo stop!’ 第一个单引号里有三个命令,.printf .echo 和g。这里的printf和c语言的printf函数语法一样,不过由于这个printf命令本身是在ba命令的双引号里面,所以需要用//来转义print中的引号。第一个引号的作用是:打印出当前exceptioninject!i的值,.echo命令换行 g命令继续执行 第二个引号的作用就是显示stop,由于后面没有g命令,所以windbg会停下。 22 bm 使用模式匹配设置断点 这个功能需要符号表的支持,bm可以通过模式一次设置多个断点,比如 bm mydriver!FastIO* 可以将所有与FastIO*模式匹配的函数下设置断点,比如FastIoRead ,FastIoWriter等函数都会被设置上断点。需要注意的是,bm命令需要full or export symbols支持。 23 ba 对内存访问设置断点 break on access 就是对于内存访问设置断点,对于在多核处理或者多核处理器调试的时候很有用,对于调试多线程也很有用,比如说,我们可以对一个全局变量设置断点, ba mydriver!gMonitoreedDevices , 如果你认为这个变量的值被莫名的修改了,相信通过ba设置的断点,你可以很快找到是谁修改的。 也可以这样 ba w4 0x4000000 'kb;g' 当0x4000000地址有写操作时,进入断点 。w表示类型为写 4表示长度为4个字节 24 bl 列出所有的断点 break list 25 bc 清除断点 break clear 26 be 开启断点 break enable 27 bd禁用断点 break disable 以上提到的断点指令通过和j指令很容易形成条件断点,比如 bp USER32!GetMessageW 'r $t1=poi(esp+4);r $t2=poi(@$t1+4); j(@$t2 = 0x102 ) ''du @$t1+8 L2;gc'';''gc''' 这个条件断点,截取WM_CHAR消息,并将字符(包括中文)显示出来。 条件断点的最简形式:bp Address 'j (Condition) ''OptionalCommands''; ''gc'' ' Address是指令的地址,Condition是一个条件表达式,如果@eax=1,''OptionalCommands''是在断点被击中并且表达式成立时要执行的指令;gc指定是从一个条件断点返回,是不可少的一部分。 28跟踪指令T,TA,TB,TC,WT,P,PA,PC T指令单步执行,在源码调试状态下,可指源码的一行,根据不同的选项也可以为一行ASM指令; TA单步跟踪到指定地址,如果没有参数将运行到断点处。 TB执行到分支指令,分支指令包括calls, returns, jumps, counted loops, and while loops TC执行到Call指令 WT Trace and Watch Data,一条强大指令,对执行流程做Profile,执行一下看看结果吧 P,PA,PC相信不用多做解释,大家也都明白了 29源代码操作指令.,lsf,lsc,ls,l,lsp .指令打一个源文件,可以打开一个全路径的文件,也可以通过函数地址来打开并定位到源文件中函数的位置,如. –a myapp!main,. j://mydriver//mydriver.c lsf指定一个源文件为当前源文件,使用lsc可显示当前指定的源文件ls可显示源文件的代码。Lsf可以使用全路径,如果源路径已经设置,也可以直接指定源文件名称。如lsf mydriver.c,lsf j://mydriver//mydriver.c lsc显示当前源文件 ls显示当前源文件的代码,如ls 200显示第200行 l 用于设置源文件选项 lsp 设置源文件行在调试时显示范围比如, 显示当前行的前50,后50,lsp 100 但通常使用Windbg时,可以直接用Ctrl+O来打开并查看源文件 30 查询符号 kd> x nt!KeServiceDescriptorTable* 8046e100 nt!KeServiceDescriptorTableShadow = 8046e0c0 nt!KeServiceDescriptorTable = kd> ln 8046e100 (8046e100) nt!KeServiceDescriptorTableShadow | (8046e140) nt!MmSectionExtendResource Exact matches: nt!KeServiceDescriptorTableShadow = 31!gle 查看LastError值 32指定进制的形式0x/0n/0t/y 分别表示 16/10/8/2进制 ? 0x12345678+0n10 Evaluate expression: 305419906 = 12345682 33!sym noice/quiet symbol prompts开关 34.srcpath 设置源代码的路径 35dv查看本地变量 36!teb 显示当前线程的执行块(execution block) 37!peb 显示当前进程的执行块(execution block) 38ln[Address] 显示当前地址上的对象类型 39!locks 显示死锁 40!handle可以获取整个进程或者某一个handle的详细信息 首先运行以下!handle,可以看到当前进程的每个一个handle的类型,以及统计信息 0:002>!handle Handle 4 Type key Handle c Type keyEvent ……. 然后找到一个key,查看详细信息 0:001>!handle 4 f 就会列出这个handle的详细信息。 41!htrace命令检查操作句柄的历史记录 !htrace命令可以打印出指定的handle的最近几次调用堆栈 0:001>!htrace 384 42!cs列出CriticalSection的详细信息 43!threadpool能看到完成端口,线城池工作线程和timer回调占线程池的情况 44.time 可以看到进程跑了多长时间 45 !dso 查看当前线程中有哪些对象,分析泄露时用到 46.dump保存进程的dump文件 Dump文件是进程的内存镜像, 可当在调试器中打开dump文件时,使用上面的命令检查,看到的结果跟用调试检查进程看到的一样 .dump /ma c://testdump.dmp 这个命令把当前进程的镜像保存为c://testdump.dmp,其中/ms参数表示dump的文件应该包含进程的完整信息。 在windbg中,通过file—open---open Crash dump菜单打开dump文件进行分析。打开文件后,运行调试命令看到的信息和状态就是dump文件保存时进程的状态。通过dump文件能够方便的保存发生问题时进程的状态,方便事后分析。