ポータブル実行可能ファイル( PE ) は、32 ビットおよび 64 ビットのWindowsオペレーティングシステム、およびUEFI環境におけるネイティブ実行可能コードのファイル形式です。 [ 2 ]ネイティブ実行可能ファイル ( .exe、.com )、ダイナミック リンク ライブラリ ( .dll、.ocx )、システム ドライバ ( .sys、.drv )、その他多くの種類のファイルに使用されます。PE 形式は、オペレーティングシステムプロセスをロードして開始するために必要なデータ(ダイナミック リンク ライブラリへの参照、アプリケーション プログラミング インターフェイス(API) 関数のインポートおよびエクスポート用のテーブル、リソース管理データ、スレッド ローカル ストレージ(TLS) 情報など) の保存をサポートします。
Unified Extensible Firmware Interface (UEFI)仕様によれば、PE フォーマットは EFI 環境における実行可能ファイルの標準としても認められています。[ 3 ] Windows NT システムでは、現在IA-32、x86-64 (AMD64/Intel 64)、IA-64、ARM、ARM64など、さまざまな命令セットをサポートしています。Windows 2000の登場以前は、Windows NT (および拡張として PE フォーマット) はMIPS、Alpha、PowerPCアーキテクチャもサポートしていました。さらに、 Windows CEでの使用により、PE はいくつかの MIPS、 ARM ( Thumbを含む)、SuperHバリアントとの互換性を維持しています。[ 4 ]
機能的には、PEフォーマットは、LinuxやほとんどのUnix系システムで使用されるELFフォーマット、macOSやiOSで見られるMach-Oフォーマットなど、他のプラットフォーム固有の実行可能フォーマットと類似しています。
Microsoft はWindows NT 3.1で PE フォーマットを初めて導入し、古い 16 ビットNew Executable (NE) フォーマットを置き換えました。その後すぐに、Windows 95、98、ME、およびWindows 3.1x用のWin32s拡張機能はすべて PE 構造を採用しました。各 PE ファイルには DOS 実行可能ヘッダーが含まれており、通常は「このプログラムは DOS モードでは実行できません」というメッセージが表示されます。ただし、この DOS セクションは、Windows 98 SE インストーラで示されているように、完全に機能する DOS プログラムに置き換えることができます。開発者は、Microsoft のリンカーのスイッチを使用してこのようなプログラムを追加し、実質的にファットバイナリを作成できます。[ 5 ]/STUB
PEフォーマットは、Windowsプラットフォームの発展とともに進化を遂げてきました。注目すべき拡張機能としては、マネージドコード用の.NET PEフォーマット、64ビットアドレス空間をサポートするPE32+、そしてWindows CE専用のバージョンなどが挙げられます。
PE ファイルが 32 ビット アーキテクチャ用か 64 ビット アーキテクチャ用かを判断するには、IMAGE_FILE_HEADER の Machine フィールドを調べます。[ 6 ]一般的な machine の値は、0x014c32 ビット Intel プロセッサの場合は 、0x8664x64 プロセッサの場合は です。さらに、Magic フィールドは、IMAGE_OPTIONAL_HEADERアドレスが 32 ビットか 64 ビットかを示します。 の値は0x10B32 ビット (PE32) ファイルを示し、 は0x20B64 ビット (PE32+) ファイルを示します。[ 7 ]

PE ファイルは、動的リンカにファイルをメモリにマッピングする方法を指示する複数のヘッダーとセクションで構成されています。実行可能イメージは、それぞれ異なるメモリ保護属性を必要とする複数の異なる領域で構成されています。適切なアライメントを確保するため、各セクションの開始位置はページ境界にアライメントする必要があります。[ 8 ]例えば、プログラム コードを含む.textセクションは、通常、実行/読み取り専用としてマッピングされます。逆に、グローバル変数を保持する.dataセクションは、実行不可/読み書き可能としてマッピングされます。ただし、ディスク上の領域を節約するため、セクションはこのようにアライメントされません。動的リンカは、各セクションを個別にメモリにマッピングし、ヘッダーの情報に基づいて適切なパーミッションを割り当てます。[ 9 ]
インポートアドレス テーブル(IAT) は、アプリケーションが別のモジュールの関数を呼び出すときにルックアップ テーブルとして使用されます。インポートは、序数または名前で指定できます。コンパイルされたプログラムは依存ライブラリのメモリ位置を事前に知ることができないため、API 呼び出しには間接ジャンプが必要です。動的リンカはモジュールを保持し、依存関係を解決する際に、対応するライブラリ関数の実際のアドレスを IAT スロットに格納します。これにより、モジュール間呼び出しと比較して余分なジャンプが発生し、パフォーマンスが低下しますが、コピー オン ライト変更が必要なメモリ ページの数を最小限に抑え、メモリとディスク I/O を節約できます。呼び出しが事前にモジュール間であることがわかっている場合 ( dllimport属性で示されている場合)、コンパイラは単純な間接呼び出しオペコードを使用して最適化されたコードを生成できます。[ 9 ]
最新のオペレーティングシステムは、アドレス空間配置ランダム化(ASLR)というプロセスを使用します。このプロセスにより、PE ファイルのメモリ内レイアウトが予測不可能になり、悪用が困難になります。ASLR の実行中、ローダーは主要コンポーネントが存在する仮想アドレスをランダム化します。これには、実行ファイルのベース、共有ライブラリ、ヒープ、スタックが含まれます。主流のコンパイラは想定されるベースに対する絶対参照を出力するため、ほとんどの PE ファイルは位置独立ではありません。ランダム化されたリベースに対応するため、リンカーは.relocテーブルを格納し、ロード時にローダーがこれらの参照を調整できるようにします。
.NET 実行可能ファイルでは、PE コード セクションに、Visual Basic実行可能ファイルと同様に、CLR仮想マシンの起動エントリを呼び出すスタブが含まれています。仮想マシンは、存在する .NET メタデータを使用します。そのルート(「CLR ヘッダー」とも呼ばれる)は、PE ヘッダーのデータ ディレクトリにある (このエントリは以前は COM+ アプリケーションのCOM+メタデータに使用されていたため、という名前が付けられています) エントリによって指されます。はPE のオプション ヘッダーに非常によく似ており、基本的に CLR ローダーの役割を果たします。[ 4 ]_CorExeMain_CorDllMainmscoree.dllIMAGE_COR20_HEADERIMAGE_DIRECTORY_ENTRY_COMHEADERIMAGE_COR20_HEADER
CLR 関連のデータ(ルート構造自体を含む)は、通常、共通コードセクションに含まれています.text。これは、メタデータ、埋め込みリソース、厳密名、およびネイティブコードとの相互運用性のためのいくつかのディレクトリで構成されています。メタデータディレクトリは、アセンブリ内のすべての個別の .NET エンティティ(型、メソッド、フィールド、定数、イベント、およびそれらの間や他のアセンブリへの参照を含む)を一覧表示するテーブルのセットです。
PEフォーマットは、Windowsとのバイナリ互換性を目的に開発されたオープンソースのオペレーティングシステムであるReactOSでも使用されています。過去には、 SkyOSやBeOS R3などの他のオペレーティングシステムでも使用されていましたが、SkyOSとBeOSは最終的にELFに移行しました。
Microsoft .NET Frameworkとのバイナリ互換性を目指すMono開発プラットフォームは、Microsoftの実装と同じPEフォーマットを使用しています。Microsoft独自のクロスプラットフォーム.NET Coreも同様です。
x86 (-64) Unix系オペレーティングシステムでは、Windowsバイナリ(PE形式)をWineを使用して実行できます。HX DOS ExtenderもネイティブDOS 32ビットバイナリにPE形式を使用し、DOS上で一部のWindowsバイナリを実行できるため、DOS版Wineのような役割を果たします。
Mac OS X 10.5は PE ファイルの読み込みと解析を行う機能を備えていますが、Windows とのバイナリ互換性は維持していません。[ 10 ]
UEFIとUEFIファームウェアは、PEファイル、およびアプリケーション用のプラットフォーム関連のABIと呼び出し規約(一般的なPCデバイスの場合はx64 ABI)を使用します。
...
Steven Edwards は、Leopard には、Windows の 32 ビット版と 64 ビット版で使用されるファイルの一種である Portable Executables 用の文書化されていないローダーが含まれていることを発見したと述べている。さらに調査を進めたところ、Leopard 独自のローダーは、Windows バイナリをロードしようとする際に Windows DLL ファイルを探そうとすることが明らかになった。