Подтвердить что ты не робот

Hardwarebreakpoint WINAPI

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

До сих пор я выполнял две функции для установки точки останова HW:

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). Впоследствии я использовал обратный адрес вызывающей функции (EIP) в качестве адреса для разрыва в DR0 и установки флагов принадлежности в DR7.

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

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

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

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

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

4b9b3361

Ответ 1

Я не думаю, что неплохо попытаться самостоятельно отладить программу. Почему бы не использовать API-интерфейс разработки отладчика, встроенный в окна?

Dev Center - Desktop > Learn > Reference > Diagnostics > Отладка и обработка ошибок > Основная отладкa > Справка по отладке > Функции отладки: http://msdn.microsoft.com/en-us/library/windows/desktop/ms679303%28v=vs.85%29.aspx

На оборудовании x86 одношаговое включение включено, установив флаг trap в eflags. CPU завершает исключение точки останова после завершения одной команды. Я думаю, что это значит, что отладчик визуальной студии меняет этот бит флагов, мешая тому, что вы пытаетесь сделать.

Попробуйте запустить вашу программу за пределами визуальной студии (без отладчика). Работает ли он так, как ожидалось?