|
Формат исполняемых PE-файлов
Экспорт
Обычно секция экспорта приблизительно выглядит следующим образом:
Typical Export Layout
я сказал обычно, но я не сказал, что так должно быть, чуть ниже мы сейчас рассмотрим данные экспорта и механизм экспорта, сейчас замечу, что, как и с именами секций, вышеописанную структуру вы найдете в нормальных исполнимых файлах (без наворотов). За исключением Export Directory Table все остальное структурами можно назвать лишь с натяжкой.
Таблица экспорта (Export Directory Table)
Информация экспорта начинается с Export Directory Table, которая описывает требуемую экспортную информацию. Export Directory Table содержит адресную информацию используемую при развязке настраиваемых ссылок в внешние точки входа внутри программы.
Export Directory Table
00h |
DWord |
Flags |
зарезервировано на будущее = 0 |
04h |
DWord |
Time/Date Stamp |
время и дата создания экспортных данных |
08h |
Word |
Major Version |
опять для нас, блин, старший номер версии таблицы экспорта
как хочешь, так и используй |
0Ah |
DWord |
Minor Version |
аналогично, младший |
0Ch |
DWord |
Name RVA |
RVA строки указывающей на имя нашей библиотеки |
10h |
DWord |
Ordinal Base |
начальный номер экспорта, для функций нашей библиотеки, обычно установлено в 1, но не факт |
14h |
DWord |
Num of Functions |
количество функций экспортируемых нашим модулем, является числом элементов массива Address Table см.ниже |
18h |
DWord |
Num of Name Pointers |
число указателей на имена, обычно равно числу функций, но это не так, если у нас есть функции экспортируемые только по номеру |
1Ch |
DWord |
Address Table RVA |
указатель на таблицу адресов (RVA) экспорта |
20h |
DWord |
Name Pointers RVA |
указатель на таблицу указателей на имена экспорта |
24h |
DWord |
Ordinal Table RVA |
указатель на таблицу ординалов экспорта, данный массив по индексам параллелен Name Pointers, элементами являются слова |
Total Structure size |
28h |
Общий размер таблички экспорта |
Для обработки запросов на связывание загрузчик системы ищет:
- импорт по имени: имя в массиве имен, по его индексу ординал, ординал корректируется на базу и этим индексом вычитывается адрес функции из поля массива Address Table
- импорт по ординалу: ординал корректируется на базу и далее, как описано выше
Надо отметить, что таблица экспорта может содержать пропуски, которые отображаются нулевыми значениями адресов экспорта. Импортировать по ординалам очень нежелательно ибо в разных версиях Windows'95 ординалы функций в модулях различаются, не говоря уже об NT и проч.
Таблица адресов экспорта (Address Table)
Данная структура данных содержит адреса экспортируемых функций (их точки входа) экпортируемых данных и т.п. в формате DWord RVA (по 4 байта на элемент). Для доступа к данным используется ординал функции с коррекцией на базу ординалов (Ordinal Base).
Таблица указателей на имена (Name Table Pointers)
Данная структура содержит указатели на имена экспортируемых функций, указатели отсортированы в лексическом порядке для обеспечения возможности бинарного поиска. Каждый указатель занимает 4 байта. Имена функций обычно лежат в секции экспорта, но я опять сказал обычно ;-) Вы их можете помещать не туда. Еще раз повторюсь, секции - нечто эфемерное, обеспечивающее упаковку программы в файле и защиту участков кода, но не больше.
Таблица ординалов (Ordinal Table)
Данная структура совместно с Name Table Pointers формирует 2 параллельных массива, разделенных для облегчения к ним доступа индексированием на родные для процессора данные (слова, двойные слова, но не сложные структуры). Данный массив содержит ординалы экспорта, которые в общем случае являются индексами в Address Table экспорта (за вычетом базы Ordinal Base). Элементами данного массива являются слова (2 байта).
Таблица имен экспорта (Export Name Table)
Эта таблица содержит необязательные (по мнению Microsoft, ничего себе ;-) имена экспортируемых функций. Данный массив используется для совместно с Name Table Pointers и Ordinal Table для обеспечения связывания загрузчиком импорта/экспорта по имени. Механизм описывался выше. Каждый элемент являет собой ASCIZ строку с именем экспортируемой функции. Никто не говорит, что они должны в файле идти друг за другом последовательно, хотя так и построено большинство файлов. Надо отметить, что имена экспорта чувствительны к регистру.
Отметим особенность загрузчика - при связывании, если адрес функции находится в секции экспорта, то на самом деле по указанному адресу лежит строка переадресующая к другой библиотеке экспортирующей данную функцию (с указанием библиотеки и самой функции), это называется передача экспорта (если верить Мэту Питреку, я данную фичу еще не проверял).
[Оглавление]
|
|