为了使层次明确,结构清晰和便于索引,《软件调试》一书中使用了三级结构来组织章节正文,章是一级,节是二级,节之下再根据需要分为小节。
例如在第1章绪论中,1.3节的标题是简要历史,下面又分3个小节,分别讲单步执行(1.3.1)、断点(1.3.2)和分支监视(1.3.3)功能的历史。
因为三级目录的总页数有31页,为了控制总页数,在《软件调试》的印刷版本中,使用的是二级目录,即本页下方所显示的内容。
如果你想查看更详细的三级目录,那么请点击这里。
第1篇 | 绪论 | ... 1 |
第1章 | 软件调试基础 | .. 3 |
1.1 | 简介 | ... 3 |
1.2 | 基本特征 | ... 6 |
1.3 | 简要历史 | ... 8 |
1.4 | 分类 | ... 12 |
1.5 | 调试技术概览 | ... 15 |
1.6 | 错误与缺欠 | ... 20 |
1.7 | 与软件工程的关系 | ... 24 |
1.8 | 本章总结 | ... 26 |
第2篇 | CPU的调试支持 | ... 27 | 第2章 | CPU基础 | .. 29 | 2.1 | 指令和指令集 | ... 29 | 2.2 | IA-32处理器 | ... 32 | 2.3 | CPU的操作模式 | ... 38 | 2.4 | 寄存器 | ... 40 | 2.5 | 理解保护模式 | ... 46 | 2.6 | 段机制 | ... 50 | 2.7 | 分页机制(Paging) | ... 55 | 2.8 | 系统概貌 | ... 62 | 2.9 | 本章总结 | ... 64 | 第3章 | 中断和异常 | .. 65 | 3.1 | 概念和差异 | ... 65 | 3.2 | 异常的分类 | ... 67 | 3.3 | 异常例析 | ... 69 | 3.4 | 中断/异常优先级 | ... 72 | 3.5 | 中断/异常处理 | ... 73 | 3.6 | 本章总结 | ... 74 | 第4章 | 断点和单步执行 | .. 75 | 4.1 | 软件断点 | ... 75 | 4.2 | 硬件断点 | ... 83 | 4.3 | 陷阱标志 | ... 95 | 4.4 | 实模式调试器例析 | ... 100 | 4.5 | 本章总结 | ... 105 | 第5章 | 分支记录和性能监视 | .. 107 | 5.1 | 分支监视概览 | ... 107 | 5.2 | 使用寄存器的分支记录 | ... 108 | 5.3 | 使用内存的分支记录 | ... 113 | 5.4 | DS示例:CpuWhere | ... 117 | 5.5 | 性能监视 | ... 123 | 5.6 | 本章总结 | ... 132 | 第6章 | 机器检查架构(MCA) | .. 133 | 6.1 | 奔腾处理器的机器检查机制 | ... 134 | 6.2 | MCA | .. 135 | 6.3 | 编写MCA软件 | ... 141 | 6.4 | 本章总结 | ... 145 | 第7章 | JTAG调试 | .. 147 | 7.1 | 简介 | ... 147 | 7.2 | JTAG原理 | ... 149 | 7.3 | JTAG应用 | ... 154 | 7.4 | IA-32处理器的JTAG支持 | ... 156 | 7.5 | 本章总结 | ... 161 |
第3篇 | 操作系统的调试支持 | ... 163 | 第8章 | Windows概要 | .. 165 | 8.1 | 简介 | ... 165 | 8.2 | 进程和进程空间 | ... 167 | 8.3 | 内核模式和用户模式 | ... 176 | 8.4 | 架构和系统部件 | ... 184 | 8.5 | 本章总结 | ... 192 | 第9章 | 用户态调试模型 | .. 193 | 9.1 | 概览 | ... 193 | 9.2 | 采集调试消息 | ... 196 | 9.3 | 发送调试消息 | ... 200 | 9.4 | 调试子系统服务器(XP之后) | ... 203 | 9.5 | 调试子系统服务器(XP之前) | ... 210 | 9.6 | 比较两种模型 | ... 219 | 9.7 | NTDLL中的调试支持例程 | ... 221 | 9.8 | 调试API | ... 224 | 9.9 | 本章总结 | ... 226 | 第10章 | 用户态调试过程 | .. 227 | 10.1 | 调试器进程 | ... 227 | 10.2 | 被调试进程 | ... 231 | 10.3 | 从调试器中启动被调试程序 | ... 234 | 10.4 | 附加到已经启动的进程 | ... 240 | 10.5 | 处理调试事件 | ... 243 | 10.6 | 中断到调试器 | ... 251 | 10.7 | 输出调试字符串 | ... 259 | 10.8 | 终止调试会话 | ... 266 | 10.9 | 本章总结 | ... 271 | 第11章 | 中断和异常管理 | .. 273 | 11.1 | 中断描述符表 | ... 273 | 11.2 | 异常的描述和登记 | ... 280 | 11.3 | 异常分发过程 | ... 284 | 11.4 | 结构化异常处理(SEH) | ... 290 | 11.5 | 向量化异常处理(VEH) | ... 302 | 11.6 | 本章总结 | ... 308 | 第12章 | 未处理异常和JIT调试 | .. 309 | 12.1 | 简介 | ... 309 | 12.2 | 默认的异常处理器 | ... 311 | 12.3 | 未处理异常过滤函数 | ... 318 | 12.4 | 应用程序错误对话框 | ... 328 | 12.5 | JIT调试和Dr. Watson | ... 334 | 12.6 | 顶层异常过滤函数 | ... 340 | 12.7 | Dr. Watson | ... 343 | 12.8 | DRWTSN32的日志文件 | ... 347 | 12.9 | 用户态转储文件 | ... 351 | 12.10 | 本章总结 | ... 357 | 第13章 | 硬错误和蓝屏 | .. 359 | 13.1 | 硬错误提示 | ... 359 | 13.2 | 蓝屏终止(BSOD) | ... 366 | 13.3 | 系统转储文件 | ... 371 | 13.4 | 分析系统转储文件 | ... 374 | 13.5 | 辅助的错误提示方法 | ... 380 | 13.6 | 配置错误提示机制 | ... 384 | 13.7 | 防止滥用错误提示机制 | ... 389 | 13.8 | 本章总结 | ... 390 | 第14章 | 错误报告 | .. 391 | 14.1 | WER 1.0 | ... 392 | 14.2 | 系统错误报告 | ... 395 | 14.3 | WER服务器端 | ... 397 | 14.4 | WER 2.0 | ... 399 |
14.5 | CER | ... 403 |
14.6 | 本章总结 | ... 404 | 第15章 | 日志 | .. 405 | 15.1 | 日志简介 | ... 405 | 15.2 | ELF的架构 | ... 406 | 15.3 | ELF的数据组织 | ... 409 | 15.4 | 察看和使用ELF日志 | ... 413 | 15.5 | CLFS的组成和原理 | ... 414 | 15.6 | CLFS的使用方法 | ... 416 | 15.7 | 本章总结 | ... 420 | 第16章 | 事件追踪 | ... 421 | 16.1 | 简介 | ... 421 | 16.2 | ETW的架构 | ... 422 | 16.3 | 提供ETW消息 | ... 424 | 16.4 | 控制ETW会话 | ... 425 | 16.5 | 消耗ETW消息 | ... 427 | 16.6 | 格式描述 | ... 428 | 16.7 | NT Kernel Logger | ... 432 | 16.8 | Global Logger Session | ... 436 | 16.9 | Crimson API | ... 440 | 16.10 | 本章总结 | ... 443 | 第17章 | WHEA | ... 445 | 17.1 | 目标和架构 | ... 445 | 17.2 | 错误源 | ... 450 | 17.3 | 错误处理过程 | ... 452 | 17.4 | 错误持久化 | ... 457 | 17.5 | 注入错误 | ... 459 | 17.6 | 本章总结 | ... 459 | 第18章 | 内核调试引擎 | .. 461 | 18.1 | 概览 | ... 462 | 18.2 | 连接 | ... 465 | 18.3 | 启用 | ... 475 | 18.4 | 初始化 | ... 478 | 18.5 | 内核调试协议 | ... 483 | 18.6 | 与内核交互 | ... 492 | 18.7 | 建立和维持连接 | ... 502 | 18.8 | 本地内核调试 | ... 509 | 18.9 | 本章总结 | ... 511 | 第19章 | Windows的验证机制 | .. 513 | 19.1 | 简介 | ... 514 | 19.2 | 驱动验证器的工作原理 | ... 515 | 19.3 | 使用驱动验证器 | ... 521 | 19.4 | 应用程序验证器的工作原理 | ... 526 | 19.5 | 使用应用程序验证器 | ... 533 | 19.6 | 本章总结 | ... 537 |
第4篇 | 编译器的调试支持 | ... 539 | 第20章 | 编译和编译期检查 | .. 541 | 20.1 | 程序的构建过程 | ... 541 | 20.2 | 编译 | ... 543 | 20.3 | Visual C++编译器 | ... 544 | 20.4 | 编译错误和警告 | ... 549 | 20.5 | 编译期检查 | ... 551 | 20.6 | 标准标注语言 | ... 555 | 20.7 | 本章总结 | ... 558 | 第21章 | 运行库和运行期检查 | .. 559 | 21.1 | C/C++运行库 | ... 559 | 21.2 | 链接运行库 | ... 562 | 21.3 | 运行库的初始化和清理 | ... 565 | 21.4 | 运行期检查 | ... 569 | 21.5 | 报告运行期检查错误 | ... 574 | 21.6 | 本章总结 | ... 580 | 第22章 | 栈和函数调用 | .. 581 | 22.1 | 简介 | ... 581 | 22.2 | 栈的创建过程 | ... 585 | 22.3 | CALL和RET指令 | ... 590 | 22.4 | 局部变量和栈帧 | ... 595 | 22.5 | 帧指针省略(FPO) | ... 604 | 22.6 | 栈指针检查 | ... 606 | 22.7 | 调用协定 | ... 609 | 22.8 | 栈空间的增长和溢出 | ... 616 | 22.9 | 栈下溢 | ... 623 | 22.10 | 缓冲区溢出 | ... 624 | 22.11 | 变量检查 | ... 628 | 22.12 | 基于Cookie的安全检查 | ... 636 | 22.13 | 本章总结 | ... 642 | 第23章 | 堆和堆检查 | .. 643 | 23.1 | 理解堆 | ... 644 | 23.2 | 堆的创建和销毁 | ... 646 | 23.3 | 分配和释放堆块 | ... 649 | 23.4 | 堆的内部结构 | ... 654 | 23.5 | 低碎片堆(LFH) | ... 661 | 23.6 | 堆的调试支持 | ... 662 | 23.7 | 栈回溯数据库 | ... 666 | 23.8 | 堆溢出和检测 | ... 670 | 23.9 | 页堆 | ... 677 | 23.10 | 准页堆 | ... 683 | 23.11 | CRT堆 | ... 688 | 23.12 | CRT堆的调试堆块 | ... 692 | 23.13 | CRT堆的调试功能 | ... 698 | 23.14 | 堆块转储 | ... 700 | 23.15 | 泄漏转储 | ... 704 | 23.16 | 本章总结 | ... 709 | 第24章 | 异常处理代码的编译 | .. 711 | 24.1 | 概览 | ... 711 | 24.2 | FS:[0]链条 | ... 713 | 24.3 | 遍历FS:[0]链条 | ... 716 | 24.4 | 执行异常处理函数 | ... 721 | 24.5 | __try{}__except()结构 | ... 724 | 24.6 | 安全问题 | ... 732 | 24.7 | 本章总结 | ... 737 | 第25章 | 调试符号 | .. 739 | 25.1 | 名称修饰 | ... 739 | 25.2 | 调试信息的存储格式 | ... 742 | 25.3 | 目标文件中的调试信息 | ... 745 | 25.4 | PE文件中的调试信息 | ... 753 | 25.5 | DBG文件 | ... 762 | 25.6 | PDB文件 | ... 764 | 25.7 | 有关的编译和链接选项 | ... 771 | 25.8 | PDB文件中的数据表 | ... 775 | 25.9 | 本章总结 | ... 780 |
第5篇 | 可调试性 | ... 781 | 第26章 | 可调试性概览 | .. 783 | 26.1 | 简介 | ... 783 | 26.2 | Showstopper和未雨绸缪 | ... 784 | 26.3 | 基本原则 | ... 787 | 26.4 | 不可调试代码 | ... 792 | 26.5 | 可调试性例析 | ... 794 | 26.6 | 与安全、性能和商业秘密的关系 | ... 798 | 26.7 | 本章总结 | ... 799 | 第27章 | 可调试性的实现 | .. 801 | 27.1 | 角色和职责 | ... 801 | 27.2 | 可调试架构 | ... 804 | 27.3 | 通过栈回溯实现可追溯性 | ... 808 | 27.4 | 数据的可追溯性 | ... 815 | 27.5 | 可观察性的实现 | ... 821 | 27.6 | 自检和自动报告 | ... 830 | 27.7 | 本章总结 | ... 832 |
第6篇 | 调试器 |
... 833 |
第28章 | 调试器概览 | .. 835 |
28.1 | TX-0计算机和FLIT调试器 | ... 835 | 28.2 | 小型机和DDT调试器 | ... 837 | 28.3 | 个人计算机和它的调试器 | ... 841 | 28.4 | 调试器的功能 | ... 845 | 28.5 | 分类标准 | ... 852 | 28.6 | 实现模型 | ... 853 | 28.7 | 经典架构 | ... 859 | 28.8 | HPD标准 | ... 862 | 28.9 | 本章总结 | ... 866 | 第29章 | WinDBG及其实现 | .. 867 | 29.1 | WinDBG溯源 | ... 867 | 29.2 | C阶段的架构 | ... 872 | 29.3 | 重构 | ... 875 |
29.4 |
调试器引擎的架构 |
... 881 |
29.5 |
调试目标 |
... 887 |
29.6 | 调试会话 | ... 892 | 29.7 | 接收和处理命令 | ... 899 | 29.8 | 本章总结 | ... 904 | 第30章 | WinDBG用法详解 | .. 905 | 30.1 | 工作空间 | ... 905 | 30.2 | 命令概览 | ... 908 | 30.3 | 用户界面 | ... 911 | 30.4 | 输入和执行命令 | ... 916 | 30.5 | 建立调试会话 | ... 923 | 30.6 | 终止调试会话 | ... 927 | 30.7 | 理解上下文 | ... 930 | 30.8 | 调试符号 | ... 933 | 30.9 | 事件处理 | ... 944 | 30.10 | 控制调试目标 | ... 951 | 30.11 | 单步执行 | ... 955 | 30.12 | 使用断点 | ... 962 | 30.13 | 控制进程和线程 | ... 969 | 30.14 | 观察栈 | ... 973 | 30.15 | 分析内存 | ... 978 | 30.16 | 遍历链表 | ... 987 | 30.17 | 调用目标程序的函数 | ... 992 | 30.18 | 命令程序 | ... 994 | 30.19 | 本章总结 | ... 997 |
附录A | 示例程序列表 | ... 999 |
附录B | WinDBG标准命令列表 | ... 1003 |
索引 | ... 1005 |
|