macosdebuggingkernelsystem-callsmsr

How do I write x86 Debug registers from user space on OSX?


I'd like to play around with the debug MSRs defined in the x86 spec (DR0-7) from my OSX user-space program. Unfortunately, these require CPL == 0 (aka ring 0). I've thumbed through the OSX syscalls and with the exception of kernel_debug nothing really jumps out as a way to access these.

It may be the case that they are only available via some higher level interface like kernel_debug, but it's unclear to me if that's the case or if I just haven't found the magic invocation to get to them.

My end goal is accessing the functionality of these registers, not the registers themselves. Does anyone have insight on how to do things like set hardware breakpoints?


Solution

  • It turns out thread_get_state/thread_set_state is the answer.

    #include <mach/mach_types.h>
    
    thread_t target = get_target_thread();
    struct x86_debug_state dr;
    mach_msg_type_number_t dr_count = x86_DEBUG_STATE_COUNT;
    
    kern_return_t rc = thread_get_state(target, x86_DEBUG_STATE, &dr, &dr_count);    
    printf("DR0: 0x%08x\n", dr.uds.ds32.__dr0);
    printf("DR1: 0x%08x\n", dr.uds.ds32.__dr1);
    printf("DR2: 0x%08x\n", dr.uds.ds32.__dr2);
    printf("DR3: 0x%08x\n", dr.uds.ds32.__dr3);
    printf("DR4: 0x%08x\n", dr.uds.ds32.__dr4);
    printf("DR5: 0x%08x\n", dr.uds.ds32.__dr5);
    printf("DR6: 0x%08x\n", dr.uds.ds32.__dr6);
    printf("DR7: 0x%08x\n", dr.uds.ds32.__dr7);