実行可能ファイルにバイナリ形式の仕様が必要なのはなぜですか?

実行可能ファイルにバイナリ形式の仕様が必要なのはなぜですか?

Linux や Windows などのオペレーティング システムは C/C++ で記述され、特定のアーキテクチャ (AMD64 など) にコンパイルされて、そのアーキテクチャに適したマシン コードが生成されることを理解しています。

私の質問 -

  1. Linux では ELF が使用され、Windows では Portable Executable Format が使用されるのに、バイナリ コードに別の仕様が必要なのはなぜですか?
  2. このバイナリ形式の仕様がなくても、オペレーティング システムとそのオペレーティング システム上で実行されるプログラムを作成できますか?
  3. バイナリ形式はアーキテクチャ依存ですか、OS 依存ですか、それとも両方ですか?
  4. バイナリ形式は実行可能ファイルにのみ適用できますか、それともオペレーティング システム コードにも適用できますか?

答え1

ご想像のとおり、実行可能形式にはマシン コード以外にもさまざまなものが含まれます。たとえば、次のようなものがあります。

  • OSのメタデータを指定します。例えば、実行ファイルがどのアーキテクチャ向けであるかなどです。このメタデータには、ヘッダファイルの。

  • プログラムを指定するレイアウト最近のOSでは、ほとんどの実行ファイルは1つのチャンクとしてメモリにロードされるのではなく、通常は複数の別々の地域/セクション/セグメントこれらのセグメントの一部には実行可能コードが含まれます。また、テキスト文字列などの不変データが含まれるセグメントもあります。さらに、プログラム ヒープ用の書き込み可能なメモリとして指定されるセグメントもあります。

    プログラムによって、これらのセクションのサイズに対する要件 (リクエスト) は異なります。これはすべてヘッダーで指定されます。

  • 一部のフォーマットでは、デジタル署名これにより、バイナリの出所を検証できます。


  1. Linux では ELF が使用され、Windows では Portable Executable Format が使用されるのに、バイナリ コードに別の仕様が必要なのはなぜですか?

理由は主に歴史的なものであり、OS は、切り替えるやむを得ない理由がない限り、既存の「ネイティブ」(または「デフォルト」) 形式に固執する傾向があります (たとえば、DOS MZ 形式から NT 3.1 の PE へ、Linux 1.2 の a.out から ELF へ、長年にわたるさまざまな Unix の COFF から ELF への変更など)。

基礎となるマシン コードは CPU アーキテクチャに依存しますが、それ以外は (システム コールとリンクされたライブラリは別として) OS 間でほぼ移植可能であることに注意してください。実際、最新の Windows と Linux は両方の実行可能形式を実行できます。ELF 実行可能ファイルは WSL 経由で Wi​​ndows で実行され、PE 実行可能ファイルは WINE 経由で Linux で実行されます。

  1. このバイナリ形式の仕様がなくても、オペレーティング システムとそのオペレーティング システム上で実行されるプログラムを作成できますか?

これらのフォーマットの本来の目的に戻りましょう。OSにプログラムの部分をロードする場所を指示するメタデータがなければ、ほとんどの最新の実行ファイルは実行できません。コムほとんど純粋なコードが含まれていますが、特に柔軟性がなく、人気がなくなってきています。

実際には、オペレーティングシステムが存在する必要すらありません。ハードウェアレベルでは、(レガシー)BIOSが存在すると仮定すると、BIOSはディスク上の特定の場所(MBR)で実行を開始するだけです。これは任意のマシン コードであり、その後引き継いで OS を起動したり、その他の任意の処理を実行したりできます (MBR 自体はバイナリ形式と見なすことができますが、実行可能コードとは直接関係ありません)。ただし、最新の UEFI では、より複雑な実行可能形式 (PE) が指定されています。

  1. バイナリ形式はアーキテクチャに依存しますか、OS に依存しますか、それとも両方に依存しますか?

実際には、フォーマットによって異なります。一部のフォーマットは特定のアーキテクチャを想定しています。他のフォーマットでは、ヘッダー内の指定された「マジックナンバー」のリストからアーキテクチャを選択できます。さらに、完全にアーキテクチャに依存しないフォーマットもあります (例: Java および .NET/CIL バイトコード)。

同様に、このフォーマットは一般的に OS に制限を課しませんが、OS が (ネイティブに) 認識して実行できるフォーマットには制限があります。もちろん、コア OS の上にある互換性レイヤーは、コア OS が認識できない他のフォーマット (JVM、.NET/CLR、WSL&WINE など) を実行できます。

  1. バイナリ形式は実行可能ファイルにのみ適用できますか、それともオペレーティング システム コードにも適用できますか?

最近のオペレーティング システムの大部分は、単に「通常の」実行可能ファイルの集まりです。ただし、オペレーティング システムの一部は「特別」であり、必ずしも他の部分と同じ形式を使用するわけではありません。通常、これはブートローダとカーネルにのみ適用されます。

具体的な、非常に一般的な例を挙げると、レガシーBIOSブートローダーはないLinuxとWindowsで使用されるELFまたはPE形式のいずれかになります。Linuxカーネルは一般的にELF派生形式GRUBブートローダーはロードできるただし、ブートローダーとの互換性を保つために異なる形式になることもあります。Linuxカーネルは、EFI スタブモードには、直接 UEFI ブートと互換性を持つ最小限の PE/COFF ヘッダーが含まれています。

答え2

このフォーマットの主な用途は、プログラムをメモリにロードすることであり、これはローダ

  1. Linux では ELF が使用され、Windows では Portable Execution Format が使用されるのに、バイナリ コードに別の仕様が必要なのはなぜですか?

丁寧な回答: OS が異なり、要件も異なるためです。 Unix ユーザーの回答: Microsoft は (四角い) 車輪を再発明するのが好きなためです。

  1. このバイナリ形式の仕様なしに、オペレーティング システムとそのオペレーティング システム上で実行されるプログラムを作成することはできますか?

はい、しかしそれは非常に些細なものだけです。つまり、「再配置」する必要がなく、外部コードにリンクする必要もない些細なプログラムを実行する、かなり基本的な OS です。

  1. バイナリ形式はアーキテクチャに依存しますか、OS に依存しますか、それとも両方に依存しますか?

なし。ELF 形式は多くのオペレーティング システムおよびアーキテクチャで使用されます。

  1. バイナリ形式は実行可能ファイルにのみ適用できますか、それともオペレーティング システム コードにも適用できますか?

Linux では、起動可能なカーネルは ELF ではない場合がありますが、カーネル モジュールは ELF 形式を使用します。

関連情報