The history of debugging - part 2
In the previous article about the history of debugging, we have described the origins of the word “bug”, as well as original methods used by program engineers in finding and eliminating software errors. You could also learn how a small mistake with the program can cause a chain reaction of disasters.
One of the revolutionary points mentioned before was the development of a method, where software was allowed to debug another software. It was the creation of the first debugging program, allowing developers to focus on the part they needed to concentrate on, look directly at specific registers and memory blocks containing the address of the local program variables.
This article will carry on from that point, explaining how debugging evolved from there until now. For further reading see the 3rd part of our history of debugging.
As mentioned before, a big step for debugging was the development of debugging software. We call those times the advent of command-line debuggers. Simple programs allowing the developers to abandon the guessing game, as they got the results dumped with values given memory locations.
Software engineers could now look directly at the parts of memory blocks and registers that contained the address of the local variables of the program. It proved to be a laying foundation to the core of what debugging is today – reproducing the error. With the increasing size of the programming industry, the more prominent programs arrived. With more substantial programs, the need for more complex solutions.
C, FORTRAN, COBOL, and such are high-level languages. Parsing with them provides information that can be kept in a separate file – Symbol map, showing the variable names to the memory address, allowing it to be run whenever you want. That enabled me to research variables and dump memory by name. The above is how Symbolic debuggers worked.
Breaking the point
Soon after the era of breakpoints arrived. Debuggers now could set breakpoints; these make it possible to interrupt the execution of a program at any point and thus enable the registers and the memory to be examined.
Software breakpoints are used most frequently, which temporarily change a byte in the program to be examined. This byte is the instruction to trigger a breakpoint, to stop the program execution at the modified byte.
However, this option includes the restriction that the examined program must not check itself for integrity, for example, by checking a checksum. Malware programmers can exploit this weakness of the soft breakpoints to complicate or even prevent the analysis of a malicious program.
The hardware breakpoints are not subject to this restriction since they do not change the examined program. Hardware breakpoints are implemented directly in the processor; however, this has only limited resources, so that only a limited number of these breakpoints are available.
Many debuggers started allowing the programmer to set conditional breakpoints. Additionally, to the instruction where the program execution is stopped, the programmer specifies the command for a Boolean expression. The debugger only interrupts program execution if the specified line of code has been reached and the Boolean expression is also true. The debugger can test whether the Boolean expression is true. Still, it must temporarily interrupt the program execution and check the expression, at which point the debugger either continues the program or leaves it in the suspended state.
Thanks to these introduced systems, the programmers could check the state when they wanted it. They still, however, had to decide where to put the breakpoint, which could mean many hours of research, especially in larger projects.
The breakpoint machines, or “debugging software” as others call it evolved with an ability to display the original line of code. Eventually even received an ability to dump memory, and look at the changes and conditional breakpoints.
The times you (probably) know
Knowing how we got here, we can now move on to modern times and today’s methods of debugging (at least the most commonly spread ones).
Many call the beginning of the modern debugging era the invention of Turbo Pascal with the Integrated Development Environment (IDE) introduced by Borland. Their creation allowed you to edit, compile, link and, lastly, debug the code on the same system. Sounds standard? It wasn’t back then in 1983! A revolution of not having to run programs, and loading symbol tables, particular compilers was just that – revolutionary.
The first version of Turbo Pascal was released in November 1983 [Borland Turbo Pascal Reference Manuals (PDF), 2nd. Auflage, Borland International Inc., 1. February 1984.], at a time when the concept of integrated development environments was still entirely new. At the time, a programmer mostly had the choice between the Microsoft BASIC- interpreter supplied with DOS or a professional and expensive BASIC-, C-, Fortran – or Pascal-Compiler (UCSD Pascal) on an IBM-compatible PC. The compilers were rather cumbersome to use: due to the lack of multitasking under MS-DOS, each test run consisted of leaving, starting, and reloading the various tools (editor, compiler, linker, debugger) required for software development. Since most PCs had no hard drives at the time (back then they cost at least $2,000), the floppy disk had to be changed several times, depending on the number of floppy drives.
Turbo Pascal came into this situation with the concept of an IDE that combined the various tools in one program. It was just 60 KB in size and ran at high speed on every PC at that time. Even on a PC with only one floppy disk drive, there was no need to change floppy disks, because there was still enough space on the Turbo Pascal floppy disk for the program you were editing. The system was affordable even for school children – resulting in becoming a quasi-standard on the PCs in the 1980s.
After the massive success of Turbo Pascal, a real multi-threaded, multitasking UNIX system appeared on the market to help programmers. The trend has shifted from text-based to GUI based applications. The names you probably recognize here are VC++ (Visual), GDB (Command Line), DDD (Front-end), and Eclipse (Visual).
As you see, the debugging process came a long way, but there is still plenty to discover and much to improve. There are solutions right now, that innovate the entire process, making it much easier and faster. In the next article, I will present the innovative solutions and go on a journey of predicting the future of debugging with you.
Feel free to contact me with any feedback, some additional debugging stories, comments, or questions. There are plenty of developments in this field, and I am very keen to find out what I can learn from my readers!
Do you feel stuck in the past? Don’t let the old ways drag you down and try the revolutionary local and remote reverse debugging software for companies of all sizes and shapes! Release your software lightning-fast; no bug can stop you now!
RevDeBug allows you to inspect the past state and performance profile of your applications, even directly from production environments! That is achieved with exquisite features.
Part 3 of the article is coming soon. Stay in touch!