Search code examples
debuggingassemblyx86virtual-memoryvirtual-address-space

Can virtual memory be used to support Data Breakpoint feature in i386?


I was lurking around my OS textbook and it mentioned that virtual address translation can be implemented on data breakpoint (for program debugging). I only know that the debugger uses INT 3 to pause the program, local and global variables being processed in someway in the debug control & address registers. But after some digging I only found information regarding linear address in the use of debug register. No articles or discussions about the mechanism behind virtual address related data breakpoint at all. So how exactly this work?


Solution

  • Linear addresses are virtual, in x86 terminology. x86 memory addressing goes:

    • addressing mode like [ebp + eax*4] to "effective address" (the offset part of a seg:off). (And every addressing mode implies a segment, if you don't manually override with [fs: rdi] for example. Normally DS, unless the base register is R/E/BP or R/ESP in which case SS. Or for implicit addressing modes as part of e.g. push rax or stosb, it depends on the instruction.)
    • seg:off -> linear by adding the segment base to the offset.
    • translation of that linear address to physical. (And if virtualizing, from guest-physical to true physical.)

    All steps are done by the CPU hardware, first using the segment base, then using the page-table pointed to by CR3. Or the TLB which caches the translations from that page table.

    The hardware debug registers for hardware breakpoints / watchpoints use virtual addresses. https://en.wikipedia.org/wiki/X86_debug_register explains it as follows:

    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.

    That implies that a watchpoint can trigger when you access the same physical address from a different virtual address than the one you put in the debug register. (If that description on Wikipedia is accurate; I'd test it and/or check Intel or AMD's manuals if that matters.)

    I don't actually know the details; know x86 has a TF flag and debug registers, and a general idea of things they can do, but I've never written code to use them.


    I only know that the debugger uses INT 3 to pause the program

    "hardware breakpoint" means the CPU will stop without software having to rewrite the executing code to 0xCC int3. The debug registers can do this, and also detect access to certain memory locations by any instruction.

    So you can set a watchpoint to break when anything your program reads or writes a certain global variable in memory, letting you find code that modifies it through a pointer or something. And since it's HW supported, you can run at full speed instead of having to single-step and have software check every access.

    See also