Рабочим названием платформы .NET было |
Структура программных компонентов
Формат исполняемых файлов
Исполняемый файл (executable file) - это файл, который может быть загружен в память загрузчиком операционной системы и затем исполнен. В операционной системе Windows исполняемые файлы, как правило, имеют расширения ".exe" и ".dll". Расширение ".exe" имеют программы, которые могут быть непосредственно запущены пользователем. Расширение ".dll" имеют так называемые динамически связываемые библиотеки (dynamic link libraries). Эти библиотеки экспортируют функции, используемые другими программами.
Для того чтобы загрузчик операционной системы мог правильно загрузить исполняемый файл в память, содержимое этого файла должно соответствовать принятому в данной операционной системе формату исполняемых файлов. В разных операционных системах в разное время существовало и до сих пор существует множество различных форматов. В этой главе мы рассмотрим формат Portable Executable (PE). Формат PE - это основной формат для хранения исполняемых файлов в операционной системе Windows. Сборки .NET тоже хранятся в этом формате.
Кроме того, формат PE может использоваться для представления объектных файлов. Объектные файлы служат для организации раздельной компиляции программы. Смысл раздельной компиляции заключается в том, что части программы (модули) компилируются независимо в объектные файлы, которые затем связываются компоновщиком в один исполняемый файл.
А теперь - немного истории. Формат PE был создан разработчиками Windows NT. До этого в операционной системе Windows использовались форматы New Executable (NE) и Linear Executable (LE) для представления исполняемых файлов, а для хранения объектных файлов использовался Object Module Format (OMF). Формат NE предназначался для 16-разрядных приложений Windows, а формат LE, изначально разработанный для OS/2, был уже 32-разрядным. Возникает вопрос: почему разработчики Windows NT решили отказаться от существующих форматов? Ответ становится очевидным, если обратить внимание на то, что большая часть команды, работавшей над созданием Windows NT, ранее работала в Digital Equipment Corporation. Они занимались в DEC разработкой инструментария для операционной системы VAX/VMS, и у них уже были навыки и готовый код для работы с исполняемыми файлами, представленными в формате Common Object File Format (COFF). Соответственно, формат COFF в слегка модифицированном виде был перенесен в Windows NT и получил название PE.
В ".NET Framework Glossary" сказано, что PE - это реализация Microsoft формата COFF. В то же время в [5] утверждается, что PE - это формат исполняемых файлов, а COFF - это формат объектных файлов. Вообще, мы можем наблюдать путаницу в документации Microsoft относительно названия формата. В некоторых местах они называют его COFF, а в некоторых - PE. Правда, можно заметить, что в новых текстах название COFF используется все меньше и меньше. Более того, формат PE постоянно эволюционирует. Например, несколько лет назад в Microsoft отказались от хранения отладочной информации внутри исполняемого файла, и поэтому теперь многие поля в структурах формата COFF просто не используются. Кроме того, формат COFF - 32-разрядный, а последняя редакция формата PE (она называется PE32+) может использоваться на 64-разрядных аппаратных платформах. Поэтому, видимо, дело идет к тому, что название COFF вообще перестанут использовать.
Интересно отметить, что исполняемые файлы в устаревших форматах NE и LE до сих пор поддерживаются Windows. Исполняемые файлы в формате NE можно запускать под управлением NTVDM (NT Virtual DOS Machine), а формат LE используется для виртуальных драйверов устройств (VxD).
Почему в названии формата PE присутствует слово "portable" ("переносимый")? Дело в том, что Windows NT была реализована не только для платформы Intel x86, но и для платформ MIPS R4000, DEC Alpha и PowerPC. И во всех реализациях для хранения исполняемых файлов использовался формат PE. При этом речь не шла о достижении двоичной совместимости между этими платформами, то есть exe-файл, предназначенный для выполнения на платформе Intel x86, нельзя было запустить на PowerPC. Важно понимать, что переносимость формата еще не означает переносимость исполняемых файлов, записанных в этом формате. Формат PE переносим в том смысле, что он слабо зависит от типа процессора и поэтому подходит для разных платформ (в том числе и для платформы .NET).
Далее в этой главе мы не будем затрагивать 64-разрядный вариант формата PE, потому что в настоящее время сборки .NET хранятся в прежнем 32-разрядном формате. Однако отметим, что 64-разрядный PE очень слабо отличается от 32-разрядного. Основное отличие касается разрядности полей структур PE-файла.