Запись основного цикла отладчика


Отладчик использует функцию WaitForDebugEvent в начале своего основного цикла. Эта функция блокирует отладчик, до тех пор, пока не произойдет событие отладки. Когда событие отладки происходит, система приостанавливает все потоки в отлаживаемом процессе и уведомляет отладчик о событии.

Отладчик может взаимодействовать с пользователем, или обрабатывать состояние отлаживаемого процесса, используя функции GetThreadContext, GetThreadSelectorEntry, ReadProcessMemory, SetThreadContext и WriteProcessMemory. GetThreadSelectorEntry возвращает запись таблицы дескрипторов для заданного селектора и потока. Отладчики используют запись таблицы дескрипторов, чтобы преобразовать адрес относительно начала сегмента в адрес линейного виртуального адреса. Функции ReadProcessMemory и WriteProcessMemory требуют линейных виртуальных адресов.

Отладчики часто читают в памяти отлаживаемого процесса и записывают в память, которая содержит инструкции кэша команд. После того, как инструкции запишутся, отладчик вызывает функцию FlushInstructionCache, чтобы исполнить кэшируемые команды.

Отладчик  использует функцию ContinueDebugEvent в конце своего основного цикла. Эта функция позволяет отлаживаемому процессу  продолжить  исполнять код.

Пример ниже использует функции WaitForDebugEvent и ContinueDebugEvent, чтобы проиллюстрировать, как простой отладчик программы  может быть организован.

DEBUG_EVENT DebugEv;                   // информация о событиях отладки
DWORD dwContinueStatus = DBG_CONTINUE; // продолжение исключения
 
for(;;) 
{ 
 
// Ожидание произошедшего события отладки. Второй параметр 
// указывает, что функция не возвращает значение до тех пор,
// пока не произойдет событие отладки. 
 
    WaitForDebugEvent(&DebugEv, INFINITE); 
 
// Обработка кода события отладки. 
 
    switch (DebugEv.dwDebugEventCode) 
    { 
        case EXCEPTION_DEBUG_EVENT: 
        // Обработка кода исключения. При обработке 
        // исключительных ситуаций, не забудьте установить
        // параметр состояния продолжения (dwContinueStatus).
        // Это значение используется функцией ContinueDebugEvent.
 
            switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode) 
            { 
                case EXCEPTION_ACCESS_VIOLATION: 
                // Первый случай: Передать это в систему. 
                // Последний случай: Показать на экране 
                // соответствующую ошибку. 
                    break;
 
                case EXCEPTION_BREAKPOINT: 
                // Первый случай: Показать на экране  текущую 
                // команду и значения регистров. 
                    break;
 
                case EXCEPTION_DATATYPE_MISALIGNMENT: 
                // Первый случай: Передать это в систему. 
                // Последний случай: Показать на экране 
                // соответствующую ошибку. 
                    break;
 
                case EXCEPTION_SINGLE_STEP: 
                // Первый случай: Обновить показанные 
                // на экране текущие команду и значения
                // регистров. 
                    break;
 
                case DBG_CONTROL_C: 
                // Первый случай: Передать это в систему. 
                // Последний случай: Показать на экране 
                // соответствующую ошибку. 
                    break;
 
                default:
                // Обработка других исключений. 
                    break;
            } 
 
        case CREATE_THREAD_DEBUG_EVENT: 
        // Как требуется, проверьте или измените регистры потока
        // функциями GetThreadContext и SetThreadContext; 
        // и приостановите и возобновите исполнение кода 
        // потока функциями SuspendThread и ResumeThread. 
            break;

        case CREATE_PROCESS_DEBUG_EVENT: 
        // Как требуется, проверьте или измените регистры
        // начального потока процесса функциями GetThreadContext
        // и SetThreadContext; прочтите из и запишите в 
        // виртуальную память процесса функциями ReadProcessMemory
        // и WriteProcessMemory; и приостановите и возобновите 
        // исполнение кода потока функциями SuspendThread и 
        // ResumeThread. Убедитесь, что закрыли дескриптор 
        // процесса загрузочного модуля функцией CloseHandle.
            break;

        case EXIT_THREAD_DEBUG_EVENT: 
        // Покажите на экране код завершения потока. 
            break;
 
        case EXIT_PROCESS_DEBUG_EVENT: 
        // Покажите на экране код завершения процесса. 
            break;
 
        case LOAD_DLL_DEBUG_EVENT: 
        // Прочтите отладочную информацию включенную в недавно 
        // загруженную DLL. Убедитесь, что закрыли дескриптор 
        // загруженной DLL функцией CloseHandle.
            break;
 
        case UNLOAD_DLL_DEBUG_EVENT: 
        // Покажите на экране сообщение, что DLL была выгружена. 
            break;
 
        case OUTPUT_DEBUG_STRING_EVENT: 
        // Покажите на экране выводимую строку отладки. 
            break;
 
    } 
 
// Возобновим исполнение кода потока, который сообщает
// о событии отладки. 
 
ContinueDebugEvent(DebugEv.dwProcessId, DebugEv.dwThreadId, 
                   dwContinueStatus); 
 
}

 

Назад в оглавление
На главную страницу
Переведено 17.06.2005 15:40 ©Copyright V. Sokovikov
Hosted by uCoz