Stamp of Software Debugging
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
navigation bar seprate line

《软件调试(第二版)》卷2目录

*页码以实际印刷为准

第一篇 大 局 观

第1 章 Windows 系统简史..................... 2
1.1 源于DOS ........................................... 2
1.2 功在NT.............................................. 4
1.3 Windows 2000 彰显实力................... 6
1.4 巅峰之作:Windows XP 和
Windows Server 2003 ........................ 8
1.5 Windows Vista 折戟沙场................... 9
1.6 Windows 7 享利中兴....................... 11
1.7 Windows 8 革新受挫....................... 13
1.8 Windows 10 何去何从..................... 15
1.9 本章总结.......................................... 17
参考资料................................................... 18
第2 章 进程和线程.................................19
2.1 任务.................................................. 19
2.2 进程资源.......................................... 19
2.3 进程空间.......................................... 22
2.3.1 32 位进程空间.......................... 22
2.3.2 64 位进程空间.......................... 24
2.4 EPROCESS 结构............................. 25
2.5 PEB................................................... 28
2.6 内核模式和用户模式...................... 30
2.6.1 访问模式................................... 30
2.6.2 使用INT 2E 切换到内核模式........................................... 31
2.6.3 快速系统调用........................... 32
2.6.4 逆向调用................................... 37
2.6.5 实例分析................................... 37
2.7 线程.................................................. 38
2.7.1 ETHREAD................................. 38
2.7.2 TEB............................................43
2.8 WoW 进程........................................44
2.8.1 架构...........................................44
2.8.2 工作过程...................................45
2.8.3 注册表重定向...........................47
2.8.4 注册表反射...............................47
2.8.5 文件系统重定向.......................47
2.9 创建进程..........................................48
2.10 最小进程和Pico 进程...................48
2.10.1 最小进程.................................49
2.10.2 Pico 进程.................................50
2.11 任务管理器.....................................52
2.12 本章总结........................................53
参考资料...................................................54
第3 章 架构和系统部件.........................55
3.1 系统概览..........................................55
3.1.1 内核空间...................................55
3.1.2 用户空间...................................56
3.2 内核和HAL 模块............................57
3.2.1 内核文件...................................57
3.2.2 HAL 文件..................................59
3.3 空闲进程..........................................61
3.4 系统进程..........................................63
3.5 内核空间的其他模块......................65
3.6 NTDLL.DLL ....................................66
3.6.1 角色...........................................66
3.6.2 调用系统服务的桩函数...........66
3.6.3 映像文件加载器.......................67
3.6.4 运行时库...................................67
3.6.5 其他功能...................................67
3.7 环境子系统......................................68
3.8 原生进程.......................................... 69
3.8.1 特点........................................... 69
3.8.2 SMSS......................................... 70
3.8.3 CSRSS ....................................... 71
3.9 本章总结.......................................... 72
参考资料................................................... 72
第4 章 启动过程.....................................73
4.1 BootMgr............................................ 73
4.1.1 工作过程................................... 73
4.1.2 调试方法................................... 74
4.2 WinLoad ........................................... 75
4.3 内核初始化...................................... 76
4.3.1 NT 的入口函数......................... 76
4.3.2 内核初始化............................... 78
4.4 执行体的阶段0 初始化.................. 80
4.4.1 总体过程...................................80
4.4.2 创建特殊进程...........................81
4.5 执行体的阶段1 初始化..................84
4.5.1 Phase1Initialization....................84
4.5.2 唤醒其他CPU...........................85
4.5.3 非启动CPU 的起步路线.........86
4.5.4 漫长的I/O 初始化....................86
4.5.5 更新进度...................................87
4.6 创建用户空间..................................87
4.6.1 创建会话管理器进程...............88
4.6.2 建立环境子系统.......................89
4.6.3 创建窗口站和桌面...................91
4.6.4 用户登录...................................92
4.7 本章总结..........................................93
参考资料...................................................93

第二篇 探 微

第5 章 特殊的过程调用.........................97
5.1 异步过程调用.................................. 97
5.2 中断请求级别................................ 101
5.2.1 设计初衷................................. 101
5.2.2 基本原理................................. 102
5.2.3 析疑......................................... 103
5.3 延迟过程调用................................ 104
5.3.1 使用模式................................. 104
5.3.2 黏滞在DPC ............................ 106
5.4 本地过程调用................................ 106
5.5 远程过程调用................................ 109
5.5.1 工作模型................................. 110
5.5.2 RPC 子系统服务..................... 110
5.5.3 端点和协议串......................... 111
5.5.4 蜂巢......................................... 112
5.5.5 案例和调试方法..................... 113
5.6 本章总结........................................ 117
参考资料................................................. 118
第6 章 垫片............................................ 119
6.1 垫片数据库.................................... 119
6.1.1 认识SDB 文件........................119
6.1.2 定制的SDB 文件....................121
6.1.3 修补模式.................................122
6.2 AppHelp..........................................123
6.2.1 SDB 功能.................................123
6.2.2 垫片引擎.................................124
6.2.3 AD 挂钩...................................125
6.2.4 穿山甲挂钩.............................126
6.3 垫片动态库....................................126
6.3.1 AcLayers.DLL .........................126
6.3.2 AcGenral.DLL 和AcSpecfc.DLL.........................127
6.3.3 其他垫片模块.........................127
6.4 应用程序垫片的工作过程............127
6.4.1 在父进程中准备垫片数据.....128
6.4.2 在新进程中加载和初始化垫片引擎.................................128
6.4.3 加载垫片模块.........................129
6.4.4 落实挂钩.................................129
6.4.5 执行垫片.................................131
6.5 内核垫片引擎................................132
6.5.1 数据和配置............................. 132
6.5.2 初始化..................................... 133
6.5.3 KSE 垫片结构......................... 133
6.5.4 注册垫片................................. 135
6.5.5 部署垫片................................. 136
6.5.6 执行垫片................................. 136
6.6 本章总结........................................ 137
参考资料................................................. 138
第7 章 托管世界...................................139
7.1 简要历史........................................ 139
7.2 宏伟蓝图........................................ 140
7.3 类和方法表.................................... 141
7.4 辅助调试线程................................ 145
7.4.1 托管调试模型......................... 145
7.4.2 RCThread................................. 147
7.4.3 刺探线程................................. 149
7.5 CLR4 的调试模型重构................. 149
7.6 SOS 扩展........................................ 151
7.6.1 加载SOS.................................151
7.6.2 设置断点.................................152
7.6.3 简要原理.................................153
7.7 本章总结........................................154
参考资料.................................................154
第8 章 Linux 子系统.............................155
8.1 源于Drawbridge ............................155
8.2 融入NT..........................................156
8.3 总体架构........................................157
8.4 子系统内核模块............................157
8.5 微软版Linux 内核.........................158
8.6 Linux 子系统服务器......................159
8.7 WSL 启动器...................................160
8.8 交叉开发........................................161
8.9 WSL2..............................................163
8.10 本章总结......................................164
参考资料.................................................164

第三篇 操作系统的调试支持

第9 章 用户态调试模型.......................167
9.1 概览................................................ 167
9.1.1 参与者..................................... 168
9.1.2 调试子系统............................. 168
9.1.3 调试事件驱动......................... 169
9.2 采集调试消息................................ 169
9.2.1 消息常量................................. 169
9.2.2 进程和线程创建消息............. 170
9.2.3 进程和线程退出消息............. 170
9.2.4 模块映射和反映射消息......... 171
9.2.5 异常消息................................. 172
9.3 发送调试消息................................ 173
9.3.1 调试消息结构......................... 173
9.3.2 DbgkpSendApiMessage函数......................................... 174
9.3.3 控制被调试进程..................... 174
9.4 调试子系统服务器(Windows XP 之后) ...................175
9.4.1 DebugObject ............................176
9.4.2 创建调试对象.........................176
9.4.3 设置调试对象.........................176
9.4.4 传递调试消息.........................177
9.4.5 杜撰的调试消息.....................178
9.4.6 清除调试对象.........................179
9.4.7 内核服务.................................179
9.4.8 全景.........................................180
9.5 调试子系统服务器(Windows XP 之前)....................182
9.5.1 概览.........................................182
9.5.2 Windows 会话管理器.............183
9.5.3 Windows 环境子系统服务器进程.........................................184
9.5.4 调用CSRSS 的服务...............185
9.5.5 CsrCreateProcess 服务............ 186
9.5.6 CsrDebugProcess 服务............ 187
9.6 比较两种模型................................ 188
9.6.1 Windows 2000 调试子系统的优点..................................... 189
9.6.2 Windows 2000 调试子系统的安全问题............................. 189
9.6.3 Windows XP 的调试模型的优点..................................... 190
9.6.4 Windows XP 引入的新调试功能......................................... 190
9.7 NTDLL.DLL 中的调试支持例程................................................ 191
9.7.1 DbgUi 函数............................. 191
9.7.2 DbgSs 函数............................. 192
9.7.3 Dbg 函数................................. 192
9.8 调试API......................................... 193
9.9 本章总结........................................ 194
参考资料................................................. 194
第10 章 用户态调试过程....................195
10.1 调试器进程.................................. 195
10.1.1 线程模型............................... 195
10.1.2 调试器的工作线程............... 196
10.1.3 DbgSsReserved 字段............. 197
10.2 被调试进程.................................. 198
10.2.1 特征....................................... 198
10.2.2 DebugPort 字段..................... 199
10.2.3 BeingDebugged 字段............ 199
10.2.4 观察DebugPort 字段和BeingDebugged 字段....... 199
10.2.5 调试会话............................... 201
10.3 从调试器中启动被调试程序...... 201
10.3.1 CreateProcess API ................. 201
10.3.2 第一批调试事件................... 203
10.3.3 初始断点............................... 204
10.3.4 自动启动调试器................... 205
10.4 附加到已经启动的进程中.......... 206
10.4.1 DebugActiveProcess API ...... 206
10.4.2 示例:TinyDbgr 程序.......... 207
10.5 处理调试事件..............................209
10.5.1 DEBUG_EVENT 结构.........209
10.5.2 WaitForDebugEvent API .......210
10.5.3 调试事件循环.......................211
10.5.4 回复调试事件.......................213
10.5.5 定制调试器的事件处理方式.......................................214
10.6 中断到调试器..............................216
10.6.1 初始断点...............................216
10.6.2 编程时加入断点...................216
10.6.3 通过调试器设置断点...........216
10.6.4 通过远程线程触发断点异常.......................................217
10.6.5 在线程当前执行位置设置断点.......................................218
10.6.6 动态调用远程函数...............219
10.6.7 挂起中断...............................220
10.6.8 调试快捷键(F12 键) ........221
10.6.9 窗口更新...............................221
10.7 输出调试字符串..........................222
10.7.1 发送调试信息.......................223
10.7.2 使用调试器接收调试信息...223
10.7.3 使用工具接收调试信息.......224
10.8 终止调试会话..............................228
10.8.1 被调试进程退出...................228
10.8.2 调试器进程退出...................229
10.8.3 分离被调试进程...................231
10.8.4 退出时分离...........................232
10.9 本章总结......................................233
参考资料.................................................233
第11 章 中断和异常管理.....................234
11.1 中断描述符表...............................234
11.1.1 概况........................................234
11.1.2 门描述符................................235
11.1.3 执行中断和异常处理函数...236
11.1.4 IDT 一览................................239
11.2 异常的描述和登记......................240
11.2.1 EXCEPTION_RECORD结构........................................241
11.2.2 登记CPU 异常..................... 242
11.2.3 登记软件异常....................... 243
11.3 异常分发过程.............................. 244
11.3.1 KiDispatchException 函数.... 244
11.3.2 内核态异常的分发过程....... 244
11.3.3 用户态异常的分发过程....... 246
11.3.4 归纳....................................... 248
11.4 结构化异常处理.......................... 249
11.4.1 SEH 简介............................... 249
11.4.2 SHE 机制的终结处理........... 249
11.4.3 SEH 机制的异常处理........... 252
11.4.4 过滤表达式........................... 253
11.4.5 异常处理块........................... 256
11.4.6 嵌套使用终结处理和异常处理............................... 258
11.5 向量化异常处理.......................... 259
11.5.1 登记和注销........................... 259
11.5.2 调用结构化异常处理器....... 260
11.5.3 示例....................................... 261
11.6 本章总结...................................... 264
参考资料................................................. 264
第12 章 未处理异常和JIT 调试........265
12.1 简介.............................................. 265
12.2 默认的异常处理器...................... 266
12.2.1 BaseProcessStart 函数中的结构化异常处理器................ 266
12.2.2 编译器插入的SEH 处理器........................... 267
12.2.3 基于信号的异常处理........... 269
12.2.4 实验:观察默认的异常处理器................................... 270
12.2.5 BaseThreadStart 函数中的结构化异常处理器............... 272
12.3 未处理异常过滤函数.................. 273
12.3.1 Windows XP 之前的异常处理机制............................... 273
12.3.2 Windows XP 中的异常处理机制............................... 276
12.4 “应用程序错误”对话框........ 282
12.4.1 用HardError 机制提示应用程序错误...............................282
12.4.2 使用ReportFault API 提示应用程序错误...............................284
12.5 JIT 调试和Dr. Watson .................286
12.5.1 配置JIT 调试器....................286
12.5.2 启动JIT 调试器....................288
12.5.3 自己编写JIT 调试器............290
12.6 顶层异常过滤函数......................291
12.6.1 注册.......................................291
12.6.2 C 运行时库的顶层过滤函数.......................................292
12.6.3 执行.......................................293
12.6.4 调试.......................................294
12.7 Dr. Watson.....................................294
12.7.1 配置和查看模式...................295
12.7.2 设置为默认的JIT 调试器....296
12.7.3 JIT 调试模式.........................296
12.8 DRWTSN32 的日志文件.............297
12.8.1 异常信息...............................297
12.8.2 系统信息...............................298
12.8.3 任务列表...............................298
12.8.4 模块列表...............................298
12.8.5 线程状态...............................298
12.8.6 函数调用序列.......................299
12.8.7 原始栈数据...........................300
12.9 用户态转储文件..........................300
12.9.1 文件格式概览.......................300
12.9.2 数据流...................................301
12.9.3 产生转储文件.......................302
12.9.4 读取转储文件.......................303
12.9.5 利用转储文件分析问题.......304
12.10 本章总结....................................306
参考资料.................................................306
第13 章 硬错误和蓝屏.........................307
13.1 硬错误提示..................................307
13.1.1 缺盘错误...............................308
13.1.2 NtRaiseHardError ..................308
13.1.3 ExpRaiseHardError................309
13.1.4 CSRSS 中的分发过程.......... 310
13.2 蓝屏终止...................................... 313
13.2.1 简介....................................... 314
13.2.2 发起和产生过程................... 315
13.2.3 诊断蓝屏错误....................... 317
13.2.4 手工触发蓝屏....................... 317
13.3 系统转储文件.............................. 317
13.3.1 分类....................................... 318
13.3.2 文件格式............................... 318
13.3.3 产生方法............................... 320
13.4 分析系统转储文件...................... 320
13.4.1 初步分析............................... 320
13.4.2 线程和栈回溯....................... 321
13.4.3 陷阱帧................................... 323
13.4.4 自动分析............................... 323
13.5 辅助的错误提示方法.................. 326
13.5.1 MessageBeep......................... 326
13.5.2 Beep 函数.............................. 328
13.5.3 闪动窗口............................... 329
13.6 配置错误提示机制...................... 329
13.6.1 SetErrorMode API................. 330
13.6.2 IoSetThreadHardErrorMode... 331
13.6.3 蓝屏后自动重启................... 332
13.7 防止滥用错误提示机制.............. 333
13.8 本章总结...................................... 334
参考资料................................................. 334
第14 章 错误报告.................................335
14.1 WER 1.0 ....................................... 335
14.1.1 客户端................................... 335
14.1.2 报告模式............................... 337
14.1.3 传输方式............................... 337
14.2 系统错误报告.............................. 338
14.3 WER 服务器端............................ 340
14.3.1 WER 服务............................. 340
14.3.2 错误报告分类方法............... 341
14.3.3 报告回应............................... 341
14.4 WER 2.0 ....................................... 341
14.4.1 模块变化............................... 342
14.4.2 创建报告............................... 342
14.4.3 提交报告...............................343
14.4.4 典型应用...............................344
14.5 CER...............................................345
14.6 本章总结......................................346
参考资料.................................................346
第15 章 日志..........................................347
15.1 日志简介......................................347
15.2 ELF 的架构..................................348
15.2.1 ELF 的日志文件...................348
15.2.2 事件源...................................349
15.2.3 ELF 服务...............................350
15.3 ELF 的数据组织..........................350
15.3.1 日志记录...............................350
15.3.2 添加日志记录.......................351
15.3.3 API 一览................................353
15.4 查看和使用ELF 日志.................353
15.5 CLFS 的组成和原理....................354
15.5.1 组成.......................................354
15.5.2 存储结构...............................355
15.5.3 LSN........................................356
15.6 CLFS 的使用方法........................356
15.6.1 创建日志文件.......................356
15.6.2 添加CLFS 容器....................357
15.6.3 创建编组区...........................357
15.6.4 添加日志记录.......................357
15.6.5 读日志记录...........................358
15.6.6 查询信息...............................358
15.6.7 管理和备份...........................359
15.7 本章总结......................................359
参考资料.................................................359
第16 章 事件追踪.................................360
16.1 简介..............................................360
16.2 ETW 的架构.................................361
16.3 提供ETW 消息............................362
16.4 控制ETW 会话............................364
16.5 消耗ETW 消息............................365
16.6 格式描述......................................366
16.6.1 MOF 文件..............................367
16.6.2 WPP....................................... 368
16.7 NT 内核记录器............................ 369
16.7.1 观察NKL 的追踪事件......... 369
16.7.2 编写代码控制NKL.............. 370
16.7.3 NKL 的实现.......................... 372
16.8 Global Logger Session ................. 373
16.8.1 启动GLS 会话...................... 373
16.8.2 配置GLS............................... 373
16.8.3 在驱动程序中使用GLS....... 374
16.8.4 自动记录器........................... 375
16.8.5 BootVis 工具......................... 375
16.9 Crimson API ................................. 376
16.9.1 发布事件............................... 376
16.9.2 消耗事件............................... 377
16.9.3 格式描述............................... 377
16.9.4 收集和观察事件................... 378
16.9.5 Crimson API 的实现............. 378
16.10 本章总结.................................... 379
参考资料................................................. 379
第17 章 WHEA.....................................380
17.1 目标、架构和PSHED.DLL........ 380
17.1.1 目标....................................... 380
17.1.2 架构....................................... 381
17.1.3 PSHED.DLL.......................... 383
17.2 错误源.......................................... 384
17.2.1 标准的错误源....................... 384
17.2.2 通过ACPI 表来定义错误源................................... 384
17.2.3 通过PSHED 插件来报告错误源........................... 385
17.3 错误处理过程.............................. 386
17.3.1 WHEA_ERROR_PACKET结构........................................ 386
17.3.2 处理过程............................... 387
17.3.3 WHEA_ERROR_RECORD结构....................................... 388
17.3.4 固件优先模式....................... 389
17.4 错误持久化.................................. 390
17.4.1 ERST......................................390
17.4.2 工作过程...............................391
17.5 注入错误......................................392
17.6 本章总结......................................392
参考资料.................................................392
第18 章 内核调试引擎.........................393
18.1 概览..............................................393
18.1.1 KD..........................................394
18.1.2 角色.......................................394
18.1.3 组成.......................................394
18.1.4 模块文件...............................396
18.1.5 版本差异...............................396
18.2 连接..............................................396
18.2.1 串行端口...............................397
18.2.2 1394 .......................................398
18.2.3 USB 2.0..................................400
18.2.4 管道.......................................401
18.2.5 选择连接方式.......................403
18.2.6 解决连接问题.......................403
18.3 启用..............................................404
18.3.1 BOOT.INI ..............................404
18.3.2 BCD .......................................405
18.3.3 高级启动选项.......................406
18.4 初始化..........................................407
18.4.1 Windows 系统启动过程概述.......................................407
18.4.2 第一次调用KdInitSystem ....409
18.4.3 第二次调用KdInitSystem ....410
18.4.4 通信扩展模块的阶段1初始化...................................410
18.5 内核调试协议..............................411
18.5.1 数据包...................................411
18.5.2 报告状态变化.......................412
18.5.3 访问目标系统.......................414
18.5.4 恢复目标系统执行...............416
18.5.5 版本.......................................416
18.5.6 典型对话过程.......................417
18.5.7 KdTalker ................................419
18.6 与内核交互.................................. 419
18.6.1 中断到调试器....................... 420
18.6.2 KdpSendWaitContinue .......... 420
18.6.3 退出调试器........................... 421
18.6.4 轮询中断包........................... 422
18.6.5 接收和报告异常事件........... 423
18.6.6 调试服务............................... 423
18.6.7 打印调试信息....................... 425
18.6.8 加载调试符号....................... 426
18.6.9 更新系统文件....................... 426
18.7 建立和维持连接.......................... 427
18.7.1 最早的调试机会................... 428
18.7.2 初始断点............................... 431
18.7.3 断开和重新建立连接........... 433
18.8 本地内核调试.............................. 434
18.8.1 LiveKD .................................. 434
18.8.2 Windows 系统自己的本地内核调试支持............................... 434
18.8.3 安全问题............................... 436
18.9 本章总结...................................... 436
参考资料................................................. 436
第19 章 验证机制.................................437
19.1 简介.............................................. 437
19.1.1 驱动程序验证器................... 438
19.1.2 应用程序验证器................... 438
19.1.3 WHQL 测试.......................... 438
19.2 驱动验证器的工作原理.............. 438
19.2.1 设计原理...............................438
19.2.2 初始化...................................439
19.2.3 挂接验证函数.......................441
19.2.4 验证函数的执行过程...........442
19.2.5 报告验证失败.......................443
19.3 使用驱动验证器..........................443
19.3.1 验证项目...............................443
19.3.2 启用驱动验证器...................444
19.3.3 开始验证...............................446
19.3.4 观察验证情况.......................446
19.3.5 WinDBG 的扩展命令...........447
19.4 应用程序验证器的工作原理......448
19.4.1 原理和组成...........................448
19.4.2 初始化...................................448
19.4.3 挂接API................................450
19.4.4 验证函数的执行过程...........452
19.4.5 报告验证失败.......................453
19.4.6 验证停顿...............................454
19.5 使用应用程序验证器..................454
19.5.1 应用验证管理器...................454
19.5.2 验证项目...............................455
19.5.3 配置验证属性.......................456
19.5.4 配置验证停顿.......................456
19.5.5 编程调用...............................457
19.5.6 调试扩展...............................457
19.6 本章总结......................................457
参考资料.................................................458

第四篇 编译器的调试支持

第20 章 编译和编译期检查................461
20.1 程序的构建过程.......................... 461
20.1.1 链接器................................... 461
20.1.2 加载器................................... 462
20.2 编译.............................................. 462
20.2.1 前端....................................... 463
20.2.2 后端....................................... 463
20.3 Visual C++编译器........................ 463
20.3.1 MSVC 简史........................... 464
20.3.2 MSVC6.................................. 465
20.3.3 VS7 和VS8........................... 465
20.3.4 构建程序............................... 466
20.3.5 调试....................................... 467
20.4 编译错误和警告.......................... 468
20.4.1 错误ID 和来源..................... 468
20.4.2 编译警告............................... 468
20.5 编译期检查.................................. 469
20.5.1 未初始化的局部变量........... 470
20.5.2 类型不匹配........................... 470
20.5.3 使用编译器指令................... 471
20.5.4 标注....................................... 471
20.5.5 驱动程序静态验证器........... 471
20.6 标准标注语言.............................. 472
20.6.1 缓冲区标注符....................... 472
20.6.2 高级标注符........................... 474
20.7 本章总结...................................... 474
参考资料................................................. 475
第21 章 运行时库和运行期检查........476
21.1 C/C++运行时库........................... 476
21.1.1 C 运行时库............................476
21.1.2 C++标准库............................477
21.2 链接运行时库..............................479
21.2.1 静态链接和动态链接...........479
21.2.2 lib 文件..................................480
21.3 运行时库的初始化和清理..........481
21.3.1 介入方法...............................481
21.3.2 初始化...................................482
21.3.3 多个运行时库实例...............484
21.4 运行期检查..................................484
21.4.1 自动的运行期检查...............485
21.4.2 断言.......................................486
21.4.3 _RPT 宏.................................489
21.5 报告运行期检查错误..................489
21.5.1 _CrtDbgReport ......................489
21.5.2 _CrtSetReportMode...............491
21.5.3 _CrtSetReportFile ..................492
21.5.4 _CrtSetReportHook ...............493
21.5.5 _CrtSetReportHook2 .............493
21.5.6 使用其他函数报告RTC
错误.......................................493
21.6 本章总结......................................494
参考资料.................................................494
第22 章 栈和函数调用.........................495
22.1 简介..............................................495
22.1.1 用户态栈和内核态栈...........496
22.1.2 函数、过程和方法...............498
22.2 栈的创建过程..............................498
22.2.1 内核态栈的创建...................498
22.2.2 用户态栈的创建...................499
22.2.3 跟踪用户态栈的创建过程... 501
22.3 CALL 和RET 指令..................... 503
22.3.1 CALL 指令............................ 503
22.3.2 RET 指令............................... 504
22.3.3 观察函数调用和返回过程... 504
22.3.4 跨特权级调用....................... 506
22.4 局部变量和栈帧.......................... 507
22.4.1 局部变量的分配和释放....... 508
22.4.2 EBP 寄存器和栈帧............... 510
22.4.3 帧指针和栈帧的遍历........... 514
22.5 帧指针省略.................................. 515
22.6 栈指针检查.................................. 517
22.7 调用协定...................................... 519
22.7.1 C 调用协定........................... 520
22.7.2 标准调用协定....................... 520
22.7.3 快速调用协定....................... 521
22.7.4 This 调用协定....................... 521
22.7.5 CLR 调用协定...................... 522
22.7.6 x64 调用协定........................ 523
22.7.7 通过编译器开关改变默认调用协定............................... 523
22.7.8 函数返回值........................... 523
22.7.9 归纳和补充........................... 525
22.8 栈空间的增长和溢出.................. 526
22.8.1 栈空间的自动增长............... 526
22.8.2 栈溢出................................... 527
22.8.3 分配检查............................... 530
22.9 栈下溢.......................................... 532
22.10 缓冲区溢出................................ 533
22.10.1 感受缓冲区溢出................. 533
22.10.2 缓冲区溢出攻击................. 535
22.11 变量检查.................................... 536
22.12 基于Cookie 的安全检查........... 543
22.12.1 安全Cookie 的产生、植入和检查................................. 543
22.12.2 报告安全检查失败............. 546
22.12.3 编写安全的代码................. 547
22.13 本章总结.................................... 548
参考资料................................................. 549
第23 章 堆和堆检查.............................550
23.1 理解堆..........................................550
23.2 堆的创建和销毁..........................552
23.2.1 进程的默认堆.......................552
23.2.2 创建私有堆...........................553
23.2.3 堆列表...................................554
23.2.4 销毁堆...................................554
23.3 分配和释放堆块..........................555
23.3.1 HeapAlloc ..............................555
23.3.2 CRT 分配函数.......................556
23.3.3 释放从堆中分配的内存.......557
23.3.4 GlobalAlloc 和LocalAlloc ...558
23.3.5 解除提交...............................558
23.4 堆的内部结构..............................560
23.4.1 结构和布局...........................560
23.4.2 HEAP 结构............................561
23.4.3 HEAP_SEGMENT 结构.......562
23.4.4 HEAP_ENTRY 结构.............563
23.4.5 分析堆块的分配和释放过程.......................................564
23.4.6 使用!heap 命令观察堆块信息.......................................565
23.5 低碎片堆......................................566
23.6 堆的调试支持..............................567
23.6.1 全局标志...............................567
23.6.2 堆释放检查...........................568
23.7 栈回溯数据库..............................570
23.7.1 工作原理...............................570
23.7.2 DH 和UMDH 工具..............572
23.7.3 定位内存泄漏.......................573
23.8 堆溢出和检测..............................574
23.8.1 堆缓冲区溢出.......................574
23.8.2 调用时验证...........................577
23.8.3 堆尾检查...............................578
23.9 页堆..............................................580
23.9.1 总体结构...............................581
23.9.2 启用和观察页堆...................581
23.9.3 堆块结构...............................583
23.9.4 检测溢出............................... 585
23.10 准页堆........................................ 586
23.10.1 启用准页堆......................... 586
23.10.2 结构布局............................. 587
23.10.3 检测溢出............................. 589
23.11 CRT 堆........................................ 590
23.11.1 CRT 堆的3 种模式............. 590
23.11.2 SBH 简介............................. 591
23.11.3 创建和选择模式................. 592
23.11.4 CRT 堆的终止..................... 593
23.12 CRT 堆的调试堆块.................... 593
23.12.1 _CrtMemBlockHeader结构...................................... 594
23.12.2 块类型................................. 594
23.12.3 分配堆块............................. 595
23.13 CRT 堆的调试功能.................... 598
23.13.1 内存分配序号断点............. 598
23.13.2 分配挂钩............................. 599
23.13.3 自动和手动检查................. 599
23.14 堆块转储.................................... 600
23.14.1 内存状态和检查点............. 600
23.14.2 _CrtMemDumpAllObjectsSince............................................. 601
23.14.3 转储挂钩............................. 602
23.15 泄漏转储.................................... 604
23.15.1 _CrtDumpMemoryLeaks..... 604
23.15.2 何时调用............................. 604
23.15.3 定位导致泄漏的源代码..... 606
23.16 本章总结.................................... 608
参考资料................................................. 609
第24 章 异常处理代码的编译............610
24.1 概览.............................................. 610
24.2 FS:[0]链条.................................... 611
24.2.1 TEB 和TIB 结构.................. 611
24.2.2 ExceptionList 字段................ 613
24.2.3 登记异常处理器................... 614
24.3 遍历FS:[0]链条........................... 615
24.3.1 RtlDispatchException............ 615
24.3.2 KiUserExceptionDispatcher....618
24.4 执行异常处理函数......................619
24.4.1 SehRaw 实例.........................619
24.4.2 执行异常处理函数...............620
24.5 _ _ try{}_ _ except()结构..............621
24.5.1 与手工方法的对应关系.......622
24.5.2 _ _ try{}_ _ except()结构的编译........................................622
24.5.3 范围表...................................624
24.5.4 TryLevel.................................625
24.5.5 _ _ try{}_ _ except()结构的执行........................................627
24.5.6 _SEH_prolog 和_SEH_epilog ..........................627
24.6 安全问题......................................629
24.6.1 安全Cookie...........................629
24.6.2 SAFESEH..............................631
24.6.3 基于表的异常处理...............633
24.7 本章总结......................................633
参考资料.................................................633
第25 章 调试符号.................................634
25.1 名称修饰......................................634
25.1.1 C 和C++................................635
25.1.2 C 的名称修饰规则................635
25.1.3 C++的名称修饰规则............635
25.2 调试信息的存储格式..................636
25.2.1 COFF 格式............................637
25.2.2 CodeView 格式.....................637
25.2.3 PDB 格式...............................638
25.2.4 DWARF 格式........................639
25.3 目标文件中的调试信息..............639
25.3.1 IMAGE_FILE_HEADER结构.......................................640
25.3.2 IMAGE_SECTION_HEADER结构.......................................641
25.3.3 节的重定位信息和行号信息...............................641
25.3.4 存储调试数据的节...............642
25.3.5 调试符号表........................... 643
25.3.6 COFF 字符串表.................... 644
25.3.7 COFF 符号例析.................... 645
25.4 PE 文件中的调试信息................ 646
25.4.1 PE 文件布局......................... 646
25.4.2 IMAGE_OPTIONAL_HEADER结构........................................ 648
25.4.3 调试数据目录....................... 649
25.4.4 调试数据............................... 650
25.4.5 使用WinDBG 观察PE 文件中的调试信息............................ 652
25.4.6 调试信息的产生过程........... 652
25.5 DBG 文件..................................... 653
25.5.1 从PE 文件产生DBG 文件... 653
25.5.2 DBG 文件的布局.................. 654
25.6 PDB 文件..................................... 655
25.6.1 复合文件............................... 655
25.6.2 PDB 文件布局...................... 656
25.6.3 PDB 签名.............................. 656
25.6.4 Magic 代码............................ 657
25.6.5 PDB_HEADER .....................657
25.6.6 根数据流——流目录...........658
25.6.7 页分配表...............................659
25.6.8 访问PDB 文件的方式.........659
25.6.9 PDB 文件的产生过程...........660
25.7 有关的编译和链接选项..............661
25.7.1 控制调试信息的编译选项...661
25.7.2 控制调试信息的链接选项...661
25.7.3 不同链接和编译选项的比较...................................662
25.8 PDB 文件中的数据表..................664
25.8.1 符号表...................................665
25.8.2 源文件表...............................666
25.8.3 节贡献表...............................667
25.8.4 段信息表...............................667
25.8.5 注入源代码表.......................667
25.8.6 帧数据表...............................668
25.9 本章总结......................................669
参考资料.................................................669
    

第五篇 调 试 器

第26 章 调试器概览.............................673
26.1 TX-0 计算机和FLIT 调试器...... 673
26.2 小型机和DDT 调试器................ 674
26.2.1 PDP-1..................................... 675
26.2.2 TOPS-10 操作系统和DDT-10.................................. 676
26.3 个人计算机和它的调试器.......... 678
26.3.1 8086 Monitor ......................... 678
26.3.2 SYMDEB .............................. 679
26.3.3 CodeView 调试器................. 679
26.3.4 Turbo Debugger..................... 680
26.3.5 SoftICE .................................. 681
26.4 调试器的功能.............................. 681
26.4.1 建立和终止调试会话........... 681
26.4.2 控制被调试程序执行........... 681
26.4.3 访问内存............................... 682
26.4.4 访问寄存器...........................682
26.4.5 断点.......................................683
26.4.6 跟踪执行...............................684
26.4.7 观察栈和栈回溯...................685
26.4.8 汇编和反汇编.......................685
26.4.9 源代码级调试.......................685
26.4.10 EnC ......................................686
26.4.11 文件管理.............................686
26.4.12 接收和显示调试信息.........686
26.4.13 转储.....................................686
26.5 分类标准......................................687
26.5.1 特权级别...............................687
26.5.2 操作系统...............................687
26.5.3 执行方式...............................687
26.5.4 处理器架构...........................688
26.5.5 编程语言...............................688
26.6 实现模型......................................688
26.6.1 进程内调试模型................... 688
26.6.2 进程外调试模型................... 689
26.6.3 混合调试模型....................... 690
26.6.4 内核调试模型....................... 690
26.7 经典架构...................................... 692
26.7.1 基本单元............................... 692
26.7.2 远程调试............................... 692
26.7.3 多语言和多处理器架构调试....................................... 693
26.8 HPD 标准..................................... 694
26.8.1 HPD 标准简介...................... 694
26.8.2 动作点................................... 695
26.8.3 进程和线程的表示和命名....................................... 695
26.8.4 命令....................................... 696
26.9 本章总结...................................... 697
参考资料................................................. 697
第27 章 VsDebug.................................698
27.1 架构和调试模型.......................... 698
27.1.1 架构概览............................... 698
27.1.2 远程调试器........................... 699
27.1.3 本地调试器........................... 701
27.2 VS 调试引擎................................ 701
27.2.1 一套接口,多种实现........... 701
27.2.2 核心类................................... 702
27.3 工作过程...................................... 703
27.3.1 开始调试32 位本地程序..... 703
27.3.2 开始调试64 位本地程序..... 704
27.3.3 访问调试目标....................... 705
27.4 使用断点...................................... 706
27.4.1 根据名称设置断点............... 706
27.4.2 数据断点............................... 707
27.4.3 附加条件............................... 708
27.4.4 附加操作............................... 708
27.5 多线程调试.................................. 709
27.5.1 并行栈回溯........................... 709
27.5.2 并行监视............................... 709
27.5.3 冻结线程............................... 710
27.6 EnC ............................................... 710
27.6.1 应用过程...............................711
27.6.2 要求/ZI 编译选项.................712
27.6.3 下次调用生效.......................712
27.6.4 应用失败...............................713
27.7 设计期调试..................................713
27.8 使用符号服务器..........................714
27.9 定制调试事件..............................715
27.9.1 初始断点...............................716
27.9.2 异常设置...............................716
27.10 本章总结....................................718
参考资料.................................................718
第28 章 VS Code 的调试扩展...........719
28.1 简介..............................................719
28.2 四大技术......................................719
28.3 理解“扩展包” ..........................721
28.3.1 包类型...................................721
28.3.2 安装.......................................721
28.3.3 工作原理...............................722
28.4 扩展包API...................................723
28.4.1 贡献点...................................723
28.4.2 命令.......................................724
28.4.3 激活事件...............................725
28.5 调试模型......................................725
28.5.1 贡献调试器...........................725
28.5.2 宏观架构...............................726
28.6 调试适配器..................................727
28.6.1 DA 描述符工厂.....................727
28.6.2 进程内DA.............................728
28.6.3 vsdbg......................................728
28.6.4 OpenDebugAD7 ....................729
28.7 机器接口......................................732
28.7.1 启用用法...............................732
28.7.2 对话示例...............................732
28.7.3 MIEngine ...............................733
28.8 调试Python 程序.........................733
28.8.1 PTVSD...................................733
28.8.2 发起异常时中断...................734
28.9 本章总结......................................735
参考资料.................................................735
第29 章 WinDBG 及其实现................736
29.1 WinDBG 溯源.............................. 736
29.1.1 KD 和NTSD 诞生................ 736
29.1.2 WinDBG 诞生....................... 737
29.1.3 发行方式............................... 737
29.1.4 版本历史............................... 739
29.2 C 阶段的架构............................... 740
29.2.1 功能模块............................... 740
29.2.2 远程调试............................... 740
29.3 重构.............................................. 741
29.3.1 版本历史............................... 742
29.3.2 界面变化............................... 743
29.3.3 模块变化............................... 744
29.3.4 发布方式和NTSD 问题....... 744
29.3.5 文件....................................... 745
29.4 调试器引擎的架构...................... 747
29.4.1 概览....................................... 747
29.4.2 对外接口............................... 748
29.4.3 DebugClient 类...................... 749
29.4.4 中间层................................... 750
29.4.5 服务层................................... 751
29.4.6 传输和连接层....................... 751
29.5 调试目标...................................... 751
29.5.1 TargetInfo 类......................... 752
29.5.2 用户态目标........................... 754
29.5.3 内核态目标........................... 754
29.5.4 转储文件目标....................... 754
29.6 调试会话...................................... 755
29.6.1 建立调试会话....................... 755
29.6.2 调试循环............................... 757
29.6.3 等待和处理调试事件........... 758
29.6.4 继续调试事件....................... 759
29.6.5 结束调试会话....................... 761
29.7 接收和处理命令.......................... 762
29.7.1 调试器的两种工作状态....... 762
29.7.2 进入命令状态....................... 762
29.7.3 执行命令............................... 764
29.7.4 结束命令状态....................... 765
29.8 扩展命令的工作原理.................. 765
29.9 本章总结......................................768
参考资料.................................................768
第30 章 WinDBG 用法详解................769
30.1 工作空间......................................769
30.2 命令概览......................................771
30.2.1 标准命令...............................771
30.2.2 元命令...................................772
30.2.3 扩展命令...............................773
30.3 用户界面......................................774
30.3.1 窗口概览...............................774
30.3.2 命令窗口和命令提示符.......775
30.4 输入和执行命令..........................777
30.4.1 要点.......................................777
30.4.2 表达式...................................778
30.4.3 伪寄存器...............................780
30.4.4 别名.......................................781
30.4.5 循环和条件执行...................783
30.4.6 进程限定符和线程限定符...784
30.4.7 记录到文件...........................784
30.5 建立调试会话..............................784
30.5.1 附加到已经运行的进程.......784
30.5.2 创建并调试新的进程...........785
30.5.3 非入侵式调试.......................785
30.5.4 双机内核调试.......................786
30.5.5 本地内核调试.......................786
30.5.6 调试转储文件.......................787
30.5.7 远程调试...............................787
30.6 终止调试会话..............................788
30.6.1 停止调试...............................788
30.6.2 分离调试目标.......................788
30.6.3 抛弃被调试进程...................788
30.6.4 终止被调试进程...................789
30.6.5 调试器终止或僵死...............789
30.6.6 重新开始调试.......................789
30.7 理解上下文..................................790
30.7.1 登录会话上下文...................790
30.7.2 进程上下文...........................791
30.7.3 寄存器上下文.......................791
30.7.4 局部(变量)上下文...........792
30.8 调试符号...................................... 793
30.8.1 重要意义............................... 793
30.8.2 符号搜索路径....................... 794
30.8.3 符号服务器........................... 794
30.8.4 加载符号文件....................... 795
30.8.5 观察模块信息....................... 797
30.8.6 检查符号............................... 799
30.8.7 搜索符号............................... 801
30.8.8 设置符号选项....................... 801
30.8.9 加载不严格匹配的符号文件................................ 802
30.9 事件处理...................................... 803
30.9.1 调试事件与异常的关系....... 803
30.9.2 两轮机会............................... 804
30.9.3 定制事件处理方式............... 804
30.9.4 GH 和GN 命令..................... 806
30.9.5 实验....................................... 806
30.10 控制调试目标............................ 808
30.10.1 初始断点............................. 808
30.10.2 俘获调试目标..................... 809
30.10.3 继续运行............................. 810
30.11 单步执行.................................... 811
30.11.1 概览..................................... 811
30.11.2 单步执行到指定地址......... 813
30.11.3 单步执行到下一个函数调用..................................... 813
30.11.4 单步执行到下一分支......... 814
30.11.5 追踪并监视......................... 814
30.11.6 程序指针飞跃..................... 816
30.11.7 归纳..................................... 816
30.12 使用断点.................................... 817
30.12.1 软件断点............................. 817
30.12.2 硬件断点............................. 819
30.12.3 条件断点............................. 820
30.12.4 地址表达方法..................... 822
30.12.5 设置针对线程的断点......... 822
30.12.6 管理断点............................. 822
30.13 控制进程和线程........................ 823
30.13.1 MulThrds 程序....................823
30.13.2 控制线程执行.....................824
30.13.3 多进程调试.........................826
30.14 观察栈........................................827
30.14.1 显示栈回溯.........................827
30.14.2 观察栈变量.........................829
30.15 分析内存....................................831
30.15.1 显示内存区域.....................831
30.15.2 显示字符串.........................832
30.15.3 显示数据类型.....................832
30.15.4 搜索内存.............................833
30.15.5 修改内存.............................835
30.15.6 使用物理内存地址.............836
30.15.7 观察内存属性.....................836
30.16 遍历链表....................................839
30.16.1 结构定义.............................839
30.16.2 双向链表示例.....................839
30.16.3 单向链表示例.....................841
30.16.4 dl 命令.................................841
30.16.5 !list 命令..............................842
30.17 调用目标程序的函数................843
30.17.1 调用示例.............................843
30.17.2 工作原理.............................843
30.17.3 限制条件和常见错误.........845
30.18 命令程序....................................845
30.18.1 流程控制符号.....................845
30.18.2 变量.....................................846
30.18.3 命令程序示例.....................846
30.18.4 执行命令程序.....................847
30.19 本章总结....................................848

参考资料.................................................848
附录A 示例程序列表............................849
附录B WinDBG 标准命令列表..........852
附录C NT 内核部件缩写列表............854
持之若痴——代跋....................................857

navigation bar seprate line
Copyright (C) 2018 Raymond Zhang, All Rights Reserved