Отладка приложений


         

Можно было подумать, что указатель


Можно было подумать, что указатель стека есть просто смещение относительно нескольких локальных переменных, но это не всегда так. Компилятор Visual C++ выполняет довольно большую работу по оптимизации кода, так что при различных наборах флажков оптимизации указатель стека не находится на одном и том же месте в памяти. Можно было объявить переменную как локальную, но компилятор может оптимизировать такую переменную, сохраняя ее в регистре, так что она даже не появится на стеке.

Необходим был гарантированный способ получать указатель стека независимо от того, какие оптимизации были установлены. В этот момент я начал подумывать о том, чтобы объявить функции подключения как _decispec (naked) и создать свой собственный код пролога и эпилога. С этим подходом я имел бы полный контроль над регистром ESP независимо от того, какие установки оптимизации были использованы. Дополнительно я получил бы адрес возврата и параметры, потому что они жестко привязаны к ESP (т. к. расположены в ЕЗР+04H и ESP+08H, соответственно). Имейте в виду, что я не делаю ничего экстраординарного с кодом пролога и эпилога: я просто выполняю обычные операции PUSH EBP и MOV EBP, ESP для пролога и MOV ESP, EBP и POP EBP для эпилога.

ESP — 32-разрядный регистр указателя стека. — Пер.

Поскольку каждую функцию подключения я собирался объявлять со спецификатором _decispec (naked), то пришлось написать пару макросов для обработки пролога и эпилога — HOOKFN_PROLOG и HOOKFN_EPILOG. Я пошел дальше и в макросе пролога HOOKFN_PROLOG объявил некоторые общие локальные переменные, которые будут нужны всем функциям подключения. Это — значение последней ошибки (dwLastError) и структура с информацией о событиях (stEvtinfo), предназначенная для передачи в DeadDetExt.DLL. Кроме того, dwLastError это еще и бит состояния, который нужно сохранять для перехвата функций.

Windows API может возвращать специальный код ошибки через функцию setLastError, которая выдает дополнительную информацию при отказе функции. Этот код ошибки может оказаться настоящим подарком, потому что он сообщает, почему отказала API-функция.

Содержание  Назад  Вперед