1 /* 2 * Test for x86 debugging facilities 3 * 4 * Copyright (c) Siemens AG, 2014 5 * 6 * Authors: 7 * Jan Kiszka <jan.kiszka@siemens.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. 10 */ 11 12 #include "libcflat.h" 13 #include "desc.h" 14 15 static volatile unsigned long bp_addr[10], dr6[10]; 16 static volatile unsigned int n; 17 static volatile unsigned long value; 18 19 static unsigned long get_dr6(void) 20 { 21 unsigned long value; 22 23 asm volatile("mov %%dr6,%0" : "=r" (value)); 24 return value; 25 } 26 27 static void set_dr0(void *value) 28 { 29 asm volatile("mov %0,%%dr0" : : "r" (value)); 30 } 31 32 static void set_dr1(void *value) 33 { 34 asm volatile("mov %0,%%dr1" : : "r" (value)); 35 } 36 37 static void set_dr7(unsigned long value) 38 { 39 asm volatile("mov %0,%%dr7" : : "r" (value)); 40 } 41 42 static void handle_db(struct ex_regs *regs) 43 { 44 bp_addr[n] = regs->rip; 45 dr6[n] = get_dr6(); 46 47 if (dr6[n] & 0x1) 48 regs->rflags |= (1 << 16); 49 50 if (++n >= 10) { 51 regs->rflags &= ~(1 << 8); 52 set_dr7(0x00000400); 53 } 54 } 55 56 static void handle_bp(struct ex_regs *regs) 57 { 58 bp_addr[0] = regs->rip; 59 } 60 61 int main(int ac, char **av) 62 { 63 unsigned long start; 64 65 setup_idt(); 66 handle_exception(DB_VECTOR, handle_db); 67 handle_exception(BP_VECTOR, handle_bp); 68 69 sw_bp: 70 asm volatile("int3"); 71 report("#BP", bp_addr[0] == (unsigned long)&&sw_bp + 1); 72 73 set_dr0(&&hw_bp); 74 set_dr7(0x00000402); 75 hw_bp: 76 asm volatile("nop"); 77 report("hw breakpoint", 78 n == 1 && 79 bp_addr[0] == ((unsigned long)&&hw_bp) && dr6[0] == 0xffff0ff1); 80 81 n = 0; 82 asm volatile( 83 "pushf\n\t" 84 "pop %%rax\n\t" 85 "or $(1<<8),%%rax\n\t" 86 "push %%rax\n\t" 87 "lea (%%rip),%0\n\t" 88 "popf\n\t" 89 "and $~(1<<8),%%rax\n\t" 90 "push %%rax\n\t" 91 "popf\n\t" 92 : "=g" (start) : : "rax"); 93 report("single step", 94 n == 3 && 95 bp_addr[0] == start+1+6 && dr6[0] == 0xffff4ff0 && 96 bp_addr[1] == start+1+6+1 && dr6[1] == 0xffff4ff0 && 97 bp_addr[2] == start+1+6+1+1 && dr6[2] == 0xffff4ff0); 98 99 n = 0; 100 set_dr1((void *)&value); 101 set_dr7(0x00d0040a); 102 103 asm volatile( 104 "mov $42,%%rax\n\t" 105 "mov %%rax,%0\n\t" 106 : "=m" (value) : : "rax"); 107 hw_wp: 108 report("hw watchpoint", 109 n == 1 && 110 bp_addr[0] == ((unsigned long)&&hw_wp) && dr6[0] == 0xffff4ff2); 111 112 return 0; 113 } 114