Составители:
Рубрика:
Мы не будем рассматривать детали организации секции импорта, от-
носящиеся к механизму предварительного связывания.
Вход в таблицу импорта представляет собой структуру, состоящую из
нескольких полей:
long ImportLookupTableRVA;
RVA таблицы имен импорта (ILT). Ранее, до изобретения предва-
рительного связывания, это поле называлось Characteristics.
long TimeDateStamp;
Это поле изначально равно нулю (в PE-файле на диске), но по-
сле загрузки dll-файла в него (уже в памяти) записывается время
загрузки. (В предварительно связанном PE-файле в поле
TimeDateStamp должно быть записано значение -1.)
long ForwarderChain;
Должно быть равно -1.
long NameRVA;
RVA ASCIIZ-строки, содержащей имя dll-файла.
long ImportAddressTableRVA;
RVA таблицы адресов импорта (IAT).
Теперь рассмотрим, как организованы наши идентичные массивы
ILT и IAT. Их элементами являются 32-разрядные целые числа. Если стар-
ший бит (31-й) такого 32-разрядного числа установлен в 1, то оставшиеся
31 бит обозначают порядковый номер импортируемого символа. Если же
старший бит равен 0, то это 32-разрядное число обозначает RVA структу-
ры Hint/Name, в которой хранится имя импортируемого символа.
Структура Hint/Name состоит из трех полей:
short Hint;
Это поле является подсказкой для загрузчика. Оно содержит
предполагаемый номер импортируемого символа. Загрузчик
сначала ищет этот символ по указанному номеру. В случае
неудачи он выполняет бинарный поиск символа по имени.
char Name[x];
Имя импортируемого символа в виде ASCIIZ-строки.
char Pad;
Это поле служит для выравнивания структуры по четной грани-
це, то есть оно присутствует только тогда, когда структура имеет
нечетный размер. Всегда равно нулю.
2.1.4.2. Секция релокаций
В секции релокаций («.reloc») содержится таблица исправлений
(Fix-up Table), в которой перечислены все абсолютные адреса в PE-файле,
которые надо исправить, если файл загружается по адресу, отличному от
указанного в поле ImageBase.
Структура программных компонентов
51
импорта (Import Address Table, далее IAT) и таблицей имен импорта
(Import Lookup Table, далее ILT). Элементы этих массивов описывают
символы, импортируемые из данного dll-файла. При этом каждый массив
заканчивается нулевым элементом.
Директория таблицы адресов импорта в дополнительном заголовке
PE-файла должна указывать на таблицу адресов импорта (IAT).
Рис. 2.5. Схема секции импорта
У тех, кто внимательно прочитал предыдущий абзац, обязательно
должен возникнуть вопрос: а зачем нужно хранить в секции импорта два
идентичных массива ILT и IAT?
Дело в том, что раньше никакого ILT не было и секция импорта со-
держала только массив IAT. При загрузке программы происходило так на-
зываемое связывание, при котором информация из IAT использовалась
для определения адресов импортируемых символов. Эти адреса записыва-
лись загрузчиком прямо в IAT (естественно, в образе PE-файла в памяти,
а не на диске) поверх той информации, которая там содержалась.
Необходимость в дополнительном массиве ILT возникла после изо-
бретения предварительного связывания, при котором таблица адресов
импорта заранее заполняется адресами импортируемых символов. Пред-
варительное связывание осуществляется утилитой BIND, которая вычис-
ляет эти адреса и записывает их прямо в PE-файл на диске. Это позволя-
ет несколько ускорить загрузку программы, но при этом возникают но-
вые проблемы. А что если предварительно связанный dll-файл вдруг из-
менится? Ведь тогда все адреса могут поменяться? Увы, это так. Правда,
загрузчик способен определить этот факт и вычислить новые адреса, и
для этого ему как раз и нужна копия таблицы адресов импорта, которая
находится в ILT.
50
CIL и системное программирование в Microsoft .NET
Import Directory Table
Import Directory Entry 1
Import Directory Entry 2
Import Directory Entry 3
NULL
Import Address
Table
NULL
Import Lookup
Table
NULL
Hint/Name
Table
50 CIL и системное программирование в Microsoft .NET Структура программных компонентов 51 импорта (Import Address Table, далее IAT) и таблицей имен импорта Мы не будем рассматривать детали организации секции импорта, от- (Import Lookup Table, далее ILT). Элементы этих массивов описывают носящиеся к механизму предварительного связывания. символы, импортируемые из данного dll-файла. При этом каждый массив Вход в таблицу импорта представляет собой структуру, состоящую из заканчивается нулевым элементом. нескольких полей: Директория таблицы адресов импорта в дополнительном заголовке long ImportLookupTableRVA; PE-файла должна указывать на таблицу адресов импорта (IAT). RVA таблицы имен импорта (ILT). Ранее, до изобретения предва- рительного связывания, это поле называлось Characteristics. Import Address long TimeDateStamp; Table Это поле изначально равно нулю (в PE-файле на диске), но по- Import Directory Table сле загрузки dll-файла в него (уже в памяти) записывается время NULL загрузки. (В предварительно связанном PE-файле в поле TimeDateStamp должно быть записано значение -1.) Import Directory Entry 1 Hint/Name long ForwarderChain; Table Должно быть равно -1. Import Directory Entry 2 Import Lookup long NameRVA; Table Import Directory Entry 3 RVA ASCIIZ-строки, содержащей имя dll-файла. long ImportAddressTableRVA; NULL NULL RVA таблицы адресов импорта (IAT). Теперь рассмотрим, как организованы наши идентичные массивы ILT и IAT. Их элементами являются 32-разрядные целые числа. Если стар- Рис. 2.5. Схема секции импорта ший бит (31-й) такого 32-разрядного числа установлен в 1, то оставшиеся 31 бит обозначают порядковый номер импортируемого символа. Если же У тех, кто внимательно прочитал предыдущий абзац, обязательно старший бит равен 0, то это 32-разрядное число обозначает RVA структу- должен возникнуть вопрос: а зачем нужно хранить в секции импорта два ры Hint/Name, в которой хранится имя импортируемого символа. идентичных массива ILT и IAT? Структура Hint/Name состоит из трех полей: Дело в том, что раньше никакого ILT не было и секция импорта со- short Hint; держала только массив IAT. При загрузке программы происходило так на- Это поле является подсказкой для загрузчика. Оно содержит зываемое связывание, при котором информация из IAT использовалась предполагаемый номер импортируемого символа. Загрузчик для определения адресов импортируемых символов. Эти адреса записыва- сначала ищет этот символ по указанному номеру. В случае лись загрузчиком прямо в IAT (естественно, в образе PE-файла в памяти, неудачи он выполняет бинарный поиск символа по имени. а не на диске) поверх той информации, которая там содержалась. char Name[x]; Необходимость в дополнительном массиве ILT возникла после изо- Имя импортируемого символа в виде ASCIIZ-строки. бретения предварительного связывания, при котором таблица адресов char Pad; импорта заранее заполняется адресами импортируемых символов. Пред- Это поле служит для выравнивания структуры по четной грани- варительное связывание осуществляется утилитой BIND, которая вычис- це, то есть оно присутствует только тогда, когда структура имеет ляет эти адреса и записывает их прямо в PE-файл на диске. Это позволя- нечетный размер. Всегда равно нулю. ет несколько ускорить загрузку программы, но при этом возникают но- вые проблемы. А что если предварительно связанный dll-файл вдруг из- 2.1.4.2. Секция релокаций менится? Ведь тогда все адреса могут поменяться? Увы, это так. Правда, В секции релокаций («.reloc») содержится таблица исправлений загрузчик способен определить этот факт и вычислить новые адреса, и (Fix-up Table), в которой перечислены все абсолютные адреса в PE-файле, для этого ему как раз и нужна копия таблицы адресов импорта, которая которые надо исправить, если файл загружается по адресу, отличному от находится в ILT. указанного в поле ImageBase.
Страницы
- « первая
- ‹ предыдущая
- …
- 30
- 31
- 32
- 33
- 34
- …
- следующая ›
- последняя »