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

UptoLike

unsigned short MinorRuntimeVersion;
struct IMAGE_DATA_DIRECTORY MetaData;
unsigned long Flags;
unsigned long EntryPointToken;
struct IMAGE_DATA_DIRECTORY NotUsed[6];
}CLI_HEADER;
struct _IMPORT_TABLE {
// Import Address Table
unsigned long HintNameTableRVA2;
unsigned long zero2;
// Вход в таблицу импорта
unsigned long ImportLookupTableRVA;
unsigned long TimeDateStamp;
unsigned long ForwarderChain;
unsigned long NameRVA;
unsigned long ImportAddressTableRVA;
unsigned char zero[20];
// Import Lookup Table
unsigned long HintNameTableRVA1;
unsigned long zero1;
// Hint/Name Table
unsigned short Hint;
char Name[12];
// Dll name (“mscoree.dll”)
char DllName[12];
}IMPORT_TABLE;
};
Поле JmpAddress заполняется значением выражения:
RVA_OF_CLI(inP) + OFFSETOF(struct CLI_SECTION_IMAGE,IMPORT_TABLE.Hint)
+ inP->ImageBase;
Заметим, что
#define OFFSETOF(s,m) (size_t)&(((s *)0)->m).
Таким образом, к абсолютному адресу секции «.cli» прибавляется
смещение поля Hint в структуре CLI_SECTION_IMAGE.
Сразу за точкой входа находится заголовок CLI, который служит для
определения положения метаданных в PE-файле. В заголовке находится
информация об RVA и размере метаданных, а также информация о версии
CLR, для которой предназначена сборка и токен метаданных, указываю-
щий на точку входа в сборку. У DLL токен точки входа равен 0, т.к. DLL
не может сама выполнять какие-либо действия.
Структура программных компонентов
61
В заключение структура HEADERS пишется в начало выходного файла,
причем записывается количество байт, равное значению макроса
SIZE_OF_HEADERS(params), который объявлен следующим образом:
#define SIZEOF_HEADERS(params) \
align(sizeof(struct HEADERS), params->FileAlignment)
Обычно размер структуры HEADERS не кратен
inP->FileAlignment, следовательно разница дописывается нулями.
2.1.6.2. Этап 2. Генерация секции «.text»
Функция, выполняющая работу на этом этапе – make_text_section.
Прототип функции:
void make_text_section (FILE* file, PINPUT_PARAMETERS inP);
В секции «.text» находятся метаданные и тела методов. Сначала в па-
мяти выделяется массив, кратный выравниванию в файле. Размер масси-
ва задается макросом SIZEOF_TEXT(params), который определен следующим
образом:
#define SIZEOF_TEXT(params) \
align(params->SizeOfMetadata+params->SizeOfCilCode, \
params->FileAlignment)
Макрос принимает в качестве аргумента блок входных параметров.
В выделенную память записываются метаданные из массива
metadata и тела методов из массива cilcode, адреса которых передаются в
функцию через поля inP->metadata и inP->cilcode блока входных параме-
тров. Затем этот массив записывается в выходной файл сразу после заго-
ловка HEADERS. Если размер метаданных и CIL-кода не кратен
inP->FileAlignment, то разница дописывается нулями.
2.1.6.3. Этап 3. Генерация секции «.cli»
Всю работу на этом этапе выполняет функция make_cli_section. Про-
тотип функции:
void make_cli_section (FILE* file, PINPUT_PARAMETERS inP);
В секции «.cli» содержится структура CLI_SECTION_IMAGE, в которой
находится точка входа в приложение, заголовок CLI, таблица импорта и
таблица адресов импорта:
struct CLI_SECTION_IMAGE {
struct _JMP_STUB { // Точка входа
unsigned short JmpInstruction;
unsigned long JmpAddress;
}JMP_STUB;
struct _CLI_HEADER { // Заголовок CLI
unsigned long cb;
unsigned short MajorRuntimeVersion;
60
CIL и системное программирование в Microsoft .NET
60                          CIL и системное программирование в Microsoft .NET   Структура программных компонентов                                       61


     В заключение структура HEADERS пишется в начало выходного файла,                       unsigned short     MinorRuntimeVersion;
причем записывается количество байт, равное значению макроса                                struct IMAGE_DATA_DIRECTORY MetaData;
SIZE_OF_HEADERS(params), который объявлен следующим образом:                                unsigned long       Flags;
     #define SIZEOF_HEADERS(params) \                                                       unsigned long       EntryPointToken;
     align(sizeof(struct HEADERS), params->FileAlignment)                                   struct IMAGE_DATA_DIRECTORY NotUsed[6];
     Обычно размер структуры HEADERS не кратен                                            }CLI_HEADER;
inP->FileAlignment, следовательно разница дописывается нулями.
                                                                                          struct _IMPORT_TABLE {
2.1.6.2. Этап 2. Генерация секции «.text»                                                            // Import Address Table
     Функция, выполняющая работу на этом этапе – make_text_section.                         unsigned long         HintNameTableRVA2;
Прототип функции:                                                                           unsigned long         zero2;
     void make_text_section (FILE* file, PINPUT_PARAMETERS inP);                                     // Вход в таблицу импорта
     В секции «.text» находятся метаданные и тела методов. Сначала в па-                    unsigned long         ImportLookupTableRVA;
мяти выделяется массив, кратный выравниванию в файле. Размер масси-                         unsigned long         TimeDateStamp;
ва задается макросом SIZEOF_TEXT(params), который определен следующим                       unsigned long         ForwarderChain;
образом:                                                                                    unsigned long         NameRVA;
     #define SIZEOF_TEXT(params)                             \                              unsigned long         ImportAddressTableRVA;
       align(params->SizeOfMetadata+params->SizeOfCilCode,   \                              unsigned char         zero[20];
       params->FileAlignment)                                                                        // Import Lookup Table
     Макрос принимает в качестве аргумента блок входных параметров.                         unsigned long         HintNameTableRVA1;
     В выделенную память записываются метаданные из массива                                 unsigned long         zero1;
metadata и тела методов из массива cilcode, адреса которых передаются в                              // Hint/Name Table
функцию через поля inP->metadata и inP->cilcode блока входных параме-                       unsigned short        Hint;
тров. Затем этот массив записывается в выходной файл сразу после заго-                      char        Name[12];
ловка HEADERS. Если размер метаданных и CIL-кода не кратен                                           // Dll name (“mscoree.dll”)
inP->FileAlignment, то разница дописывается нулями.                                         char        DllName[12];
                                                                                          }IMPORT_TABLE;
2.1.6.3. Этап 3. Генерация секции «.cli»                                             };
     Всю работу на этом этапе выполняет функция make_cli_section. Про-
тотип функции:                                                                       Поле JmpAddress заполняется значением выражения:
     void make_cli_section (FILE* file, PINPUT_PARAMETERS inP);                      RVA_OF_CLI(inP) + OFFSETOF(struct CLI_SECTION_IMAGE,IMPORT_TABLE.Hint)
     В секции «.cli» содержится структура CLI_SECTION_IMAGE, в которой                + inP->ImageBase;
находится точка входа в приложение, заголовок CLI, таблица импорта и                 Заметим, что
таблица адресов импорта:                                                             #define OFFSETOF(s,m) (size_t)&(((s *)0)->m).
     struct CLI_SECTION_IMAGE {                                                      Таким образом, к абсолютному адресу секции «.cli» прибавляется
        struct _JMP_STUB {               // Точка входа                         смещение поля Hint в структуре CLI_SECTION_IMAGE.
          unsigned short JmpInstruction;                                             Сразу за точкой входа находится заголовок CLI, который служит для
          unsigned long JmpAddress;                                             определения положения метаданных в PE-файле. В заголовке находится
        }JMP_STUB;                                                              информация об RVA и размере метаданных, а также информация о версии
        struct _CLI_HEADER { // Заголовок CLI                                   CLR, для которой предназначена сборка и токен метаданных, указываю-
          unsigned long        cb;                                              щий на точку входа в сборку. У DLL токен точки входа равен 0, т.к. DLL
          unsigned short       MajorRuntimeVersion;                             не может сама выполнять какие-либо действия.