Hardwarebreakpoint WINAPI

В настоящее время я реализую последнюю задачу для небольшого отладочного фреймворка, а именно HW Breakpoints. Пока что я ссылался на эту статью: http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx и книгу о написании отладчика.

На данный момент я получил следующие две функции для установки 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;
 }

Итак, сначала я создаю вспомогательный поток, поскольку я отлаживаю текущий поток. В функции обратного вызова вспомогательного потока я приостанавливаю основной поток. После этого я считываю текущие значения DR основного потока (в данный момент это не актуально, так как я всегда использую DR0, после того как это сработает, я проверю, какие регистры свободны и использую до 4 BP´s). После этого я использовал адрес возврата вызывающей функции (EIP) как адрес для прерывания в DR0 и установил флаги принадлежности в DR7.

В конце я возобновляю основной поток и закрываю хэндл вспомогательного потока, так как он завершен.

С этим кодом у меня возникла следующая проблема:

Если я выполняю программу в режиме отладки, то программа останавливается по нужному адресу, но я больше ничего не могу сделать, так как установлен флаг INT1, я полагаю, и отладчик VS не может сделать ни одного шага дальше?

Если я выполняю программу без отладки, то она просто падает. Я пытался использовать __try, __except как в упомянутом проекте (http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx), но это тоже не работает.

Буду благодарен за помощь или информацию о том, что я делаю неправильно и как решить эту проблему.

12
задан greatwolf 5 January 2012 в 13:49
поделиться