This chapter explained several debugging types and mechanisms in Windows and how they work at the system level. After reading this chapter, the following points should be familiar to you:
Native user-mode debugging relies on a system-provided architecture that’s based on a set of debug events generated by the system on behalf of the target process. These events are sent to a shared debug port object that the OS executive associates with the target process, with a dedicated thread in the debugger process waiting for new events and processing them in that order. This generic framework provides the foundation that user-mode debuggers use to control the target’s execution, including setting code breakpoints and single-stepping the target.
Kernel-mode debugging shares many concepts with user-mode debugging. Because of its global scope, however, a few debugging actions—such as setting code breakpoints and single-stepping the target—are implemented in a slightly different way to accommodate this reality.
Both script and managed-code debugging use the in-process debugging paradigm, which has a helper thread running in the target process to assist the debugger in its operations. Visual Studio uses this architecture to support both types of debugging.
The SOS Windows debugger extension can also be used to debug managed code in a completely out-of-process way, though without the convenience of source-level debugging.
The Windows debuggers support collaborative remote user-mode and kernel-mode debugging using remote sessions. Visual Studio also supports remote debugging, but it uses a different architecture that takes advantage of a remote stub process running on the target machine. The type of remote debugging architecture also affects where symbols and debugger extensions get loaded from, so they each have their practical applications.
Now that you’ve seen how debuggers can actively debug local and remote targets in Windows, the next chapter will introduce you to another debugging approach when direct live debugging isn’t an option. This very important debugging concept is called postmortem debugging.