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


Чтение и запись памяти - часть 2


По завершении записи в память нужно установить защиту страницы в исходное состояние. Если этого не сделать, подчиненный отладчик может случайно записать страницу (и преуспеть в этом, тогда как должен был потерпеть неудачу). Если бы, например, первоначальным параметром защиты страницы было "только-чтение", то случайная запись подчиненного отладчика привела бы к нарушению доступа. Без восстановления защиты страницы (от записи) случайная запись не сгенерирует соответствующего исключения, и вы будете иметь случай, когда выполнение под отладчиком отличается от выполнения вне его.

Интересная деталь отладочного API Win32: когда появляется событие OUTPUT_DEBUG_STRING_EVENT, то ответственным за получение строки для вывода является основной отладчик. Информация, переданная отладчику, включает расположение и длину строки. Получив это сообщение, отладчик читает память вне подчиненного отладчика. В главе 3 упоминалось, что при выполнении под отладчиком операторы трассировки могут легко изменить поведение приложения. Поскольку все потоки в приложении останавливаются, когда цикл отладки обрабатывает событие, вызов функции OutputDebugString в подчиненном отладчике означает, что все потоки стоят. Листинг 4-3 показывает, как WDBG обрабатывает событие OUTPUT_DEBUG_STRING_EVENT. Заметьте, что функция DBG_ReadProcessMemory является функцией-оболочкой вокруг ReadProcessMemory из LOCALASSIST.DLL.

Листинг 4-3.OutputDebugStringEvent изPROCESSDEBUGEVENTS.CPP

static

DWORD OutputDebugStringEvent ( CDebugBaseUser * pUserClass ,

LPDEBUGGEEINFO pData ,

 DWORD dwProcessId, 

DWORD dwThreadld , 

OUTPUT_DEBUG_STRING_INFO & stODSI )

 {

TCHAR szBuff[ 512 ];

HANDLE hProc = pData->GetProcessHandle (); DWORD dwRead;

 // Читать память.

BOOL bRet = DBG_ReadProcessMemory( hProc ,

stODSI.lpDebugStringData , 

szBuff, min ( sizeof ( szBuff) ,

stODSI.nDebugStringLength), 

&dwRead ) ;

ASSERT ( TRUE == bRet);

if ( TRUE == bRet)

{

// Строку всегда завершает NULL . 

szBuff [ dwRead + 1 ] = _T ( '\0');

 // Преобразовать символы CR/LF .

pUserClass->ConvertCRLF ( szBuff, sizeof ( szBuff)); 

// Послать ковертированную строку в класс пользователя.

 pUserClass->OutputDebugStringEvent ( dwProcessId,

dwThreadld , szBuff ); 

}

 return ( DBG_CONTINUE);

}




Начало  Назад  Вперед



Книжный магазин