Переносимый исполняемый файл - Portable Executable

Переносимый исполняемый файл
Расширение имени файла
.acm, .ax, .cpl, .dll, .drv, .efi, .исполняемый файл, .mui, .ocx, .scr, .sys, .tsp
Тип интернет-СМИ
приложение / vnd.microsoft.portable-исполняемый[1]
РазработанВ настоящее время: Microsoft
Тип форматаДвоичный, исполняемый файл, объект, общие библиотеки
Расширен сИсполняемый файл DOS MZ
COFF

В Переносимый исполняемый файл (PE) формат - это формат файла для исполняемые файлы, объектный код, DLL и другие, используемые в 32-битных и 64-битных версиях Windows операционные системы. Формат PE - это структура данных, которая инкапсулирует информацию, необходимую загрузчику ОС Windows для управления упакованными исполняемый код. Это включает в себя ссылки на динамические библиотеки для связывания, API таблицы экспорта и импорта, данные управления ресурсами и локальное хранилище потока (TLS) данные. На NT операционных систем формат PE используется для исполняемый файл, DLL, SYS (драйвер устройства ) и другие типы файлов. В Расширяемый интерфейс микропрограмм (EFI) В спецификации указано, что PE - это стандартный исполняемый формат в средах EFI.[2]

В операционных системах Windows NT PE в настоящее время поддерживает x86, IA-32, x86-64 (AMD64 / Intel 64), IA-64, РУКА и ARM64 архитектуры наборов команд (Как есть). До Windows 2000, Windows NT (и, следовательно, PE) поддерживает MIPS, Альфа, и PowerPC Как есть. Поскольку PE используется на Windows CE, он продолжает поддерживать несколько вариантов MIPS, РУКА (в том числе Большой палец ), и SuperH Как есть. [3]

Аналогичные форматы PE есть ELF (используется в Linux и большинство других версий Unix ) и Мачо (используется в macOS и iOS ).

История

Microsoft перешла на формат PE с 16-битной NE форматы с введением Windows NT 3.1 Операционная система. Все более поздние версии Windows, включая Windows 95/98 / ME и Win32s Помимо Windows 3.1x, поддерживает файловую структуру. Формат сохранил ограниченную устаревшую поддержку, чтобы преодолеть разрыв между ДОС -системы и NT системы. Например, заголовки PE / COFF по-прежнему включают Исполняемая программа DOS, который по умолчанию Заглушка DOS который отображает сообщение типа «Эта программа не может быть запущена в режиме DOS» (или подобное), хотя это может быть полноценная версия программы для DOS (более поздний заметный случай - установщик Windows 98 SE).[4] Это представляет собой форму толстый двоичный файл. PE также продолжает обслуживать меняющуюся платформу Windows. Некоторые расширения включают формат .NET PE (см. Ниже), 64-разрядную версию PE32 + (иногда PE +) и спецификацию для Windows CE.

Технические подробности

Макет

Структура переносимого исполняемого 32-битного файла

PE-файл состоит из ряда заголовков и разделов, которые сообщают динамический компоновщик как отобразить файл в память. Исполняемый образ состоит из нескольких различных областей, каждая из которых требует разной защиты памяти; поэтому начало каждого раздела должно быть выровнено по границе страницы.[5] Например, обычно .текст раздел (который содержит программный код) отображается как выполнение / только чтение, а .данные раздел (содержащий глобальные переменные) отображается как без выполнения / чтения и записи. Однако, чтобы не тратить лишнее место, разные разделы на диске не выравниваются по страницам. Часть работы динамического компоновщика состоит в том, чтобы сопоставить каждый раздел с памятью отдельно и назначить правильные разрешения для результирующих областей в соответствии с инструкциями, содержащимися в заголовках.[6]

Таблица импорта

Следует отметить, что таблица адресов импорта (IAT), которая используется в качестве таблицы поиска, когда приложение вызывает функцию в другом модуле. Это может быть как в виде импорт по порядку и импорт по имени. Поскольку скомпилированная программа не может знать расположение в памяти библиотек, от которых она зависит, при каждом вызове API требуется косвенный переход. Когда динамический компоновщик загружает модули и объединяет их вместе, он записывает фактические адреса в слоты IAT, так что они указывают на ячейки памяти соответствующих библиотечных функций. Хотя это добавляет дополнительный скачок к стоимости внутримодульного вызова, что приводит к снижению производительности, это дает ключевое преимущество: количество страниц памяти, которые должны быть копирование при записи изменение загрузчиком сводится к минимуму, экономя память и время ввода-вывода диска. Если компилятор заранее знает, что вызов будет межмодульным (через атрибут dllimport), он может создать более оптимизированный код, который просто приведет к косвенному вызову код операции.[6]

Переезды

PE-файлы обычно не содержат позиционно-независимый код. Вместо этого они компилируются в предпочтительный базовый адрес, и все адреса, выдаваемые компилятором / компоновщиком, фиксируются заранее. Если PE-файл не может быть загружен по предпочтительному адресу (потому что он уже занят чем-то другим), операционная система перебазировать Это. Это включает в себя пересчет каждого абсолютного адреса и изменение кода для использования новых значений. Загрузчик делает это, сравнивая предпочтительный и фактический адреса загрузки и вычисляя дельта ценность. Затем он добавляется к предпочтительному адресу, чтобы получить новый адрес ячейки памяти. База переезд сохраняются в списке и при необходимости добавляются в существующую ячейку памяти. Полученный код теперь является частным для процесса и больше не разделяемый, поэтому в этом сценарии теряются многие преимущества DLL по экономии памяти. Это также значительно замедляет загрузку модуля. По этой причине по возможности следует избегать перебазирования, а библиотеки DLL, поставляемые Microsoft, имеют предварительно вычисленные базовые адреса, чтобы не перекрываться. Таким образом, в случае отсутствия перебазирования PE имеет преимущество в виде очень эффективного кода, но при наличии перебазирования использование памяти может быть дорогостоящим. Это контрастирует с ELF который использует полностью независимый от позиции код и глобальную таблицу смещений, в которой время выполнения сокращается в пользу меньшего использования памяти.

.NET, метаданные и формат PE

В исполняемом файле .NET секция кода PE содержит заглушку, которая вызывает CLR запись о запуске виртуальной машины, _CorExeMain или _CorDllMain в mscoree.dll, как это было в Visual Basic исполняемые файлы. Затем виртуальная машина использует имеющиеся метаданные .NET, корень которых, IMAGE_COR20_HEADER (также называемый "заголовком CLR") указывается IMAGE_DIRECTORY_ENTRY_COMHEADER[7] запись в каталоге данных PE-заголовка. IMAGE_COR20_HEADER сильно напоминает необязательный заголовок PE, по сути, играя свою роль для загрузчика CLR.[3]

Данные, связанные с CLR, включая саму корневую структуру, обычно содержатся в разделе общего кода, .текст. Он состоит из нескольких каталогов: метаданных, встроенных ресурсов, строгих имен и нескольких каталогов для взаимодействия с собственным кодом. Каталог метаданных - это набор таблиц, в которых перечислены все отдельные сущности .NET в сборке, включая типы, методы, поля, константы, события, а также ссылки между ними и другими сборками.

Использование в других операционных системах

Формат PE также используется ReactOS, поскольку ReactOS предназначена для двоично-совместимый с виндой. Он также исторически использовался рядом других операционных систем, включая SkyOS и BeOS R3. Однако и SkyOS, и BeOS в конечном итоге перешли на ELF.

Поскольку Платформа разработки Mono намеревается быть двоично совместимым с Microsoft .NET Framework, он использует тот же формат PE, что и реализация Microsoft. То же самое и с кроссплатформенностью Microsoft. .NET Core.

На x86 (-64) Unix-подобный операционных систем, двоичные файлы Windows (в формате PE) могут выполняться с Вино. В HX DOS Extender также использует формат PE для собственных 32-битных двоичных файлов DOS, плюс он может до некоторой степени выполнять существующие двоичные файлы Windows в DOS, таким образом действуя как эквивалент Вино для DOS.

На IA-32 и x86-64 Linux можно также запустить Windows ' DLL под loadlibrary.[8]

Mac OS X 10.5 имеет возможность загружать и анализировать PE-файлы, но не совместим с Windows.[9]

UEFI и прошивка EFI используют Portable Executable файлы, а также Windows ABI x64 соглашение о вызовах для Приложения.

Смотрите также

использованная литература

  1. ^ Андерссон, Хенрик (2015-04-23). "приложение / vnd.microsoft.portable-исполняемый файл". IANA. Получено 2017-03-26.
  2. ^ «Спецификация UEFI, версия 2.8B» (PDF).в примечании на стр. 15 говорится, что «этот тип изображения выбран, чтобы разрешить изображениям UEFI содержать инструкции Thumb и Thumb2, при этом сами интерфейсы EFI определены как находящиеся в режиме ARM».
  3. ^ а б «Формат PE (Windows)». Получено 2017-10-21.
  4. ^ Например. Компоновщик Microsoft имеет / Переключатель STUB прикрепить один
  5. ^ «Переносимый исполняемый файл сверху вниз». Получено 2017-10-21.
  6. ^ а б "Пиринг внутри PE: обзор переносимого исполняемого файла Win32". Получено 2017-10-21.
  7. ^ Запись ранее использовалась для COM + метаданные в приложениях COM +, отсюда и название
  8. ^ https://github.com/taviso/loadlibrary
  9. ^ Шартье, Дэвид (30 ноября 2007 г.). «Обнаружено: свидетельство того, что Mac OS X скоро сможет запускать приложения для Windows». Ars Technica. Получено 2007-12-03. ... Стивен Эдвардс описывает открытие, что Leopard, по-видимому, содержит недокументированный загрузчик для Portable Executables, типа файла, используемого в 32-битных и 64-битных версиях Windows. Дальнейшие поиски показали, что собственный загрузчик Leopard пытается найти файлы DLL Windows при попытке загрузить двоичный файл Windows.

внешние ссылки