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




Обработка _сdесl-подключений


Как показано в главе 12, _stdcail-функции легко подключать, потому что такая функция сама чистит стек; для _cdeci-функций стеки чистит вызывающая функция.

_stdcaii _cdeci — спецификаторы соглашений о вызовах функций в языках C/C++ (см. табл. 6.3 главы 6). — Пер

Кроме того, функции DiagOutputA, DiagOutputW И AfxTrace, имеют параметры переменной длины, так что перехватить их намного труднее. Само подключение — такое же, как и для экспортируемых _stdcaii-функций, но обработка _cdeci-функций должна быть совсем другой. В LIMODSDLL.DLL требовалось, чтобы функция подключения захватила адрес возврата и определила, является ли он диапазоном адресов, в котором пользователь хочет видеть предложения трассировки. После проверки источника функция трассировки либо выполняется, либо игнорируется, после чего выполняется возврат в вызывающую. Для _stdcaii-функций эта обработка очень проста. Можно напрямую вызвать функцию трассировки и возвратиться прямо из функции подключения в вызывающую функцию, потому стек очищается внутри функции подключения. Для _cdeci-функций нужно вернуть стек обратно в первоначальное состояние и затем, если необходимо выполнить функцию трассировки, перейти к ней (а не вызвать ее!).

 Листинг 14-3. cdecl-функция подключения с расширенным макросом 

VOID NAKEDDEF LIMODS_DiagOutputA ( void)

{

// Содержит адрес возврата вызывающей функции

DWORD_PTR dwRet;

// Содержит сохраненный регистр ESI, поэтому отладочные построения

// Visual C++ 6 работают. (ESI использует функцию chkesp,

// вставляемую ключом компилятора /GZ.)

DWORD_PTR dwESI;

_asm PUSH EBP /* Установить стандартный кадр. */

_asm MOV EBP, ESP

_asm SUB ESP, _LOCAL_SIZE /* Сохранить место для локальных */

/* переменных. */

_asm MOV EAX, EBP /* EBP указатели на исходный стек.*/

 _asm ADD EAX, 4 /* Счетчик для PUSH EBP. */ 

_asm MOV EAX, [EAX] /* Получить адрес возврата. */ 

_asm MOV [dwRet], EAX /* Сохранить адрес возврата. */

 _asm MOV [dwESI], ESI /* Сохранить ESI, чтобы в отладочных*/




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