On the x86 architecture, a debug register is a register used by a processor for program debugging. There are six debug registers, named DR0...DR7, with DR4 and DR5 as obsolete synonyms for DR6 and DR7. The debug registers allow programmers to selectively enable various debug conditions associated with a set of four debug addresses. Two of these registers are used to control debug features. These registers are accessed by variants of the MOV instruction. A debug register may be either the source operand or destination operand. The debug registers are privileged resources; the MOV instructions that access them can only be executed at privilege level zero. An attempt to read or write the debug registers when executing at any other privilege level causes a general protection fault.
Each of these registers contains the linear address associated with one of four breakpoint conditions. Each breakpoint condition is further defined by bits in DR7.
The debug address registers are effective whether or not paging is enabled. The addresses in these registers are linear addresses. If paging is enabled, the linear addresses are translated into physical addresses by the processor's paging mechanism. If paging is not enabled, these linear addresses are the same as physical addresses.
Note that when paging is enabled, different tasks may have different linear-to-physical address mappings. When this is the case, an address in a debug address register may be relevant to one task but not to another. For this reason the x86 has both global and local enable bits in DR7. These bits indicate whether a given debug address has a global (all tasks) or local (current task only) relevance.
The debug status register permits the debugger to determine which debug conditions have occurred. When the processor detects an enabled debug exception, it will set the corresponding bits of this register before entering the debug exception handler.
In some implementations, B0-B3 can be set for breakpoints that match but are not enabled[1] - therefore, the debug handler should only check bits that correspond to enabled breakpoints.
Also, it is implementation-dependent whether hardware will clear B0-B3 for non-matching breakpoint conditions - therefore, debug handlers are recommended to manually clear these bits before returning to the interrupted task.[2]
DEBUGCTL
(MSR 1D9h
), any instruction that causes a Bus Lock (mainly instructions that use the LOCK
prefix to perform memory atomics that straddle cache-line boundaries or operate on uncacheable memory) will clear bit 11 of DR6 and cause a trap-type #DB exception. This bit is not otherwise set or cleared by the processors - debug handlers are recommended to set this bit to 1 before returning to the interrupted task.In some implementations, this bit may be set even if DR7.GD is not set.[1]
XBEGIN
instruction that started the transaction, otherwise the transaction is aborted with no exceptions raised.The debug control register is used to selectively enable the four address breakpoint conditions, and to specify the type and size of each of the four breakpoints. There are two levels of enabling: the local (0,2,4,6) and global (1,3,5,7) levels. The local enable bits are automatically reset by the processor at every task switch to avoid unwanted breakpoint conditions in the new task. The global enable bits are not reset by a task switch; therefore, they can be used for conditions that are global to all tasks.
On later processors, breakpoints are always exact - bits 9:8 of DR7 are still present as writable bits and are recommended to be set, but are ignored by the CPU.
F1h
("ICEBP"
/"INT01"
) opcode to:10b
on processors where the CR4.DE bit is missing or set to zero is undefined.For instruction execution breakpoints, the breakpoint length must be set to 00b
(1 byte) or else behavior is undefined.
The behavior of using breakpoint length 10b
(8 bytes) outside 64-bit mode is undefined.
Not real registers. On processors that support the CR4.DE bit (Intel Pentium and later), their behaviour is controlled by CR4.DE:
On processors without CR4.DE, the behaviour is officially undefined - usually, DR4/5 are aliased to DR6/7, but exceptions exist and have been used for CPU detection.[10]