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

UptoLike

execute/read for EXEs or 0 for DLLs». Налицо две ошибки: лиш-
ний ноль в адресе (который подчеркнут), а также информация о
том, что для dll-файлов поле должно быть равно 0.
long BaseOfCode;
RVA первой кодовой секции в PE-файле.
Описание этого поля в [2] абсолютно неправильное: «RVA of the
code section, always 0x00400000 for exes and 0x10000000 for DLL.»
Авторы явно путают относительные адреса с абсолютными, а
также базовый адрес образа PE-файла в памяти с адресом кодо-
вой секции.
long BaseOfData;
RVA первой секции, содержащей данные. Видимо, не использу-
ется загрузчиком, потому что различные версии компоновщика
по-разному устанавливают это поле. В 64-разрядной версии
формата PE от этого поля вообще отказались.
В сборках .NET, не содержащих секций с данными, принято за-
писывать в это поле RVA секции, которая могла бы идти непо-
средственно после последней секции в PE-файле.
Следующие поля специфичны для Windows NT:
long ImageBase;
Предпочтительный базовый адрес, по которому PE-файл загру-
жается в память (то есть, если файл загружается по этому адресу,
то применение таблицы релокаций не нужно). Для exe-файлов,
как правило, равен 0x400000, а для dll-файлов – 0x10000000.
Нужно отметить, что в выборе базового адреса для dll-файлов
наблюдается большой плюрализм мнений. Например, dll-фай-
лы, сгенерированные компилятором C#, содержат в поле
ImageBase значение 0x11000000. А dll-файлы, сгенерированные
ассемблером ILASM, содержат в этом поле значение 0x400000
(как и exe-файлы).
long SectionAlignment;
Задает выравнивание секций в памяти. Для сборок .NET всегда
равно 0x2000.
long FileAlignment;
Задает выравнивание секций в PE-файле. Для сборок .NET раз-
решены значения 0x200 и 0x1000.
unsigned short OSMajor;
Старшее число версии Windows, для которой предназначена
сборка. Это поле игнорируется загрузчиком, и в случае сборок
.NET должно содержать значение 4.
unsigned short OSMinor;
Младшее число версии Windows, для которой предназначена
Структура программных компонентов
45
char LMinor;
Младшее число версии компоновщика. Для сборок .NET – 0.
long CodeSize;
Суммарный размер всех кодовых секций, всегда выровнен по
значению SectionAlignment (см. далее).
long InitializedDataSize;
Суммарный размер всех секций, содержащих инициализиро-
ванные данные. Выровнен по значению SectionAlignment (см.
далее). Для сборок .NET характерно то, что в состав секций, со-
держащих инициализированные данные, включают секции с
метаданными и CIL-кодом.
long UninitializedDataSize;
Суммарный размер всех секций, содержащих неинициализиро-
ванные данные. В сборках .NET, как правило, это поле содержит
значение 0 (нет таких секций).
long EntryPointRVA;
RVA точки входа в программу. Для dll-файлов (обычных, не сбо-
рок .NET) может быть равен 0, а может указывать на код, вызы-
ваемый в процессе инициализации, завершения работы, а также
во время создания или уничтожения потоков управления.
Передаче управления на точку входа всегда предшествует корре-
ктировка абсолютных адресов (в соответствии с таблицей рело-
каций), а также формирование таблицы адресов импорта.
Для сборок .NET (как exe, так и dll) значение этого поля всегда
указывает на 6 байт, расположенных в кодовой секции PE-фай-
ла. Эти 6 байт начинаются с двух байтов 0xFF 0x25, за которыми
следует некий абсолютный адрес x. Тем самым кодируется сле-
дующая инструкция:
jmp dword ptr ds:[x]
Для exe-файлов адрес x представляет собой сумму значения по-
ля ImageBase (как правило, это 0x400000) и RVA ячейки в табли-
це адресов импорта, которая соответствует функции
_CorExeMain, импортируемой из динамической библиотеки
mscoree.dll.
Для dll-файлов адрес x представляет собой сумму значения поля
ImageBase (как правило, это либо 0x400000, либо 0x10000000, ли-
бо 0x11000000) и RVA ячейки в таблице адресов импорта, кото-
рая соответствуюет функции _CorDllMain, импортируемой из ди-
намической библиотеки mscoree.dll.
Интересно, что описание этого поля в [2] явно не соответствует
действительности: «RVA of entry point, needs to point to bytes 0xFF
0x25 followed by the RVA+0x4000000 in a section marked
44
CIL и системное программирование в Microsoft .NET
44                            CIL и системное программирование в Microsoft .NET   Структура программных компонентов                                       45


     char LMinor;                                                                           execute/read for EXEs or 0 for DLLs». Налицо две ошибки: лиш-
          Младшее число версии компоновщика. Для сборок .NET – 0.                           ний ноль в адресе (который подчеркнут), а также информация о
     long CodeSize;                                                                         том, что для dll-файлов поле должно быть равно 0.
          Суммарный размер всех кодовых секций, всегда выровнен по                     long BaseOfCode;
          значению SectionAlignment (см. далее).                                            RVA первой кодовой секции в PE-файле.
     long InitializedDataSize;                                                              Описание этого поля в [2] абсолютно неправильное: «RVA of the
          Суммарный размер всех секций, содержащих инициализиро-                            code section, always 0x00400000 for exes and 0x10000000 for DLL.»
          ванные данные. Выровнен по значению SectionAlignment (см.                         Авторы явно путают относительные адреса с абсолютными, а
          далее). Для сборок .NET характерно то, что в состав секций, со-                   также базовый адрес образа PE-файла в памяти с адресом кодо-
          держащих инициализированные данные, включают секции с                             вой секции.
          метаданными и CIL-кодом.                                                     long BaseOfData;
     long UninitializedDataSize;                                                            RVA первой секции, содержащей данные. Видимо, не использу-
          Суммарный размер всех секций, содержащих неинициализиро-                          ется загрузчиком, потому что различные версии компоновщика
          ванные данные. В сборках .NET, как правило, это поле содержит                     по-разному устанавливают это поле. В 64-разрядной версии
          значение 0 (нет таких секций).                                                    формата PE от этого поля вообще отказались.
     long EntryPointRVA;                                                                    В сборках .NET, не содержащих секций с данными, принято за-
          RVA точки входа в программу. Для dll-файлов (обычных, не сбо-                     писывать в это поле RVA секции, которая могла бы идти непо-
          рок .NET) может быть равен 0, а может указывать на код, вызы-                     средственно после последней секции в PE-файле.
          ваемый в процессе инициализации, завершения работы, а также                  Следующие поля специфичны для Windows NT:
          во время создания или уничтожения потоков управления.                        long ImageBase;
          Передаче управления на точку входа всегда предшествует корре-                     Предпочтительный базовый адрес, по которому PE-файл загру-
          ктировка абсолютных адресов (в соответствии с таблицей рело-                      жается в память (то есть, если файл загружается по этому адресу,
          каций), а также формирование таблицы адресов импорта.                             то применение таблицы релокаций не нужно). Для exe-файлов,
          Для сборок .NET (как exe, так и dll) значение этого поля всегда                   как правило, равен 0x400000, а для dll-файлов – 0x10000000.
          указывает на 6 байт, расположенных в кодовой секции PE-фай-                       Нужно отметить, что в выборе базового адреса для dll-файлов
          ла. Эти 6 байт начинаются с двух байтов 0xFF 0x25, за которыми                    наблюдается большой плюрализм мнений. Например, dll-фай-
          следует некий абсолютный адрес x. Тем самым кодируется сле-                       лы, сгенерированные компилятором C#, содержат в поле
          дующая инструкция:                                                                ImageBase значение 0x11000000. А dll-файлы, сгенерированные
         jmp dword ptr ds:[x]                                                               ассемблером ILASM, содержат в этом поле значение 0x400000
          Для exe-файлов адрес x представляет собой сумму значения по-                      (как и exe-файлы).
          ля ImageBase (как правило, это 0x400000) и RVA ячейки в табли-               long SectionAlignment;
          це адресов импорта, которая соответствует функции                                 Задает выравнивание секций в памяти. Для сборок .NET всегда
          _CorExeMain, импортируемой из динамической библиотеки                             равно 0x2000.
          mscoree.dll.                                                                 long FileAlignment;
          Для dll-файлов адрес x представляет собой сумму значения поля                     Задает выравнивание секций в PE-файле. Для сборок .NET раз-
          ImageBase (как правило, это либо 0x400000, либо 0x10000000, ли-                   решены значения 0x200 и 0x1000.
          бо 0x11000000) и RVA ячейки в таблице адресов импорта, кото-                 unsigned short OSMajor;
          рая соответствуюет функции _CorDllMain, импортируемой из ди-                      Старшее число версии Windows, для которой предназначена
          намической библиотеки mscoree.dll.                                                сборка. Это поле игнорируется загрузчиком, и в случае сборок
          Интересно, что описание этого поля в [2] явно не соответствует                    .NET должно содержать значение 4.
          действительности: «RVA of entry point, needs to point to bytes 0xFF          unsigned short OSMinor;
          0x25 followed by the RVA+0x4000000 in a section marked                            Младшее число версии Windows, для которой предназначена