Поэкспериментируйте немного с ildasm, чтобы привыкнуть к этой программе. Не пугайтесь при виде каких ни будь непонятных данных, дальше будет еще страшнее. :)
Теперь откройте манифест (manifest) и внимательно посмотрите. Ниже я привожу содержание манифеста, полученное мной при помощи утилиты ildasm.
// Microsoft (R) .NET Framework IL Disassembler. Version 1.0.2914.16
// Copyright (C) Microsoft Corp. 1998-2001. All rights reserved.
// VTableFixup Directory:
// No data.
//Это ссылка на основную библиотеку классов .NET
.assembly extern mscorlib {
//Это хеш публичного ключа данной сборки
//он нужен для подтверждения валидности сборки
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
//Версия сборки которая использовалась при создании приложения
.ver 1:0:2411:0
}
//Описание нашей сборки
.assembly Some {
// – The following custom attribute is added automatically, do not uncomment –
// – Следующий атрибут добавлен автоматически, не убирайте комментарий
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,
// bool) = ( 01 00 00 01 00 00 )
//Алгоритм по которому считается хэш
.hash algorithm 0x00008004
//Версия нашей сборки
.ver 0:0:0:0
}
//Название запускаемого файла
.module Some.exe
// MVID: {2FA89A98-AD9F-4E31-8DB1-AB1FFB64A4F4}
//Предпочтительный адрес для загрузки сборки
.imagebase 0x00400000
//Подсистема (консоль, оконное приложение, приложение времени загрузки)
.subsystem 0x00000003
//Выравнивание секций
.file alignment 512
//Зарезервированный флаг
.corflags 0x00000001
Что, вам кажется, что это полная чушь? Ошибаетесь, если в этом разобраться, что, кстати, не так уж и трудно, то вам откроется много очень полезной и порой необходимой информации. В начале вы увидите записи со словами .assembly extern, которые описывают зависимости от внешних сборок, необходимых для функционирования этой программы. А данные, идущие далее в блоке, заключённом в фигурных скобках, описывают версию и контрольную сумму сборки. Эти данные берутся из сборок при компиляции программы, что гарантирует использование именно тех сборок, которые использовались при компиляции и тестировании. Далее следует .assembly, но уже без модификатора extern. С этой директивы и начинается описание нашей с вами сборки. Как вы могли догадаться, .verописывает версию нашей сборки. Ну а .hash algorithmопределяет функцию, по которой будет вычисляться хэш, но об этом я расскажу позднее. Затем идут описания имени самого модуля, подсистемы исполнения, информация о выравнивании секций и еще некоторые данные. Полная документация по этому вопросу находится в Framework SDK. Более подробно об устройстве манифеста я расскажу далее.
ПРИМЕЧАНИЕ
На самом деле, .publickeytokenописывает не контрольную сумму файла, а является хэшем (контрольной суммой) публичного ключа автора, создавшего сборку, на которую ссылается ключ .assembly extern.
Давайте "копнём" поглубже
Как же сборка устроена изнутри? Что у нее "под капотом"? Оказывается, не так все и страшно, как вам могло показаться. Сборка помещается внутри файла в формате PE (Portable Executable), то есть внутри DLL или EXE. Здесь все зависит от того, будет ли сборка самостоятельной программой или "библиотекой". Любая сборка импортирует функции из библиотеки mscoree.dll , которая является частью среды исполнения. Исполняемые файлы (EXE) импортируют из этой библиотеки функцию _CorExeMain, которую они вызывают для своего запуска. А происходит это так: как и в любом exe-файле, в нашем присутствует точка входа - это маленькая функция (6 байт), которая призвана передавать управление функции _CorExeMainиз библиотеки mscoree.dll . Когда данная функция получает управление, она находит в exe-файле свою точку входа и начинает выполнение с нее. Вы можете проверить все сказанное мною сами при помощи утилиты dumpbin, запустив ее с параметрам /imports. Правда, у файла, скомпилированного на Managed C++, вы можете увидеть много других импортов. Не пугайтесь, это нормально, так как MC++ одновременно поддерживает как управляемые, так и неуправляемые данные (managed/unmanaged data). А значит, может делать самостоятельные системные вызовы в обход CLR.
Динамически загружаемые библиотеки импортируют функцию _CorDllMain, которую они вызывают из DllMain, "точки входа" DLL. Сама же функция точки входа ничего, кроме вызова _CorDllMain, не делает. С exe-сборками дело обстоит аналогичным образом, только вместо _CorDllMain, импортируется функция _CorExeMain.
Читать дальше