Hardwarebreakpoint WINAPI

12

I'm currently implementing the last task for a little debug framework, namely HW Breakpoints. I referred to this article so far: http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx and a Book about writing a Debugger.

I got following two functions so far for setting a HW breakpoint:

void debuglib::breakpoints::hw_bp() {
    HANDLE helper = 0;

    CONTEXT co;
    CURRENTCONTEXT(co);

    helper = ::CreateThread(0,0,threadfunc,reinterpret_cast<void*>(co.Eip),0,0);

    DWORD status = ::WaitForSingleObject(helper,INFINITE);


    if (status != WAIT_OBJECT_0) { 
            ::MessageBoxA(0, "Helper thread didn't exit cleanly", "HWBreakpoint", MB_OK);
    }

    ::CloseHandle(helper);
}

static DWORD WINAPI debuglib::breakpoints::threadfunc(void* param) {

    DWORD suspendcnt = ::SuspendThread(debuglib::process::thread());
    if(suspendcnt) {
        return 0;
    }

    CONTEXT co;
    ::ZeroMemory(&co,sizeof(co));
    co.ContextFlags = CONTEXT_DEBUG_REGISTERS;

    BOOL ok = ::GetThreadContext(debuglib::process::thread(),&co);

    if(!ok) {
        return 0;
    }

    DWORD freeDr = 0;
    DWORD condition = debuglib::breakpoints::TRIGGER::CODE;
    DWORD length = debuglib::breakpoints::SIZE::SIZE_1;

    co.Dr0 = reinterpret_cast<DWORD>(param);

    co.Dr7 = co.Dr7 | 1 << (freeDr*2);
    co.Dr7 = co.Dr7 | condition << ((freeDr*4)+16);
    co.Dr7 = co.Dr7 | length << ((freeDr*4)+18);

    co.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    ok = ::SetThreadContext(debuglib::process::thread(), &co);

    co.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    ::GetThreadContext(debuglib::process::thread(),&co);

    suspendcnt = ::ResumeThread(debuglib::process::thread());
    if(suspendcnt == 0xFFFFFFFF) {
        return 0;
    }

    return 1;
 }

So first I'm creating a helper thread since I´m debugging the current thread. Within the callback function of the helper thread, I´m suspending the main thread. Afterwards I read the current DR values of the main thread (at the moment this is not relevant, since I always use DR0, after this works, I will check which registers are free and use up to 4 BP´s). Afterwards I used the return address of the calling function (EIP) as address to break in DR0 and set the belonging flags in DR7.

At the end I'm resuming the main thread and closing the handle of the helper thread, as it is finished.

With this code I got following problem:

If I execute the program in debug mode the programs halts at the right address, but I cannot do anything anymore, since the INT1 flag is set I guess and the VS debugger cannot single-step further?

If I execute the program without debugging it simple crashes. I tried to use __try, __except like in the mentioned project (http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx) but this does not work either.

I appreciate and help or information what I´m doing wrong and how to solve this problem.

c++
winapi
breakpoints
asked on Stack Overflow Jan 5, 2012 by Chris • edited Jan 5, 2012 by greatwolf

1 Answer

2

I don't think it's a good idea to try to make a program debug itself. Why not use the debugger development API built into windows?

Dev Center - Desktop > Learn > Reference > Diagnostics > Debugging and Error Handling > Basic Debugging > Debugging Reference > Debugging Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/ms679303%28v=vs.85%29.aspx

On x86 hardware, single-stepping is enabled by setting the trap flag in eflags. The CPU will raise a debug exception (interrupt 1) after it completes one instruction. What I think is happening is the visual studio debugger is changing that bit of the flags, interfering with what you're trying to do.

Try running your program outside visual studio (no debugger). Does it work as expected then?

answered on Stack Overflow Mar 16, 2012 by doug65536 • edited Nov 2, 2020 by doug65536

User contributions licensed under CC BY-SA 3.0