% A Dynamic Debugging System For Muddle % Joel Mayer Berez % January 1978 MIT Technical Memo 94 Laboratory for Computer Science Massachusetts Institute of Technology 545 Technology Square Cambridge, Massachusetts 02139 # Copyright This report was originally published in the United States in January 1978 without a copyright notice and without subsequent registration with the U.S. Copyright Office within 5 years. Doing at least one of those was a requirement of United States copyright law at that time [^1]. This report is therefore in the public domain in the United States for failure to comply with the required formalities. This means you're free to download, modify and redistribute this report. People outside of the United States must check the copyright laws of their country before downloading or redistributing. [^1]: # Abstract Program debugging is a time consuming process. Conventional debugging techniques and aids typically give the user a narrow view of the program's operation, making debugging difficult. A debugging system that would present a clear overall picture of a program's behavior and would be both flexible and simple to operate would be a valuable tool. Such a system was designed and implemented in for Muddle, a high-level applicative programming language. This report discusses: the design alternatives considered during the debugging system's design and implementation phases, the reasons for the resulting design choices, and the system attributes. A major attribute of the system (MEND) is that it does not simulate the program being debugged but instead monitors it from another process. This attribute results in a robust and viable debugging system, because MEND not be modified in order to handle each new extension to Muddle and/or each new user-defined primitive. This report reproduces a thesis Of the same title submitted to the Department of Electrical Engineering, Massachusetts Institute of Technology, in partial fulfillment of the requirements for the Degree of Bachelor of Science. # Acknowledgements I wish to thank Al Vezza, for supervising this work and guiding me along the road to winnage; Stu Galley, for the original idea; Bruce Daniels and Gerald Farrell, for laying some of the ground work I have built upon; Brian Berkowitz and Chris Reeve, for patiently repairing my ailing Muddles; Marc Blank and Tak To, for support work and for providing me with company during all-night console sessions; and all of the other ITS and DynaMod hackers who have built a system well worth using. This research was supported by the Advanced Research Projects Agency of the Department of Defense and was monitored by the Office of Naval Research under Contract No. N00014-75-C-0661. # Introduction ## Background A time-consuming and frustrating aspect of computer programming is the debugging of faulty programs. Current debugging techniques involve tracing through the present operation of the program and mentally comparing its action with one's concept of what should be happening. With few exceptions, an understanding of where the program fails to conform to "correct" operation must be made before the cause of the failure can be determined and corrective action taken. This is where much of the difficulty occurs. In conventional debugging, it is rare for the programmer to have available any more than the most basic aids. One usually has to extrapolate from a bare minimum of information (such as machine generated error messages) or one may be buried under a large excess of information, most irrelevant (such as a core dump). Even with the more advanced aids, the programmer typically gets but a small window in the operation of the program through which, sooner or later, she or he will locate the problem. A well-localized fault will be relatively easy to spot compared to a global problem that the programmer may only catch glimpses of through the debugging window. In a compiler language, the programmer's best hope is to insert statements to print intermediate results or to try to separate the program into easier-to-handle modules. There are a few more advanced aids available, but their use is limited. One problem is that the program is, in effect, first translated into a lower-level language (generally "machine" language) and then executed interpretively in that language. The original symbols and syntax of the source program are lost, or saved only with great difficulty, making analysis and manipulation of the executing program a very painful process. If the programmer is using an interpretive language with facilities for interaction, things are considerably easier. The common technique is to stop execution at strategic points and examine the state of the environment. Since this is done interactively, with the source program still available in more or less its original form, the cause of the problem can often be found in less time than it could otherwise. one of the best example of this approach is the use of DDT (Dynamic Debugging Tool/Technique). DDT basically works with machine-language programs. However, by freely translating between numbers and symbols through the use of a table generated by the assembler, DDT makes programs look to the programmer like symbolic assembly-language programs. The user of DDT can operate in free-run mode or in n-step (statement) mode, switching between them at will. In either case one can set a breakpoint at any statement, which will cause execution to stop just before the statement is executed. Whenever stopped in DDT, the user can examine or change the contents of any location. This can be done in several data modes (e.g., unsigned octal, full ASCII, sixbit, etc.) including the use of symbols to represent addresses. Arbitrary numeric expressions can also be evaluated without affecting the program. One main advantage of DDT is that the debugging environment is very similar to the language environment the programmer used to write the program. One has to learn only the DDT commands rather than an entirely new language. Another advantage is the user's ability for viewing the results of the changes. In addition, one can quickly see the results of the changes and act accordingly. The main deficiency of DDT is that, although is names include the word "dynamic", its operation is really static. The application program can run freely, but when the programmer wants to see what is taking place, the program must be stopped. Although the real interest may be about changes on a gross scale, perhaps thousands of program statements, if one does not know exactly where the program is misbehaving, one may be required to suspend execution of it every few instructions to examine variable in order to obtain a true picture of the program's behavior. This the programmers see *not what is taking place*, but *what has taken place*, and through small windows at that. This is inefficient, and the programmer can become bogged down in detail that hinders the discovery of the true problem. The situation can be improved with the use of breakpoints that allow the program is execute freely until a breakpoint is reached, at which point the program halts. DDT is a powerful tool but still leaves much to be desired in a debugging tool. ESP (Execution Simulator and Presenter) is one solution to the static problem. It really is dynamic is that large amounts of data are constantly being displayed for the programmer while the program is being executed (actually, simulated). The information is presented in graphic form to improve readability and reduce confusion. A user of ESP may watch areas of the display where data of particular interest are being presented. One also has many options including control over the speed of execution, the type of quantity of data displayed, and special (more flexible than just a breakpoint) conditions for halting execution. In this way one can structure and control the picture presented to more easily understand what the simulated program is doing. And that is one key step in the process of debugging. Like DDT, ESP has deficiencies also. These are mainly in the area of editing and DDT-like examination of a faulty program. DDT is a sophisticated language that ESP does not attempt to entirely replace. The flaw in ESP is that it is not compatible with DDT. Ideally both should be simultaneously available to the programmer, who can use features of each as the need dictates. DDT and ESP work with a low-level language whose operation can be shown fairly simply. For example, ESP often shows flow of control by just displaying the actual section of program being executed and pointing to the current statement. It also draws lines to show where branching has occurred and in some cases even indicates looping. The display philosophy can be readily extended to higher level languages that are line oriented, like BASIC, but it fails with applicative ones, like LISP or Muddle. The latter type does not use a linear control flow, but uses a complex depth-first tree structure. Furthermore, quite complicated data structures can be built (or themselves executed) that bear little relation to the appearance of the program. A good basic display for Muddle was used in MUMBLE (Gerald Farrell's monitor and debugging aid). The code being executed is shown in stack form. Each line shows a piece of code being evaluated. As each object in the bottom line is evaluated, it is replaced by a single downward-arrow symbol in this line and then printed on a new line. In this way the evaluation can be followed from the top level down to the current object being evaluated. Furthermore, after the bottom is reached, the value returned by each line replaces its symbol in the previous line. With this mechanism, the programmer can follow execution in a natural and reasonably clear representation. MUMBLE had some difficulties arising from the fact that it simulated execution rather than just watching it and letting it proceed naturally. This caused it to run slowly and to be complex yet fragile. At the time MUMBLE was written, the Muddle compiler was not yet perfected and the language itself lacked some of the multiprocessing features that would have made simulation unnecessary. Later Farrell replaced MUMBLE with a debugger utilizing new software related to single-stepping a process, which eliminated the simulation but also eliminated the feature reflecting results of an evaluation back into the original code. Also, a mode was added that allowed the programmer to attach conditions to parts of the program which would stop execution when and if a condition was false. This is as far as MUMBLE ever progressed, and it was not in use as of the time of the proposal for the current work.