自定义处于qume中的Linux虚拟机int3中断,使得gdb可以调试Linux用户程序。
code
// 驱动程序代码
void int3_handler()
{
asm volatile ("swapgs");
printk(KERN_ALERT "int3_handler...\n");
asm volatile ("swapgs; popq %rbp");
breakpoint_ret();
}
void install_int3_handler()
{
unsigned long int3_handler_addr = (unsigned long)int3_handler;
unsigned long* int3_desc = (unsigned long*)((unsigned long)idt_table + 0x30);
*int3_desc = (unsigned long)(((int3_handler_addr & 0xffff0000) << 32) | (int3_handler_addr & 0xffff) | (*int3_desc & 0xffffffff0000));
int3_desc++;
*int3_desc = (unsigned long)((*int3_desc & 0x00000000) | (int3_handler_addr >> 32));
printk(KERN_ALERT "install int3_handler done!\n");
}
.section .text
.global breakpoint_ret
/* .type @function */
breakpoint_ret:
addq $8, %rsp # 平衡call breakpoint_ret()
iretq # 返回至用户态
int3中断至内核
在breakpoint_ret
函数处下断点,每次用户程序执行 int3
时总是可以中断至gdb调试器,然后执行ni/si
指令返回用户态。
当然,在内核中由于调用了printk
函数输出信息,为防止用户态regs被改写,可以将printk函数注释掉,或者每次进入内核和退出内核前实现pt_regs的保存与恢复。