Portable Executable
Переносимый исполняемый файл | |
---|---|
Расширение |
.exe ,.dll ,.sys ,.scr ,.drv ,.efi ,.acm ,.ax ,.mui или.tsp |
MIME-тип | application/vnd.microsoft.portable-executable[1]иapplication/efi[2] |
Тип формата | двоичный,исполняемый,объектный,динамическая библиотека |
![]() |
Portable Executable(PE,«переносимый исполняемый») —форматисполняемых файлов,объектного кодаидинамических библиотек(DLL), используемый в 32- и 64-разрядных версияхоперационной системыMicrosoft Windows.Формат PE представляет собой структуру данных, содержащую всю информацию, необходимуюPE-загрузчикудля отображения файла в память. Исполняемый код включает в себя ссылки для связывания динамически загружаемых библиотек, таблицы экспорта и импортаAPI-функций, данные для управления ресурсами и данные локальной памяти потока (TLS). В операционных системах семействаWindows NTформат PE используется дляEXE,DLL,SYS(драйверов устройств) и других типов исполняемых файлов.
PE представляет собой модифицированную версиюCOFF-формата файла дляUnix.PE/COFF— альтернативный термин при разработке Windows.
На операционных системах семейства Windows NT формат PE в настоящее время поддерживает следующиеархитектуры наборов команд:IA-32,IA-64,ARM64иx86-64(AMD64/Intel64). ДоWindows 2000Windows NT (таким образом, и PE) поддерживалMIPS,AlphaиPowerPC.Поскольку PE используется наWindows CE,он продолжает поддерживать несколько разновидностейMIPS,ARM(включаяThumb) иSuperH.
Основные «конкуренты» PE —ELF(используемый вLinuxи большинстве других версийUnix) иMach-O(используемый вMac OS X).
Краткая история
[править|править код]С появлением операционной системыWindows NT 3.1Microsoft перешла на формат PE. Все более поздние версии Windows, включая Windows 95/98/ME, поддерживают этот формат. Формат сохранил ограниченную поддержку существующего (MZ) для преодоления разрыва между системами, основанными на DOS, и системами NT. Например, заголовки PE/COFF всё ещё включают исполняемую программу MS-DOS, которая по умолчанию являетсязаглушкой,выводящей на экран простое сообщение"This program cannot be run in DOS mode"
— «Эта программа не может быть выполнена в режиме DOS» (или подобное). PE продолжает служить изменяющейся платформе Windows. Некоторые расширения включают формат PE.NET (см. ниже), 64-разрядную версию под названием PE32+ (иногда PE+) и спецификацию для Windows CE.
Технические детали
[править|править код]![](https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Portable_Executable_32_bit_Structure_in_SVG.svg/320px-Portable_Executable_32_bit_Structure_in_SVG.svg.png)
Сигнатура
[править|править код]Первые 2 байта PE-файла содержат сигнатуру 0x4D 0x5A — «MZ» (как наследникMZ-формата). Далее — двойное слово по смещению 0x3C содержит адрес PE-заголовка. Последний начинается с сигнатуры 0x50 0x45 — «PE».
Структура
[править|править код]Файл PE состоит из нескольких заголовков и секций, которые указывают динамическому компоновщику, как отображать файл в память. Исполняемый образ состоит из нескольких различных областей (секций), каждая из которых требует различных прав доступа к памяти; таким образом, начало каждой секции должно быть выровнено по границе страницы. Например, обычно секция.text, которая содержит код программы, отображена как исполняемая/доступная только для чтения, а секция.data, содержащая глобальные переменные, отображена как неисполняемая/доступная для чтения и записи. Однако, чтобы не тратить впустую пространство на жёстком диске, различные секции на нём на границу страницы не выровнены. Часть работы динамического компоновщика состоит в том, чтобы отобразить каждую секцию в память отдельно и присвоить корректные права доступа получившимся областям согласно указаниям, содержащимся в заголовках.
Таблица импорта
[править|править код]Одна из известных секций — таблица адресов импорта (IAT — Import Address Table), которая используется в качестве таблицы поиска, когда приложение вызывает функцию из другого модуля. Это может быть сделано и в форме импорта по порядковому номеру функции (ordinal), и импорта по её имени. Поскольку скомпилированной программе неизвестно расположение библиотек, от которых она зависит, то требуется производить косвенный переход всякий раз, когда происходит вызов API-функции. Когда динамический компоновщик загружает модули и объединяет их, он записывает действительные адреса в область IAT так, чтобы они указали на ячейки памяти соответствующих библиотечных функций. Хотя это добавляет дополнительный переход внутри модуля, приводящий к потере производительности, это предоставляет ключевое преимущество: количество страниц памяти, которые должны быть скопированы загрузчиком при записи, минимизировано, что приводит к экономии памяти и дискового времени ввода-вывода. Если компилятору будет известно заранее, что вызов будет межмодульным (через атрибут dllimport), то он сможет произвести более оптимизированный код, который просто приводит ккоду операциикосвенного вызова.
Таблица экспорта
[править|править код]Таблица адресов экспорта (EAT — Export Address Table) нужна для того, чтобы один модуль (обычно этодинамически загружаемая библиотека) мог указать другим модулям, какие функции они могут из него импортировать, и по каким адресам последние расположены.
Таблица перемещений
[править|править код]Файлы PE не содержатпозиционно-независимого кода.Вместо этого они скомпилированы для предпочтительногобазового адреса,и все адреса, генерируемые компилятором/компоновщиком, заранее фиксированы. Если PE-файл не может быть загружен по своему предпочтительному адресу (потому что он уже занят чем-то ещё), операционная система будетперебазироватьего. Это включает в себя перевычисление каждого абсолютного адреса и изменение кода для того, чтобы использовать новые значения. Загрузчик делает это, сравнивая предпочтительный и фактический адреса загрузки, и вычисляя значениеразности.Тогда для получения нового адреса ячейки памяти эта разность складывается с предпочтительным адресом. Базовые адреса перемещений хранятся в списке и при необходимости добавляются к существующей ячейке памяти. Полученный код является теперь отдельным по отношению к процессу и не является больше разделяемым, так что при таком способе теряются многие из преимуществ экономии памяти динамически загружаемых библиотек. Такой способ также значительно замедляет загрузку модуля. По этой причине следует избегать перебазирования везде, где это возможно; например, библиотеки, поставляемые Microsoft, имеют предварительно вычисленные неперекрывающиеся базовые адреса. В случае отсутствия необходимости перебазировании PE-файлы имеют преимущество очень эффективного кода, но при наличии перебазирования издержки в использовании памяти могут быть значительными. Это отличает формат PE отELF,который использует полностью позиционно-независимый код и глобальную таблицу смещений, которая жертвует временем выполнения в пользу расходования памяти.
.NET, метаданные и PE-формат
[править|править код]Платформа.NETкорпорации Microsoft расширила формат PE с помощью функций, которые поддерживаютобщеязыковую среду исполнения(Common Language Runtime — CLR). Среди дополнений — заголовок CLR и секция данных CLR. После загрузки двоичного файла загрузчик ОС приводит к выполнению CLR через ссылку в таблице импорта PE/COFF. Затем CLR загружает заголовок CLR и секции данных.
Секция данных CLR содержит два важных сегмента: сегмент метаданных и сегмент кода промежуточного языка (IL):
- Метаданные содержат информацию, относящуюся к сборке, включая манифест сборки. Манифест подробно описывает сборку, включая уникальный идентификатор (с помощью хеша, номера версии и т. д.), данные об экспортируемых компонентах, расширенную информацию о типе (поддерживаемую общей системой типов (Common Type System — CTS)), внешние ссылки и список файлов в сборке. Среда CLR широко использует метаданные.
- Код промежуточного языка (Intermediate Language — IL) — абстрактный, независимый от языка код, который удовлетворяет требованиямобщего промежуточного языка(Common Intermediate Language — CIL).NET CLR. Термин «промежуточный» относится к природе кода IL, обладающего межъязыковой и кроссплатформенной совместимостью. Этот промежуточный язык, подобныйбайт-кодуJava,позволяет платформам и языкам поддерживать общую среду.NET CLR. IL поддерживаетобъектно-ориентированное программирование(полиморфизм, наследование, абстрактные типы и т. д.), исключения, события и различные структуры данных.
Использование в других операционных системах
[править|править код]Формат PE также используетсяReactOS,поскольку ReactOS предназначена для того, чтобы быть двоично совместимой с Windows на уровне кода. Кроме того, он исторически использовался многими другими операционными системами, включаяSkyOSиBeOSR3. Однако и SkyOS, и BeOS в конечном счёте перешли на формат ELF.
Посколькуплатформа разработки Monoнамеревается быть двоично совместимой сMicrosoft.NET,она использует тот же формат PE, что и в реализации Microsoft.
На платформеx86вUnix-подобных операционных системахнекоторые двоичные файлы Windows (в формате PE) могут быть исполнены с помощьюWine.HX DOS Extenderтакже использует формат PE для собственных 32-разрядных двоичных файлов DOS, кроме того, может в некоторой степени выполнить существующие двоичные файлы Windows в DOS, действуя, таким образом, какWineдля DOS.
Mac OS X 10.5имеет возможность загружать и интерпретировать PE-файлы, однако они не являются двоично совместимыми с Windows.