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

UptoLike

предназначена данная сборка. В настоящее время эти поля
должны содержать значения 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, для которой