Составители:
Рубрика:
предназначена данная сборка. В настоящее время эти поля
должны содержать значения 2 и 0 соответственно.
struct { long RVA, Size; } Metadata;
В этом поле указываются RVA и размер в байтах метаданных в
образе PE-файла.
long Flags;
Это поле описывает свойства сборки. Для обычных сборок .NET
равно 1.
long EntryPointToken;
Токен метаданных, указывающий на точку входа в сборку.
struct { long RVA, Size; } Resources;
В этом поле указываются RVA и размер в байтах ресурсов сборки.
struct { long RVA, Size; } StrongNameSignature;
В этом поле указываются RVA и размер данных, используемых
загрузчиком CLI для контроля версий связываемых динамиче-
ских библиотек.
long CodeManagerTable[2];
Это поле не используется и всегда заполнено нулями.
struct { long RVA, Size; } VTableFixups;
В этом поле указываются RVA и размер данных, используемых
загрузчиком для исправления таблиц виртуальных методов. Так
как эти таблицы, вообще говоря, порождаются только некоторы-
ми «экзотическими» компиляторами (предположительно, Visual
C++ With Managed Extensions), мы их рассматривать не будем.
long ExportAddressTableJumps[2];
Это поле не используется и всегда заполнено нулями.
long ManagedNativeHeader[2];
Это поле не используется и всегда заполнено нулями.
2.1.6. Пример генерации PE-файла
В приложении A приведен исходный код программы pegen, демонст-
рирующей генерацию PE-файла. Эта программа создает сборку hello.exe,
работа которой заключается в дублировании строки, введенной пользова-
телем с клавиатуры. Несмотря на то, что генерируемая сборка столь при-
митивна, программа pegen может служить основой для разработки реаль-
ного генератора исполняемых файлов .NET.
Программа pegen написана на языке C и состоит из двух частей:
1. модуль генерации PE-файла, оформленный как отдельная биб-
лиотека;
2. главный модуль, использующий модуль генерации для создания
простейшей сборки .NET.
Структура программных компонентов
53
Директория релокаций в дополнительном заголовке PE-файла долж-
на указывать на таблицу исправлений.
Таблица исправлений разбита на блоки. Каждый блок описывает ис-
правления, которые нужно внести в определенную страницу (4K байт) за-
груженного в память PE-файла. Каждый блок должен начинаться на 32-
битовой границе.
В начале каждого блока располагается заголовок, состоящий из сле-
дующих полей:
long PageRVA;
Это поле содержит RVA страницы PE-файла, исправления в ко-
торой описываются данным блоком.
long BlockSize;
Суммарный размер блока в байтах, включая заголовок.
После заголовка следует массив 16-разрядных слов, каждое из кото-
рых описывает одно исправление. При этом старшие четыре бита каждого
из этих слов задают тип исправления, а остальные 12 бит обозначают сме-
щение относительно начала страницы, соответствующей данному блоку.
В сборках .NET в качестве типа исправления используется значение
3. Этот тип означает, что по заданному смещению относительно начала
описываемой блоком страницы PE-файла находится 32-разрядное значе-
ние, которое необходимо исправить.
Рассмотрим, как загрузчик выполняет исправление образа PE-файла.
Пусть ActualAddress – это адрес, по которому загружен PE-файл. И пусть
delta – это смещение исправляемого 32-разрядного значения относитель-
но начала страницы. Тогда адрес исправляемого значения вычисляется
следующим образом:
FixupAddress = ActualAddress + PageRVA + delta;
Внесение исправления в 32-разрядное значение, которое находится
по адресу FixupAddress, выполняется так (преобразования типов для про-
стоты не указаны):
*FixupAddress += ActualAddress – ImageBase;
2.1.5. Заголовок CLI
Директория заголовка CLI в дополнительном заголовке PE-файла
должна указывать на заголовок CLI, который служит главным образом для
локализации метаданных в PE-файле.
Заголовок CLI состоит из следующих полей:
long Cb;
Размер заголовка в байтах.
short MajorRuntimeVersion;
short MinorRuntimeVersion;
Эти два поля содержат информацию о версии CLR, для которой
52
CIL и системное программирование в Microsoft .NET
52 CIL и системное программирование в Microsoft .NET Структура программных компонентов 53 Директория релокаций в дополнительном заголовке PE-файла долж- предназначена данная сборка. В настоящее время эти поля на указывать на таблицу исправлений. должны содержать значения 2 и 0 соответственно. Таблица исправлений разбита на блоки. Каждый блок описывает ис- struct { long RVA, Size; } Metadata; правления, которые нужно внести в определенную страницу (4K байт) за- В этом поле указываются RVA и размер в байтах метаданных в груженного в память PE-файла. Каждый блок должен начинаться на 32- образе PE-файла. битовой границе. long Flags; В начале каждого блока располагается заголовок, состоящий из сле- Это поле описывает свойства сборки. Для обычных сборок .NET дующих полей: равно 1. long PageRVA; long EntryPointToken; Это поле содержит RVA страницы PE-файла, исправления в ко- Токен метаданных, указывающий на точку входа в сборку. торой описываются данным блоком. struct { long RVA, Size; } Resources; long BlockSize; В этом поле указываются RVA и размер в байтах ресурсов сборки. Суммарный размер блока в байтах, включая заголовок. struct { long RVA, Size; } StrongNameSignature; После заголовка следует массив 16-разрядных слов, каждое из кото- В этом поле указываются RVA и размер данных, используемых рых описывает одно исправление. При этом старшие четыре бита каждого загрузчиком CLI для контроля версий связываемых динамиче- из этих слов задают тип исправления, а остальные 12 бит обозначают сме- ских библиотек. щение относительно начала страницы, соответствующей данному блоку. long CodeManagerTable[2]; В сборках .NET в качестве типа исправления используется значение Это поле не используется и всегда заполнено нулями. 3. Этот тип означает, что по заданному смещению относительно начала struct { long RVA, Size; } VTableFixups; описываемой блоком страницы PE-файла находится 32-разрядное значе- В этом поле указываются RVA и размер данных, используемых ние, которое необходимо исправить. загрузчиком для исправления таблиц виртуальных методов. Так Рассмотрим, как загрузчик выполняет исправление образа PE-файла. как эти таблицы, вообще говоря, порождаются только некоторы- Пусть ActualAddress – это адрес, по которому загружен PE-файл. И пусть ми «экзотическими» компиляторами (предположительно, Visual delta – это смещение исправляемого 32-разрядного значения относитель- C++ With Managed Extensions), мы их рассматривать не будем. но начала страницы. Тогда адрес исправляемого значения вычисляется long ExportAddressTableJumps[2]; следующим образом: Это поле не используется и всегда заполнено нулями. FixupAddress = ActualAddress + PageRVA + delta; long ManagedNativeHeader[2]; Внесение исправления в 32-разрядное значение, которое находится Это поле не используется и всегда заполнено нулями. по адресу FixupAddress, выполняется так (преобразования типов для про- стоты не указаны): 2.1.6. Пример генерации PE-файла *FixupAddress += ActualAddress – ImageBase; В приложении A приведен исходный код программы pegen, демонст- рирующей генерацию PE-файла. Эта программа создает сборку hello.exe, 2.1.5. Заголовок CLI работа которой заключается в дублировании строки, введенной пользова- Директория заголовка CLI в дополнительном заголовке PE-файла телем с клавиатуры. Несмотря на то, что генерируемая сборка столь при- должна указывать на заголовок CLI, который служит главным образом для митивна, программа pegen может служить основой для разработки реаль- локализации метаданных в PE-файле. ного генератора исполняемых файлов .NET. Заголовок CLI состоит из следующих полей: Программа pegen написана на языке C и состоит из двух частей: long Cb; 1. модуль генерации PE-файла, оформленный как отдельная биб- Размер заголовка в байтах. лиотека; short MajorRuntimeVersion; 2. главный модуль, использующий модуль генерации для создания short MinorRuntimeVersion; простейшей сборки .NET. Эти два поля содержат информацию о версии CLR, для которой
Страницы
- « первая
- ‹ предыдущая
- …
- 31
- 32
- 33
- 34
- 35
- …
- следующая ›
- последняя »