现代计算机系统的一个重要设计原则是让硬件在软件的指挥下工作,把灵活性和智能留在软件中实现,这同时也把计算机系统的控制权交给了软件。让软件控制强大的计算机硬件是聪明的,运行不同的软件就可以让同一台机器做完全不同的事情;也是冒险的,一条错误的指令就可能让系统崩溃甚至导致灾难。
降低风险的方法是提高软件的质量和我们对软件的控制力。但对人类而言,无形的软件比有形的硬件更加难以驾驭!软件瑕疵总是存在但却难以寻找;病毒和恶意软件不请自来,而且挥之不去;CPU不堪重负,用户下达的命令却还得不到执行。相对于淳朴的硬件,软件更加复杂、多变、桀骜、事故和狡黠!何以应对?
征服软件的最强大工具是调试器。一旦进了调试器,再狂野的软件都会变得服服帖帖,所有的宏观结构和微观细节任由我们审阅,大到整个地址空间和每个文件,小到每一个内存单元和每一条指令。如果静态的分析还不够,那么我们可以让它根据我们的要求来执行,执行一条指令,执行到下一个分支,执行到上一级函数,等等。总之,利用调试器可以自由的控制软件,高效的认识软件。
本书第一次全方位的展示了以调试器为核心的软件调试技术,并探讨了具有普遍意义的复杂软件问题。围绕如何实现高效调试这一主题,本书深入的讨论了如下内容。
- CPU的调试支持,包括异常、断点、单步执行、分支监视、JTAG、MCE等。
- Windows操作系统中的调试设施,包括内核调试引擎、用户态调试子系统、验证器、Dr. Watson、WER、ETW、故障转储、WHEA等。
- Visual C/C++编译器的调试支持,重点讨论了编译期检查、运行期检查、以及调试符号。
- WinDBG调试器的发展历史、模块结构、工作模型、使用方法、主要调试功能的实现细节,和遍布全书应用的实例。
- 内核调试、用户态调试、JIT调试、远程调试的原理、实现和用法。
- 分别从CPU、操作系统、编译器和调试器多个角度全面探讨了异常的概念、渊源、分发方法、处理方法、编译方法和与调试相关的若干问题。
- 栈和堆的结构布局、工作原理和有关的软件问题,包括Win32堆、页堆、CRT堆、栈的自动增长和溢出,缓冲区溢出,溢出攻击,安全Cookie,内存泄漏,堆崩溃等。
- 调试符号的作用、分类、产生过程、使用方法和对常用类型调试符号的详细介绍。
- 错误提示、错误记录、自动错误报告、硬件错误处理、自动验证、事件追踪、故障转储等辅助调试措施。
- 软件的可调试性和实现建议。
此外,书中还诠释了很多较难理解的概念(保护模式、虚拟内存、IDT、GDT、任务状态段、系统调用、函数调用协议、栈帧等),思考了一系列耐人深思和具有普遍意义的问题。本书是对软件调试技术在过去50年中所取得成就的全面展示,也是对作者本人在软件设计和系统开发第一线奋战十多年的经验总结。本书适合每一位希望深刻理解软件和自由驾驭软件的人阅读,不论您是憎恨软件,还是热爱软件,不论您是想发现软件中的瑕疵,还是想领略其中蕴含的智慧!
|