调试器工作原理
《How Debuggers Work》作者: Jonathan B. Rosenberg 副标题: Algorithms, Data Structures, and Architecture ISBN: 9780471149668 页数: 272 定价: USD 49.99 出版社: Wiley 装帧: Paperback 出版年: 1996-09-27
This book is for people wha are curious about how debuggers work. it is also for those brave individuals who are embarking on the creation of a new debugger or a tool similar to a debuggers. Even for developers who are not building a debugger, this book has a lot to offer. Every developer has spent-and will spend-an enormous time in front of one debugger or another, And if you understand a complex tool--which debuggers most certainly are--you can use it and understand what it is telling you and why much better. Debuggers, very complex beasts, have direct interactions with the CPU and intimate dealings with the operating system; they must be built closely is conjunction with the complier, linker and other applicatian development tools. People interested in systems technology will find a lot to dig into in this book. Finally, anyone interested in algrithrns will find a lot of unique and interesting algorithms that debuggers use to perform their normal functions.
这本书写给对那些好奇调试器的工作原理的人们。本书也写给正着手写一个新调试器或与调试器有类似功能的工具的勇敢的程序员们。即便是不打算写个调试器的程序员,本书对他们也是有很大的裨益的,因为,程序员都得每天花很多量时间与一个或多个调试器打交道,如果程序员们能够理解这个复杂的家伙,不是会更容易驾驭它来完成工作吗?调试器--这只复杂的怪兽--与CPU直接的交互并且也与操作系统有着紧密的联系;它与编译器、链接器和其实开发工具有着不可分割的伙伴关系。对系统技术有兴趣的读者也会发现本书有这方面的很深入的内容。最后,对算法感兴趣的读者也可以找到调试器使用的独特的有趣的算法。
You will see how hardware has evolved to support debugging. This dimension is important because debugging keeps getting more and more essential and the requirements on debuggers and the functionality they offer keep rising. Similar to the hardware evolution, the operating systems and their support and understanding of debuggers have grown enormously in the past ten years. But it is clear--and I will show why-that operating systems have a long way to go to provide what debuggers really need to develop outstanding functionality for debugging the kinds of applications now in demand. I will give you a much better understanding of how these vital and very complex tools work-I will give you a detailed look "under the hood." If you should ever need to build a debugger-from a simple, specialized debugging tool to be used only, by you, all the way up to a battle-hardened, production-quality, mass marker debugger-I try to document here the collective knowledge of a broad array of debugger technology. And finally, you will learn about some very interesting and sometimes very clever algorism employed in debuggers. Wherever possible, I will call out, in a stylized fashion, the most interesting, must important debugger algorithms.
你将了解到硬件是如何演化来支持调试机制。硬件的维度很重要,因为调试的需要越来越逼切,而对调试器的功能也在不断的增加。和硬件的演化类似,操作系统及其对调试器的支持在近十年来也有了翻天覆地的变化。不过可以很清楚的就是(我们说明为什么会这样)操作系统为了提供调试器所需的功能走了一条很长的路子。我们将揭开调试器这个神秘而复杂的家伙的面纱,让你更好的理解它的工作原理。如果你要写一个调试器,无论是自用的简单特殊的还是复杂的调试器,这里提供一些写调试器的相关技术。最后,你将学习到调试器实现用到的一些有趣的,有时候是相当灵巧的算法实现。
.Chapter 1 is introductory and covers basic principals of debuggers and the environments in which they operate. .Chapter 2 gives an overview of debugger architecture-what the interface and paradigms are, how a debugger is put together, and how the various components interact. .chapters 3 and 4 cover basic underlying infrastructure: hardware and operating system support needed by debuggers to be able to provide the most basic functionality. .Chapter 5 delves into the details of how a debugger controls the execution of a child process (which we will usually call the debuggee.) .Chapter 6 then explores the algorithms and data structures behind breakpoints and single-stepping-the two most important ways in which a debugger control the execution of the debuggee. Breakpoints like probes placed into a running program to observe it during operation (and without changing the program beforehand). Single-stepping is a way to carefully "walk through" a program to watch its behavior step-by-step and observe its control flow
第一章介绍调试器的基本原理和它的操作环境;
第二章概览调试器的架构--结构与接口是什么,如何集成和组成元素是如何交互的;
第三章第四章讲述调试器的根基--硬件和操作系统为调试器完成最基本功能提供的支持;
第五章深入探讨调试如何控制被调试的子进程(通常叫debuggee)的具体细节;
第六章分析断点和单步调试这两大调试技术背后所使用的算法和数据结构。断点就像一根探针扎进正在运行的程序,不必事先对程序进行修改而观察程序的状态。而单步调试则……
.Chapters 7 and 8 focus on three aspects of observing a program's context. First, I examines stack back traces. Next I explore the why's and wherefores of disassembling hardware instructions and relating them back to the user's original source code. And finally, I explore in derail the very large topic of inspecting program variables in the debuggee. This includes symbol table lookup, scope resolution, address mappings, expression evaluation, function evaluation and more. Chapter 9 covers the complex and vitally important issues of multi-threaded debugging. The modern operating systems provide “just enough rope” to start using threads and to quickly run into serious programming-- and debugging--issues with threads. debuggers are still supposed to help you solve the resulting difficult multithreaded bugs. .Chapter 10 addresses the special circumstances of debugging GUI(graphical user interface) Applications. Because almost all applications have a major user interface component and because almost all modern GUI systems are event-based, there are a lot of important common Issues to cover. .Chapter 11 focuses on special uses of debuggers for debugger-related tools such as memory corruption debugging, reverse execution, hooking debuggers, remote debugging, debugging parallel architecture machines, and the debugging of distributed objects. ,Chapter 12 covers the very complex issues surrounding debugging optimized code. The microprocessors industry trend is toward more and mere RISC processors (even Intel is moving in this direction), and RISC demands better and better compiler optimization work to meet its performance goals. This will put more and more pressure on debuggers to handle these optimizations, without having to pull out all optimizations just to debug application.
第七章第八章集中讨论调试器检查程序上下文的三个侧面。首先是堆栈回溯(stack back traces);接着是源码的反汇编;最后是很大篇幅讲述一个大主题--检查程序的变量。以上涉及了符号查找、作用域解析、地址映射、表达式求值和函数求值等。
第九章讲述多线程调试问题;
第十章讲述对GUI应用的调试;因为大部分的应用都有用户界面,而大部分用户界面都是事件驱动的,事件驱动有很多常见的重要的问题要处理。
第十一章讲述调试器的特殊应用,像调试内存毁损、反向执行、勾子调试器、远程调试、并行体系调试和分布式对象调试。
第十二章讲述了调试优化代码所产生的各种复杂问题。
Debuggers are critical tools for the development of software. They are studied very little, as compared, for example, to compilers. But more hours are typically spent debugging programs than compiling them. Debuggers are very difficult tools to build robustly because they depend heavily on relatively weak portions of operating systems and because they tend to stress the underlying operating system's capabilities. More sophisticated operating system features and the relentless trend toward mare advanced graphical programs put increased demands an debugger capabilities. This book is an introduction to how debuggers operate, and it discusses algorithm used by production debuggers.
调试器是软件开发中很重要的工具,但是与编译器相比,它被研究得太少了。而且调试的时间比编译的时间更是多很多。调试器是很难鲁棒地编写的,因为它严重依赖操作系统,因为它……
The term debugger is something of a misnomer. Strictly speaking, a debugger is a tool to help track down, isolate, and remove bugs from software programs. Bugs are software defects that have been affectionately known as "bugs"' since the infamous math of the Harvard Mark I”. In truth, debuggers are tools to illuminate the dynamic nature of a program--they are used to understand a program as well as find and Fix defects. Debuggers are the magnifying glass, the microscope, the logic analyzer, the profiler, and the browser with which a program can be examined. In spite of the limited scope of the term debugger, l will still use this term to describe these software analyzers.
“ 调试器”这个词其实是一个误称。严格地说,调试器是用于帮助追踪、隔离和去除软件程序自身错误的一种工具。有“bug”的程序是不合格的产品。更实质的是,调试器是展示软件的动态本质的工具,调试器有助于理解软件程序,查找并去除它的错误。调试器是放大镜,是显微镜,是逻辑分析器,是剖析工具,是浏览器,用于检查软件程序。由此可见,“调试器”其实是一个软件分析工具。
Debuggers are quite complex pieces of software. Their inner workings require a suite of sophisticated algorithm and data structures to accomplish their tasks. Debuggers also require an exceptionally close cooperation with and intimate knowledge of the operating system. These algorithms and interfaces are one of the subjects of this book. To discuss debuggers adequately, I must first cover some background information and terminology Here are some basic questions about debuggers I will answer to provide the necessary background from which to start: u What are they?
u Who uses them?
u How are they used?
u Why are they used?
u When are they used?
u How do they work?
Debuggers are a necessary part of the engineering process when dealing with something as complex as software systems. All interactions cannot be predicted, specifications usually are not written to the level of programming details, and implementation is an inherently difficult and error-prone process. As software gets continuously mare complex, debuggers become more and more important in tracking down problems.
调试器随着软件系统的复杂性的不断增加变得越来越重要。因为,各种(代码)交互无法预测,而规范往往不规定编码的细节,而且代码的实现是一种本质易出错的过程。
How debuggers work and how they will change over time are the primary subjects of this book. First, to present a complete overview, the various types of debuggers, the variety of approaches used to accomplish debugging, and a brief history of debugging are covered.
There are numerous approaches to debugging-perhaps as many as there are bugs. A few of the techniques used include using print statements, printing to log files, sprinkling the code with assertions, using post-mortem dumps, having programs that provide function call stacks an termination, profiling, heap checking, automated data flow analysis, reverse execution, system call tracing tool and, of course, interactive source-level debugging.
调试器是如何工作的和它的演变过程情况如何是本书的主要内容之一。首先,我们作一个全面的概览,看看各种不同的调试器是怎么被使用的;接着讲述一下调试技术的简要历史。有多少种BUG就有多少种调试方法。这些调试方法包括打印表达式的值、输出日志文件、代码片断断言(sprinkling the code with assertions)、事后检讨之盖棺论定(post-mortem dumps)、检查函数调用堆栈的程序、堆检查、自动数据流分析、反向执行、系统调用跟踪工具,当然还有源码级交互调试。
A very important class of debugging is source-level symbolic debugging-the primary emphasis of this back. The model presented to the user is that the user's high-level language source code is executed directly by the CPU.
Source-level symbolic debugging proves to be the most effective and most frequently used technique for debugging end-user applications.
The historical progression of debugging tools has gone from static past-mortem dumps, to more interactive dump analyzers, to machine-level debuggers, to basic symbolic debuggers, to command-line symbolic debuggers, to full-screen text mode debuggers, to graphical user interface( GUI) debuggers, to the current state-of-the-arc, full-fledged programming environments that integrate editor compiler, debugger, browser, profiler; and more.
源码级调试是很重要的一种调试方法,也是本书所集中讲述的一种调试方法。用户看到的模型就像是CPU是直接执行高级语言代码而非机器码。这种源码级调试符号调试方法是目前最有效的,因为它在用户的理解度和可控性找到了平衡点。调试工具的历史发展经历了静态内存转储,到交互式内存转储分析,再到机器级调试器,到简单符号调试器,到命令行符号调试器,到全屏字符模式调试器,到GUI调试器,到现在的与IDE(编辑器、编译器、链接器、浏览器和概要器(profiler))集成的全功能的调试器。
The state-of-the-art "debugger" covers a lot more, functionality than its name implies. For example, it may log all calls to certain APIs, and it may provide sophisticated profiling capabilities as well as other capabilities that stretch the traditional view of "debugging."
Current debuggers can all control the execution of the program under scrutiny using breakpoints and instruction-level single-step. A breakpoint is a special code placed in the executing code stream that, when executed, causes a special trap to occur that the processor and the operating system report to the debugger. Most CPUs have special instructions far this purpose, provided explicitly for use by a debugger. Single-step allows the debugger to control the processor executing the subject program at such a fine-grained level that only a single machine instruction may be executed. Again, most modern processors have a special mode that can be set by a debugger that causes the processor, when told to commence execution, to execute only a single instruction before stopping and giving control hack to the debugger program.
in spite of how much can be gained by building debugging tools that model the high-level source being directly executed, it is also important that debuggers show clue underlying implementation this is why debuggers provide disassembly views and direct access to hardware registers.
The user gains a lot of confidence from these views because, when chasing a bug, the user must believe that some aspects of the program or its environment are acting as expected and can be counted on. Users typically keep trying our theories that explain a bug by checking all the things that must he true in order to support that theory.