package proctl /* #include #include #include #include // Exposes C macro `offsetof` which is needed for getting // the offset of the debug register we want, and passing // that offset to PTRACE_POKE_USER. int offset(int reg) { return offsetof(struct user, u_debugreg[reg]); } */ import "C" import "fmt" // Sets a hardware breakpoint by setting the contents of the // debug register `reg` with the address of the instruction // that we want to break at. There are only 4 debug registers // DR0-DR3. Debug register 7 is the control register. func setHardwareBreakpoint(reg, tid int, addr uint64) error { if reg < 0 || reg > 3 { return fmt.Errorf("invalid debug register value") } var ( dr7off = uintptr(C.offset(C.DR_CONTROL)) drxoff = uintptr(C.offset(C.int(reg))) drxmask = uintptr((((1 << C.DR_CONTROL_SIZE) - 1) << uintptr(reg*C.DR_CONTROL_SIZE)) | (((1 << C.DR_ENABLE_SIZE) - 1) << uintptr(reg*C.DR_ENABLE_SIZE))) drxenable = uintptr(0x1) << uintptr(reg*C.DR_ENABLE_SIZE) drxctl = uintptr(C.DR_RW_EXECUTE|C.DR_LEN_1) << uintptr(reg*C.DR_CONTROL_SIZE) ) // Get current state dr7, err := PtracePeekUser(tid, dr7off) if err != nil { return err } // If addr == 0 we are expected to disable the breakpoint if addr == 0 { dr7 &= ^drxmask return PtracePokeUser(tid, dr7off, dr7) } // Error out if dr`reg` is already used if dr7&(0x3<