A debugger is a tool whose job is to take control of another running program so that a human can observe and direct its execution in detail. Where ordinary execution races ahead at machine speed and discards intermediate state, a debugger lets the developer stop the program at chosen points, inspect the values of variables, registers, and memory, modify that state, and resume, step, or restart. It turns an opaque, fast-moving process into something that can be examined one careful step at a time.
The word debugging predates electronic computers, but its most-cited origin in computing is the 1947 log-book entry from the Harvard Mark II team, who taped a moth found in a relay into their notebook and labeled it the first actual case of bug being found. The activity the word names, locating and removing the cause of incorrect behavior, is what a debugger automates and accelerates.
The mechanics of a modern debugger rest on services the operating system provides for one process to control another. The Linux ptrace system call is the canonical example: its manual page describes ptrace as a means by which one process, the tracer, may observe and control the execution of another process, the tracee, and examine and change the tracee’s memory and registers. Operations such as reading and writing the tracee’s memory, fetching and setting its CPU registers, and resuming it for a single instruction or until the next signal are the primitives out of which higher-level debugger features are built. The manual notes that ptrace is primarily used to implement breakpoint debugging and system call tracing.
On top of these primitives a source-level debugger like GDB maps raw addresses back to source files, line numbers, function names, and variables, using debugging information emitted by the compiler. This is what lets a developer think in terms of their own code, setting a breakpoint on a function or watching a named variable, rather than in terms of bare machine addresses. The GDB documentation describes the debugger’s purpose as letting a programmer see what is going on inside a program as it executes, or what it was doing at the moment it crashed.
Debuggers operate in two broad modes. Live debugging attaches to or launches a running process and drives it interactively. Post-mortem debugging instead loads a saved snapshot, a core dump, taken when a program crashed, and reconstructs its final state for analysis after the fact. Together these modes make the debugger one of the oldest and most enduring categories of developer tool, central to how software defects are diagnosed and fixed.