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

UptoLike

0x00000080 – секция содержит неинициализированные данные;
0x02000000 – секция может быть удалена из исполняемого фай-
ла (этот флаг установлен для секции «.reloc», содержащей табли-
цу релокаций);
0x20000000 – код секции может быть исполнен;
0x40000000 – секция доступна для чтения;
0x80000000 – секция доступна для записи.
Для секций, содержащих метаданные и CIL-код, необходимо
использовать значение флагов 0x60000020.
2.1.4. Особые секции PE-файла
Секции PE-файла, как правило, содержат исполняемый код и дан-
ные, которые не имеют специального смысла для загрузчика. Но из всяко-
го правила бывают исключения, поэтому далее мы рассмотрим структуру
секции импорта «.idata», а также особенности хранения таблицы релока-
ций в секции «.reloc». В состав PE-файла могут входить и другие особые
секции, но мы не будем их обсуждать, так как они не встречаются в сбор-
ках .NET.
2.1.4.1. Секция импорта
В секции импорта перечисляются все dll-файлы, используемые про-
граммой, а также все функции и глобальные переменные, импортируемые
из этих файлов. Для краткости будем называть такие функции и глобаль-
ные переменные символами.
Директория импорта в дополнительном заголовке PE-файла должна
указывать на данные, расположенные в секции импорта.
Секция импорта содержит названия dll-файлов и имена импортируе-
мых символов, представленные в виде ASCIIZ-строк. При этом использу-
ется непрямая схема хранения этих строк, потому что вся основная ин-
формация в секции импорта организована в виде таблиц, а строковые дан-
ные, в силу их произвольного размера, в таблицах хранить неудобно. По-
этому названия dll-файлов и имена символов компактно хранятся где-то
внутри PE-файла (чаще всего – в каком-нибудь свободном месте секции
импорта), и вместо них в таблицах записываются их RVA.
Схема секции импорта приведена на рис. 2.5. Ключевым элементом
этой секции является таблица импорта (Import Directory Table), представ-
ляющая собой массив так называемых входов в таблицу импорта (Import
Directory Entry). При этом самый последний вход в таблицу импорта за-
полнен нулями и сигнализирует о конце массива.
Каждому dll-файлу, используемому программой, соответствует ровно
один вход в таблицу импорта. Этот вход содержит указатели (в форме
RVA) на два идентичных массива, которые называются таблицей адресов
Структура программных компонентов
49
2.1.3.4. Заголовки секций
Непосредственно после дополнительного заголовка следует массив
заголовков секций. Количество секций и, соответственно, размер этого
массива задается полем NumberOfSections заголовка PE-файла. Секции в
массиве отсортированы по их начальным адресам (по RVA).
Заголовок каждой секции состоит из следующих полей:
char Name[8];
Имя секции представляет собой ASCIIZ-строку, содержащую
не более 8 символов. Если имя содержит ровно 8 символов, то
оно не оканчивается на 0.
long VirtualSize;
Размер секции, когда она загружена в память. Значение этого
поля не нужно выравнивать.
Если размер секции в памяти превышает размер той же секции
в PE-файле (см. далее SizeOfRawData), то разница заполняется
нулями.
long VirtualAddress;
RVA секции, когда она загружена в память.
long SizeOfRawData;
Размер секции в PE-файле, выровненный по значению
FileAlignment из дополнительного заголовка PE-файла.
Если секция содержит только неинициализированные данные,
значение этого поля должно быть равно 0.
long PointerToRawData;
Смещение секции относительно начала PE-файла. Значение
этого поля всегда выровнено по значению FileAlignment из до-
полнительного заголовка PE-файла.
long PointerToRelocations;
Смещение таблицы релокаций для данной секции. Использует-
ся только в объектных файлах – в исполняемых файлах равно 0.
long PointerToLinenumbers;
Смещение информации о номерах строк. В сборках .NET всегда
равно 0.
short NumberOfRelocations;
Количество релокаций для этой секции. В исполняемых файлах
всегда равно 0.
short NumberOfLinenumbers;
Количество номеров строк. В сборках .NET всегда равно 0.
long Characteristics;
Комбинация флагов, задающая свойства секции:
0x00000020 – секция содержит исполняемый код;
0x00000040 – секция содержит инициализированные данные;
48
CIL и системное программирование в Microsoft .NET
48                         CIL и системное программирование в Microsoft .NET   Структура программных компонентов                                     49


2.1.3.4. Заголовки секций                                                                0x00000080 – секция содержит неинициализированные данные;
     Непосредственно после дополнительного заголовка следует массив                      0x02000000 – секция может быть удалена из исполняемого фай-
заголовков секций. Количество секций и, соответственно, размер этого                     ла (этот флаг установлен для секции «.reloc», содержащей табли-
массива задается полем NumberOfSections заголовка PE-файла. Секции в                     цу релокаций);
массиве отсортированы по их начальным адресам (по RVA).                                  0x20000000 – код секции может быть исполнен;
     Заголовок каждой секции состоит из следующих полей:                                 0x40000000 – секция доступна для чтения;
     char Name[8];                                                                       0x80000000 – секция доступна для записи.
           Имя секции представляет собой ASCIIZ-строку, содержащую                       Для секций, содержащих метаданные и CIL-код, необходимо
           не более 8 символов. Если имя содержит ровно 8 символов, то                   использовать значение флагов 0x60000020.
           оно не оканчивается на 0.
     long VirtualSize;                                                         2.1.4. Особые секции PE-файла
           Размер секции, когда она загружена в память. Значение этого              Секции PE-файла, как правило, содержат исполняемый код и дан-
           поля не нужно выравнивать.                                          ные, которые не имеют специального смысла для загрузчика. Но из всяко-
           Если размер секции в памяти превышает размер той же секции          го правила бывают исключения, поэтому далее мы рассмотрим структуру
           в PE-файле (см. далее SizeOfRawData), то разница заполняется        секции импорта «.idata», а также особенности хранения таблицы релока-
           нулями.                                                             ций в секции «.reloc». В состав PE-файла могут входить и другие особые
     long VirtualAddress;                                                      секции, но мы не будем их обсуждать, так как они не встречаются в сбор-
           RVA секции, когда она загружена в память.                           ках .NET.
     long SizeOfRawData;
           Размер секции в PE-файле, выровненный по значению                   2.1.4.1. Секция импорта
           FileAlignment из дополнительного заголовка PE-файла.                      В секции импорта перечисляются все dll-файлы, используемые про-
           Если секция содержит только неинициализированные данные,            граммой, а также все функции и глобальные переменные, импортируемые
           значение этого поля должно быть равно 0.                            из этих файлов. Для краткости будем называть такие функции и глобаль-
     long PointerToRawData;                                                    ные переменные символами.
           Смещение секции относительно начала PE-файла. Значение                    Директория импорта в дополнительном заголовке PE-файла должна
           этого поля всегда выровнено по значению FileAlignment из до-        указывать на данные, расположенные в секции импорта.
           полнительного заголовка PE-файла.                                         Секция импорта содержит названия dll-файлов и имена импортируе-
     long PointerToRelocations;                                                мых символов, представленные в виде ASCIIZ-строк. При этом использу-
           Смещение таблицы релокаций для данной секции. Использует-           ется непрямая схема хранения этих строк, потому что вся основная ин-
           ся только в объектных файлах – в исполняемых файлах равно 0.        формация в секции импорта организована в виде таблиц, а строковые дан-
     long PointerToLinenumbers;                                                ные, в силу их произвольного размера, в таблицах хранить неудобно. По-
           Смещение информации о номерах строк. В сборках .NET всегда          этому названия dll-файлов и имена символов компактно хранятся где-то
           равно 0.                                                            внутри PE-файла (чаще всего – в каком-нибудь свободном месте секции
     short NumberOfRelocations;                                                импорта), и вместо них в таблицах записываются их RVA.
           Количество релокаций для этой секции. В исполняемых файлах                Схема секции импорта приведена на рис. 2.5. Ключевым элементом
           всегда равно 0.                                                     этой секции является таблица импорта (Import Directory Table), представ-
     short NumberOfLinenumbers;                                                ляющая собой массив так называемых входов в таблицу импорта (Import
           Количество номеров строк. В сборках .NET всегда равно 0.            Directory Entry). При этом самый последний вход в таблицу импорта за-
     long Characteristics;                                                     полнен нулями и сигнализирует о конце массива.
           Комбинация флагов, задающая свойства секции:                              Каждому dll-файлу, используемому программой, соответствует ровно
           0x00000020 – секция содержит исполняемый код;                       один вход в таблицу импорта. Этот вход содержит указатели (в форме
           0x00000040 – секция содержит инициализированные данные;             RVA) на два идентичных массива, которые называются таблицей адресов