stringtranslate.com

Портативный исполняемый файл

Формат Portable Executable ( PE ) — это формат файла для исполняемых файлов , объектного кода , DLL и других, используемых в 32- и 64-разрядных версиях операционных систем Windows , а также в средах UEFI . [2] Формат PE — это структура данных, которая инкапсулирует информацию, необходимую загрузчику ОС Windows для управления исполняемым кодом . Сюда входят ссылки на динамические библиотеки для связывания , таблицы экспорта и импорта API , данные управления ресурсами и данные локального хранилища потоков (TLS). В операционных системах NT формат PE используется для EXE , DLL , SYS ( драйвер устройства ), MUI и других типов файлов. В спецификации Unified Extensible Firmware Interface (UEFI) указано, что PE является стандартным форматом исполняемых файлов в средах EFI. [3]

В операционных системах Windows NT PE в настоящее время поддерживает архитектуры набора инструкций (ISA) IA-32 , x86-64 (AMD64/Intel 64), IA-64 , ARM и ARM64 . До Windows 2000 Windows NT (и, следовательно, PE) поддерживала MIPS , Alpha и PowerPC ISA. Поскольку PE используется в Windows CE , она продолжает поддерживать несколько вариантов MIPS, ARM (включая Thumb ) и SuperH ISA. [4]

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

История

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

PE также продолжает обслуживать меняющуюся платформу Windows. Некоторые расширения включают формат .NET PE, версию с поддержкой 64-битного адресного пространства, называемую PE32+, и спецификацию для Windows CE.

Является ли исполняемый код 32- или 64-битным, можно узнать, проверив поле Machine в IMAGE_FILE_HEADER. [6] Являются ли адреса в исполняемом файле 32- или 64-битными, можно узнать, проверив поле Magic в IMAGE_OPTIONAL_HEADER. 10B 16 указывает на файл PE32, тогда как 20B 16 указывает на файл PE32+. [7]

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

Макет

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

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

Импортировать таблицу

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

Переезды

Файлы 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(запись ранее использовалась для метаданных COM+ в приложениях COM+, отсюда и название [ необходима цитата ] ) записью в каталоге данных заголовка PE. IMAGE_COR20_HEADERсильно напоминает необязательный заголовок PE, по сути играя свою роль для загрузчика CLR. [4]

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

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

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

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

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

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

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

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

Ссылки

  1. ^ Андерссон, Хенрик (2015-04-23). ​​"application/vnd.microsoft.portable-executable". IANA . Получено 2017-03-26 .
  2. ^ "Переносимый исполняемый файл (PE) - Определение - Trend Micro IN". www.trendmicro.com . Получено 2022-11-10 .
  3. ^ «Спецификация UEFI, версия 2.8B» (PDF) .В примечании на стр. 15 говорится, что «этот тип образа выбран для того, чтобы образы UEFI могли содержать инструкции Thumb и Thumb2, а сами интерфейсы EFI должны находиться в режиме ARM».
  4. ^ ab "Формат PE (Windows)" . Получено 2017-10-21 .
  5. ^ "/STUB (имя файла-заглушки MS-DOS)". 3 августа 2021 г.
  6. ^ Объяснение трюка PE: Различение 32 и 64 бит невооруженным глазом, Карстен Хан
  7. ^ Формат PE на Microsoft.com
  8. ^ "Переносимый исполняемый файл сверху вниз" . Получено 21 октября 2017 г.
  9. ^ ab "Взгляд внутрь PE: обзор исполняемого файла Win32 Portable". 30 июня 2010 г. Получено 21 октября 2017 г.
  10. ^ Chartier, David (2007-11-30). "Обнаружено: доказательство того, что Mac OS X вскоре сможет запускать приложения Windows". Ars Technica . Получено 2007-12-03 . ... Стивен Эдвардс описывает открытие, что Leopard, по-видимому, содержит недокументированный загрузчик для Portable Executables, типа файла, используемого в 32-разрядных и 64-разрядных версиях Windows. Дальнейшее исследование показало, что собственный загрузчик Leopard пытается найти файлы Windows DLL при попытке загрузить двоичный файл Windows.

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