1. 高级调试概念
1.1 调试模式深入
用户模式调试进阶
进程附加策略
# 非侵入式附加
windbg -pv -p <PID> # 附加但不中断进程
windbg -pvr -p <PID> # 附加并允许进程继续运行
# 子进程调试
windbg -o notepad.exe # 调试notepad及其子进程
调试会话管理
# 分离调试器
.detach # 分离调试器但保持进程运行
.kill # 终止被调试进程
.abandon # 放弃调试会话
# 会话信息
.ttime # 显示目标执行时间
.effmach # 显示有效机器类型
内核模式调试进阶
内核调试连接类型
# 串口调试
windbg -k com:port=COM1,baud=115200
# 网络调试
windbg -k net:port=50000,key=1.2.3.4
# USB调试
windbg -k usb:targetname=MyTarget
# 1394调试
windbg -k 1394:channel=1
内核调试控制
# 中断目标系统
Ctrl+Break # 强制中断
.crash # 触发系统崩溃
.reboot # 重启目标系统
# 内核状态查看
!process 0 0 # 显示所有进程
!thread # 显示当前线程信息
!irql # 显示当前IRQL级别
1.2 调试目标类型
转储文件分析
转储文件类型
# 小型转储(Mini Dump)
.dump /m c:\mini.dmp # 创建小型转储
# 完整转储(Full Dump)
.dump /ma c:\full.dmp # 创建完整转储
# 内核转储
.dump /k c:\kernel.dmp # 创建内核转储
# 活动转储
.dump /mA c:\active.dmp # 创建活动内存转储
转储文件信息
!analyze -v # 自动分析转储
.dumpdebug # 显示转储创建信息
.time # 显示转储时间
!vm # 显示虚拟内存状态
远程调试
调试服务器设置
# 启动调试服务器
windbg -server tcp:port=5005 -p <PID>
# 连接到调试服务器
windbg -remote tcp:server=192.168.1.100,port=5005
# 进程服务器
dbgsrv -t tcp:port=5006
windbg -premote tcp:server=192.168.1.100,port=5006 -p <PID>
远程调试管理
.clients # 显示连接的客户端
.endpsrv # 结束进程服务器
.endsrv # 结束调试服务器
2. 内存分析技术
2.1 堆分析
堆基础信息
!heap # 显示所有堆
!heap -s # 堆统计信息
!heap -a # 显示所有堆的详细信息
!heap -h <堆地址> # 显示特定堆信息
堆损坏检测
!heap -p # 启用页堆
!heap -p -h <堆地址> # 检查特定堆的页堆状态
!heap -x <地址> # 查找地址所属的堆块
!heap -flt s <大小> # 查找指定大小的堆块
堆泄漏分析
# 启用堆跟踪
gflags -i myapp.exe +hpa +hpc
# 分析堆泄漏
!heap -stat -h 0 # 详细堆统计
!heap -flt s 100 # 查找100字节的分配
!heap -p -a <地址> # 显示分配调用堆栈
2.2 虚拟内存分析
虚拟内存布局
!address # 显示虚拟内存布局
!address -summary # 虚拟内存摘要
!address <地址> # 显示特定地址的内存信息
!vadump # 转储VAD树
内存保护和属性
!vprot <地址> # 显示内存保护属性
!vm # 虚拟内存统计
!poolused # 内核池使用情况
!memusage # 内存使用分析
内存泄漏检测
# 用户模式内存泄漏
!heap -stat -h 0
!heap -flt s 0x1000 # 查找4KB分配
# 内核模式内存泄漏
!poolused 2 # 显示非分页池使用
!poolfind <标签> # 查找特定标签的池分配
2.3 句柄分析
句柄信息
!handle # 显示所有句柄
!handle 0 f # 显示所有句柄的详细信息
!handle <句柄值> # 显示特定句柄信息
!handle 0 f File # 显示所有文件句柄
句柄泄漏检测
# 句柄计数
!process <进程地址> 1 # 显示进程句柄信息
# 句柄跟踪
gflags -i myapp.exe +htc # 启用句柄跟踪
!htrace # 显示句柄跟踪信息
3. 线程和同步分析
3.1 线程状态分析
线程信息
~ # 显示所有线程
~*k # 显示所有线程堆栈
~<线程号>s # 切换到指定线程
!thread # 显示当前线程详细信息
!thread <线程地址> # 显示特定线程信息
线程状态
!runaway # 显示线程CPU使用时间
!runaway 7 # 详细的线程时间信息
!ready # 显示就绪线程
!running # 显示正在运行的线程
线程上下文
.thread <线程地址> # 设置线程上下文
.cxr <上下文地址> # 设置上下文记录
.trap <陷阱帧地址> # 设置陷阱帧
3.2 同步对象分析
临界区分析
!cs # 显示所有临界区
!cs -l # 显示锁定的临界区
!cs <地址> # 显示特定临界区信息
!cs -o # 显示临界区所有者
互斥体和事件
!handle 0 f Mutant # 显示所有互斥体
!handle 0 f Event # 显示所有事件
!object <对象地址> # 显示对象信息
死锁检测
!deadlock # 检测死锁
!locks # 显示内核锁信息
!irql # 显示IRQL级别
!spinlock <地址> # 显示自旋锁信息
3.3 等待链分析
等待链显示
!wdfkd.wdfwaitlock # WDF等待锁分析
!analyze -hang # 分析挂起问题
!analyze -hang -v # 详细挂起分析
阻塞分析
# 查找阻塞线程
~*k # 所有线程堆栈
!uniqstack # 唯一堆栈
!findstack <符号> # 查找包含特定符号的堆栈
4. 异常和错误分析
4.1 异常处理机制
异常记录分析
.exr -1 # 显示最后异常记录
.exr <异常记录地址> # 显示特定异常记录
.cxr <上下文地址> # 显示异常上下文
异常类型分析
# 访问违例分析
!analyze -v # 自动分析访问违例
ln <故障地址> # 查找故障地址符号
!address <故障地址> # 分析故障地址内存属性
# 堆栈溢出分析
!analyze -v
k 100 # 显示深层堆栈
!address @esp # 检查堆栈内存
SEH链分析
!exchain # 显示SEH链
!exchain /f # 显示完整SEH链
!cppexr # 分析C++异常
4.2 崩溃分析技术
自动崩溃分析
!analyze -v # 详细自动分析
!analyze -hang # 挂起分析
!analyze -f # 函数分析
!analyze -D # 默认分析
手动崩溃分析
# 分析步骤
1. 检查异常信息: .exr -1
2. 设置异常上下文: .cxr <地址>
3. 查看调用堆栈: k
4. 分析故障指令: u @eip
5. 检查内存状态: !address <故障地址>
6. 查看模块信息: lm
蓝屏分析
# 内核崩溃分析
!analyze -v # 自动分析蓝屏
!bugcheck # 显示蓝屏代码
!error <错误代码> # 解释错误代码
!vm # 虚拟内存状态
!process 0 0 # 进程列表
4.3 错误代码分析
Windows错误代码
!error <错误代码> # 解释Windows错误代码
!gle # 显示最后错误
!teb # 显示TEB信息
NTSTATUS代码
!error <NTSTATUS> # 解释NTSTATUS代码
.formats <数值> # 显示数值的各种格式
5. 性能分析技术
5.1 CPU性能分析
CPU使用率分析
!runaway # 线程CPU时间
!runaway 7 # 详细CPU时间信息
.time # 显示时间信息
!perfctr # 性能计数器
热点函数分析
# 采样分析
bp kernel32!* "g" # 在所有kernel32函数设置断点
!uniqstack # 分析唯一堆栈
指令级性能分析
# 单步性能测试
.time; t; .time # 测量单条指令时间
# 函数性能测试
.time; gu; .time # 测量函数执行时间
5.2 内存性能分析
内存分配性能
!heap -stat -h 0 # 堆分配统计
!heap -flt s 0x1000 # 查找大块分配
!poolused # 内核池使用
缓存性能分析
!vm # 虚拟内存统计
!pfn <页帧号> # 页帧信息
!memusage # 内存使用分析
5.3 I/O性能分析
文件I/O分析
!handle 0 f File # 显示文件句柄
!irp # 显示I/O请求包
!devobj <设备对象> # 设备对象信息
网络I/O分析
!handle 0 f Socket # 显示套接字句柄
!netstat # 网络连接状态
6. 驱动程序调试
6.1 驱动程序基础调试
驱动程序信息
!drvobj <驱动对象> # 显示驱动对象信息
!devobj <设备对象> # 显示设备对象信息
!devnode 0 1 # 显示设备节点树
lm t n # 按类型列出模块
驱动程序加载
.load <驱动路径> # 加载驱动符号
.unload <模块名> # 卸载模块
!reload <模块名> # 重新加载模块符号
6.2 I/O请求分析
IRP分析
!irp <IRP地址> # 显示IRP信息
!irpfind <设备对象> # 查找设备的IRP
!irpzone # 显示IRP区域
I/O堆栈分析
!irp <IRP地址> 1 # 显示IRP和I/O堆栈
!iospace # 显示I/O空间
6.3 即插即用调试
PnP设备树
!devnode 0 1 # 显示设备树
!devnode <设备节点> 1 # 显示特定设备节点
!arbiter 4 # 显示仲裁器信息
电源管理
!poaction # 显示电源操作
!popolicy # 显示电源策略
!potrigger # 显示电源触发器
7. .NET和托管代码调试
7.1 .NET调试扩展
SOS扩展加载
.loadby sos clr # 加载SOS扩展(.NET Framework)
.loadby sos coreclr # 加载SOS扩展(.NET Core)
基本.NET信息
!version # 显示CLR版本
!eeversion # 显示执行引擎版本
!threads # 显示托管线程
!clrstack # 显示托管调用堆栈
7.2 托管堆分析
堆信息
!eeheap # 显示托管堆信息
!eeheap -gc # 显示GC堆信息
!heapstat # 堆统计信息
!dumpheap # 转储堆对象
对象分析
!do <对象地址> # 显示对象信息
!dumpobj <对象地址> # 转储对象
!objsize <对象地址> # 显示对象大小
!gcroot <对象地址> # 查找GC根
7.3 垃圾回收分析
GC信息
!gcinfo # 显示GC信息
!gchandles # 显示GC句柄
!finalizequeue # 显示终结队列
!syncblk # 显示同步块
内存泄漏分析
!dumpheap -stat # 按类型统计堆对象
!dumpheap -mt <方法表> # 转储特定类型的对象
!gcroot <对象地址> # 查找对象引用链
8. 脚本和自动化
8.1 WinDbg脚本
脚本文件
# 创建脚本文件 debug.wds
.echo "Starting automated analysis"
!analyze -v
k
lm
.echo "Analysis complete"
# 执行脚本
$$>< c:\debug.wds
条件脚本
# 条件执行脚本
.if (@eax == 0) {
.echo "EAX is zero"
k
} .else {
.echo "EAX is not zero"
r eax
}
8.2 JavaScript脚本
JavaScript扩展
// 示例JavaScript脚本
function analyzeThreads() {
var control = host.namespace.Debugger.Utility.Control;
var output = control.ExecuteCommand("~*k");
host.diagnostics.debugLog("Thread analysis:\n");
for (var line of output) {
host.diagnostics.debugLog(line + "\n");
}
}
// 执行脚本
.scriptload c:\analyze_threads.js
dx @$scriptContents.analyzeThreads()
数据模型扩展
// 扩展数据模型
class ProcessAnalyzer {
get Threads() {
return host.currentProcess.Threads;
}
get HeapInfo() {
var control = host.namespace.Debugger.Utility.Control;
return control.ExecuteCommand("!heap -s");
}
}
// 注册扩展
host.namedModelParents.ProcessAnalyzer = ProcessAnalyzer;
8.3 自动化调试流程
批量分析脚本
@echo off
echo Batch dump analysis starting...
for %%f in (*.dmp) do (
echo Analyzing %%f
windbg -z "%%f" -c "!analyze -v; .logopen %%f.log; k; lm; .logclose; q"
)
echo Batch analysis complete
持续监控脚本
# 监控脚本 monitor.wds
.while (1) {
.echo "=== Monitoring at:"
.time
!runaway
!heap -s
.sleep 5000
}
9. 高级分析案例
9.1 内存损坏分析
堆损坏检测
# 启用页堆
gflags -i myapp.exe +hpa
# 分析堆损坏
!heap -p -h 0 # 检查页堆状态
!heap -p -a <地址> # 显示分配信息
!heap -p -l # 显示泄漏信息
缓冲区溢出分析
# 分析访问违例
!analyze -v
.exr -1 # 异常记录
.cxr <上下文地址> # 设置上下文
k # 调用堆栈
u @eip # 反汇编故障指令
!address <故障地址> # 内存属性
9.2 性能问题分析
CPU占用过高
# 分析CPU使用
!runaway 7 # 详细线程时间
~*k # 所有线程堆栈
!uniqstack # 唯一堆栈分析
# 热点函数分析
bp kernel32!* "g" # 函数调用统计
内存泄漏分析
# 用户模式内存泄漏
!heap -stat -h 0 # 堆统计
!heap -flt s 0x1000 # 大块分配
# 托管内存泄漏
!dumpheap -stat # 托管堆统计
!gcroot <对象地址> # 引用链分析
9.3 死锁分析
用户模式死锁
!cs -l # 锁定的临界区
!cs -o # 临界区所有者
~*k # 所有线程堆栈
!analyze -hang # 挂起分析
内核模式死锁
!deadlock # 死锁检测
!locks # 内核锁信息
!thread # 线程信息
!irql # IRQL级别
小结
本章深入介绍了WinDbg的高级调试和分析技术:
- 高级调试概念:掌握了用户模式和内核模式的高级调试技巧
- 内存分析技术:学习了堆分析、虚拟内存分析和句柄分析
- 线程和同步分析:了解了线程状态分析和同步对象分析
- 异常和错误分析:掌握了异常处理机制和崩溃分析技术
- 性能分析技术:学习了CPU、内存和I/O性能分析方法
- 驱动程序调试:了解了驱动程序和I/O请求的调试技巧
- .NET调试:掌握了托管代码的调试和分析方法
- 脚本和自动化:学习了脚本编写和自动化调试流程
- 高级分析案例:通过实际案例学习了复杂问题的分析方法
下一章将学习WinDbg在实际项目中的应用和最佳实践。