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

       

Создание или уничтожение SEH-кадра


Первые инструкции после установки кадра стека часто похожи на следующий фрагмент, который является стандартным кодом, начинающим _try-блок. Первый узел в цепочке SEH-обработчиков расположен в TIB со смещением 0. В показанном ниже фрагменте кода дизассемблера компилятор помещает в стек значение данных и указатель на функцию _except_ handlers. Первая инструкция MOV обращается к TIB. Смещение 0 указывает, что узел добавляется к вершине цепочки исключений. Две последних инструкции показывают, каким образом код перемещает фактический узел в цепочку

PUSH 004060d0

PUSH 004014a0

MOV EAX , FS:[00000000]

PUSH EAX



MOV DWORD PTR FS:[0] , ESP

Хотя этот пример довольно прост и понятен, компилятор не всегда производит такой аккуратный код. Иногда он расширяет область создания SEH-кадра. В зависимости от флажков генерации кода и оптимизации, компилятор перемещает окружающие инструкции так, чтобы усилить преимущества конвейерной обработки CPU. Следующий пример дизассемблерного кода, в котором загружены символы библиотеки KERNEL32.DLL, демонстрирует запуск функции IsBadReadPtr из Microsoft Windows NT 4.

MOV EAX , FS:[00000000h]

PUSH EBP

MOV EBP , ESP

PUSH 0FFh

PUSH 77F3DlE8h

PUSH _except_handler3

PUSH EAX

MOV EAX , [BaseStaticServerData];

MOV DWORD PTR FS:[0000000h] , ESP

Как показывает следующий фрагмент кода, уничтожение SEH-кадра намного проще, чем его создание. Основной момент, который нужно запомнить, это то, что запись FS: [0] означает доступ к SEH.

MOV ЕСХ , DWORD PTR [EBP-lOh] . 

MOV DWORD PTR FS:[0] , ECX

Организация доступа к TIB

Значение в FS:[18] является линейным адресом структуры TIB. В следующем фрагменте кода реализация GetCurrentThreadid (из Windows 2000) получает сначала линейный адрес TIB-блока и затем, в позиции со смещением 0x24 (в Т1В-блоке) — фактический идентификатор (ID) потока.

GetCurrentThreadid:

MOV EAX , FS:[00000018h]

MOV EAX , DWORD PTR [EAX+024h]

RET

Доступ к локальному хранилищу потока

Локальное хранилище потока (Thread Local Storage — TLS) — это механизм Win32, который позволяет каждому потоку (в многопоточной ситуации) иметь свой собственный экземпляр глобальных переменных. Указатель на массив локального хранилища потока размещается в структуре TIB со смещением 0х2С. Следующий фрагмент кода дизассемблера показывает, как получить доступ к указателю локального хранилища потока.

MOV ЕСХ , DWORD PTR FS:[2Ch] 

MOV EDX , DWORD PTR [ECX+EAX*4]



Содержание раздела