发表于2008/9/28 0:25:00 2745人阅读
调试器工作原理《How Debuggers Work》
作者: Jonathan B. Rosenberg 副标题: Algorithms, Data Structures, and Architecture ISBN: 9780471149668 页数: 272 定价: USD 49.99 出版社: Wiley 装帧: Paperback 出版年: 1996-09-27
who Should Read this Book
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.
What will You Get out of This Book?
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.
Layout of this Book
.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
.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)；接着是源码的反汇编；最后是很大篇幅讲述一个大主题--检查程序的变量。以上涉及了符号查找、作用域解析、地址映射、表达式求值和函数求值等。
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.
Basic concepts of 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.
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?
Why Are They used?为什么使用？
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 do they work?如何工作的？
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.
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.