Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 32 стр.

UptoLike

Мы не будем рассматривать детали организации секции импорта, от-
носящиеся к механизму предварительного связывания.
Вход в таблицу импорта представляет собой структуру, состоящую из
нескольких полей:
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.