Part II - Debugger overview
Debugging is mostly divided into two parts, low level debugging and high level debugging.
Low level debugging
Low level debugging involves debugging the program at the instruction level. One can read write instruction memory, read write registers, and read write data memory. Set a breakpoint at a certain address, and step a single instruction. All these has nothing to do with the programming language itself.
Building the low level debugging components requires hacking the virtual machine we just built. We will add the break instruction to allow the virtual machine to notify us when a breakpoint is hit. We will also add a single stepping flag to the virtual machine to ask it to run just one instruction. Last but not least, we will also build the private interface between the debugger and the virtual machine to allow data access.
These interfaces are closely modeled after real processor and operating system support, so you can use this knowledge when you need to build a debugger for real systems.
High level debugging
High level debugging involves something like showing the current line number, function name, variable name and values, tasks that involve the programming language itself. This time we will refrain from hacking the virtual machine and build this on top of the low level primitives, but we will need to hack the compiler to build us this symbolic information.