Thursday, May 2, 2013

Access x86 debug register DR0 to DR7

x86 debug register allow access in ring0 or SMM.

On Windows, you may want to write a device driver to run your code
On Linux, you need to write a kernel module to run your code

This sample code sets the DR0 to value 0x4013c8, which is an entry point of a program. It also sets the DR7 to value 0x401, which is to enable local breakpoint of DR0.

Tested code is following:


u32 dr0_RD=0xff;
u32 dr7_RD=0xff;



asm __volatile__ (
"mov %%dr0, %0\n"
"mov %%dr7, %1\n"
:"=r"(dr0_RD), "=r"(dr7_RD)
);
printk("\ndr0_RD is: %x\ndr7_RD is: %x\n", dr0_RD, dr7_RD);


asm __volatile__ (
"movl $0x401, %eax\n"
"movl %eax, %dr7\n"
"movl $0x4013c8, %eax\n"
"movl %eax, %dr0\n"
);

asm __volatile__ (
"mov %%dr0, %0\n"
"mov %%dr7, %1\n"
:"=r"(dr0_RD), "=r"(dr7_RD)
);


printk("\ndr0_RD is: %x\ndr7_RD is: %x\n", dr0_RD, dr7_RD);


Notes about inline gcc assembly

For the block of code in red, I cannot do movl $0x401, %dr4; Additionally, I cannot define a variable u32 dr7 =0x401, and pass it to the inline gcc assembly, "movl %0, %%dr7\n":"=r"(dr7)

Additionally, if there is a paramater passing, all of the register need to use two percent. Otherwise  compile error will generates.