Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 13674] ファイルの概要

このコミットは、Go言語のリンカ (cmd/ld) において、Linux/ARMバイナリのELFヘッダフラグを設定する変更を導入しています。これにより、生成されるバイナリがより仕様に準拠するようになります。

コミット

Go言語のリンカ (cmd/ld) が生成するLinux/ARMバイナリのELFヘッダに、適切なフラグ(0x5000002)を設定する変更です。このフラグは、バイナリがエントリポイントを持ち、ARM EABI (Embedded Application Binary Interface) のバージョン5に準拠していることを示します。この変更は、OABI (Old Application Binary Interface) のみで動作するカーネル上での実行動作には影響を与えません。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/1cf27acfed67a25bb1e53115739a7d88efd9997d

元コミット内容

commit 1cf27acfed67a25bb1e53115739a7d88efd9997d
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Thu Aug 23 14:33:41 2012 +0800

    cmd/ld: set ELF header flags for our Linux/ARM binary
    To make it more compliant.
    This won't affect the behavior of running on OABI-only kernels.
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/6475044

変更の背景

この変更の背景には、Go言語が生成するARMアーキテクチャ向けLinuxバイナリのELF (Executable and Linkable Format) ヘッダが、より標準的な仕様に準拠するように改善するという目的があります。

ELFは、Unix系システムで実行可能ファイル、オブジェクトファイル、共有ライブラリなどを表現するための標準的なファイルフォーマットです。ELFヘッダには、ファイルのタイプ、ターゲットアーキテクチャ、エントリポイントのアドレスなど、実行に必要な基本的な情報が含まれています。

特にARMアーキテクチャにおいては、EABI (Embedded Application Binary Interface) と呼ばれる標準が存在します。これは、異なるコンパイラやツールチェインで生成されたコードが相互運用できるように、レジスタの使用方法、スタックフレームのレイアウト、関数呼び出し規約などを定義したものです。EABIには複数のバージョンがあり、このコミットが対象としているのは「Version5 EABI」です。

Goリンカが生成するバイナリが、このEABIの仕様に沿ったELFヘッダフラグを持たない場合でも、多くのLinuxカーネルは互換性レイヤーや柔軟なローダーによって実行を可能にしていました。しかし、より厳密な環境や将来的な互換性を考慮すると、標準に準拠したフラグを設定することが望ましいと判断されました。

コミットメッセージにある「This won't affect the behavior of running on OABI-only kernels.」という記述は、この変更が古いOABI (Old Application Binary Interface) のみをサポートするカーネル上での動作に悪影響を与えないことを保証しています。OABIはEABI以前のARMバイナリインターフェースであり、EABIが普及するにつれて置き換えられていきました。この変更はEABI準拠を目的としているものの、OABI環境との後方互換性も考慮されていることを示しています。

前提知識の解説

ELF (Executable and Linkable Format)

ELFは、Unix系オペレーティングシステム(Linuxを含む)で広く使用されている、実行可能ファイル、オブジェクトファイル、共有ライブラリ、コアダンプなどを格納するための標準ファイルフォーマットです。ELFファイルは、ヘッダ、プログラムヘッダテーブル、セクションヘッダテーブル、およびデータセクションで構成されます。

  • ELFヘッダ (ELF Header): ファイルの先頭に位置し、ELFファイルの基本的な情報(マジックナンバー、クラス、データエンコーディング、バージョン、OS ABI、オブジェクトファイルタイプ、ターゲットアーキテクチャ、エントリポイントアドレス、プログラムヘッダテーブルとセクションヘッダテーブルのオフセットとサイズなど)を格納します。
  • プログラムヘッダテーブル (Program Header Table): 実行時にメモリにロードされるセグメント(コード、データなど)のレイアウトを記述します。
  • セクションヘッダテーブル (Section Header Table): リンク時に使用されるファイルの論理的な構造(コードセクション、データセクション、シンボルテーブルなど)を記述します。

ARMアーキテクチャ

ARM (Advanced RISC Machine) は、モバイルデバイス、組み込みシステム、IoTデバイス、さらにはサーバーやデスクトップPCまで、幅広い分野で利用されているRISC (Reduced Instruction Set Computer) ベースのプロセッサアーキテクチャです。低消費電力と高性能を両立させる設計が特徴です。

EABI (Embedded Application Binary Interface)

EABIは、ARMアーキテクチャ向けのソフトウェア開発におけるバイナリ互換性を保証するための標準です。異なるコンパイラやツールチェインで生成されたコードが、互いにリンクして正しく動作するために必要な規約(レジスタの使用方法、スタックフレームのレイアウト、関数呼び出し規約、データ型のアライメントなど)を定義します。

  • OABI (Old Application Binary Interface): EABI以前のARMバイナリインターフェース。
  • EABI (Embedded Application Binary Interface): OABIに代わる新しい標準。より効率的なコード生成や、C++例外処理、DWARF2デバッグ情報などのサポートが改善されています。EABIには複数のバージョンが存在し、このコミットでは「Version5 EABI」が言及されています。

cmd/ld (Goリンカ)

cmd/ld は、Go言語のツールチェインの一部であるリンカです。Goのコンパイラ (cmd/compile) が生成したオブジェクトファイルや、他のライブラリを結合して、最終的な実行可能バイナリを生成する役割を担います。リンカは、シンボル解決、アドレスの再配置、実行可能ファイルのフォーマット(ELFなど)への変換などを行います。このコミットは、cmd/ld がELFヘッダを生成する際のロジックを変更しています。

技術的詳細

このコミットの技術的詳細の中心は、ELFヘッダの e_flags フィールドに設定される値 0x5000002 です。

ELFヘッダの e_flags フィールドは、プロセッサ固有のフラグを格納するために使用されます。ARMアーキテクチャの場合、このフィールドはARM EABIの仕様に基づいて特定の意味を持ちます。

0x5000002 という値は、以下のように解釈されます(ARM EABIの仕様に基づく):

  • 0x5000000: これは EF_ARM_EABI_VERSION フィールドの一部であり、EABIのバージョンを示します。0x5 はEABIバージョン5を意味します。
  • 0x0000002: これは EF_ARM_ABI_FLOAT_SOFT または EF_ARM_ABI_FLOAT_HARD に関連するビットですが、この文脈では EF_ARM_HASENTRY (0x02) を示唆している可能性が高いです。EF_ARM_HASENTRY は、実行可能ファイルにエントリポイントがあることを示します。

したがって、hdr.flags = 0x5000002 は、生成されるARMバイナリが「EABIバージョン5に準拠しており、かつエントリポイントを持つ実行可能ファイルである」ことをELFヘッダに明示的に示すものです。

コードの変更箇所を見ると、case '5': という部分があります。これは、Goの内部的なアーキテクチャ識別子で、ARMアーキテクチャを指すものと考えられます。Goのリンカは、ターゲットアーキテクチャに応じて異なるELFヘッダ情報を設定する必要があるため、この case 文でARM固有の処理を行っています。

// fallthrough コメントは、この case '5' の処理が完了した後、default: ブロックの処理も引き続き実行されることを示しています。default: ブロックでは、hdr.phoff (プログラムヘッダテーブルのオフセット) や hdr.shoff (セクションヘッダテーブルのオフセット) など、32ビットアーキテクチャに共通のELFヘッダフィールドが設定されます。これは、ARMが32ビットアーキテクチャであるため、ARM固有のフラグ設定に加えて、共通の32ビットELFヘッダ設定も必要であることを意味します。

この変更により、Goリンカが生成するARMバイナリは、より標準的なELF仕様に準拠し、特にEABIバージョン5の要件を満たすようになります。これにより、異なるツールチェインやシステムとの互換性が向上し、より堅牢なバイナリが生成されることが期待されます。

コアとなるコードの変更箇所

--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -52,6 +52,9 @@ elfinit(void)\n 	\tbreak;\n \n 	// 32-bit architectures\n+\tcase '5':\n+\t\thdr.flags = 0x5000002; // has entry point, Version5 EABI\n+\t\t// fallthrough\n \tdefault:\n \t\thdr.phoff = ELF32HDRSIZE;\t/* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */\n \t\thdr.shoff = ELF32HDRSIZE;\t/* Will move as we add PHeaders */

コアとなるコードの解説

このコードスニペットは、Goリンカの elf.c ファイル内の elfinit 関数の一部です。この関数は、ELFヘッダの初期化を担当しています。

変更の核心は、// 32-bit architectures のコメントの下に追加された以下の3行です。

+	case '5':
+		hdr.flags = 0x5000002; // has entry point, Version5 EABI
+		// fallthrough
  • case '5':: この case 文は、Goリンカがターゲットとするアーキテクチャを識別するための内部的なメカニズムの一部です。Goのソースコードでは、異なるアーキテクチャに対して数値や文字で識別子を割り当てることがあります。この場合、'5' はARMアーキテクチャを指しています。リンカは、ビルドターゲットがARMである場合にこのブロックに入ります。

  • hdr.flags = 0x5000002;: これがこのコミットの主要な変更点です。hdr はELFヘッダ構造体を表しており、flags はその中の e_flags フィールドに対応します。 0x5000002 という16進数の値が e_flags に設定されます。前述の「技術的詳細」で解説した通り、この値はARM EABIバージョン5に準拠し、かつバイナリがエントリポイントを持つことを示します。これにより、生成されるELFバイナリがARM EABIの仕様に沿ったものになります。

  • // fallthrough: このコメントは、C言語の switch 文における fallthrough の意図を示しています。通常、case ブロックの最後には break; が置かれ、その case の処理が完了すると switch 文を抜けます。しかし、fallthrough が意図されている場合、break; は置かれず、次の case または default ブロックのコードが続けて実行されます。 この文脈では、ARMアーキテクチャ (case '5') 固有の e_flags 設定を行った後、default: ブロックで定義されている32ビットアーキテクチャ共通のELFヘッダ初期化処理(例: hdr.phoff = ELF32HDRSIZE;)も実行されるようにしています。これは、ARMが32ビットアーキテクチャであるため、ARM固有の設定と共通の32ビット設定の両方が必要だからです。

この変更により、GoリンカはARM Linuxバイナリを生成する際に、より正確で標準に準拠したELFヘッダフラグを設定するようになり、システムとの互換性と堅牢性が向上します。

関連リンク

参考にした情報源リンク

  • GitHub: golang/go commit 1cf27acfed67a25bb1e53115739a7d88efd9997d
  • golang.org/cl/6475044 (Goのコードレビューシステムにおけるこの変更のCL (Change List) ページ)
  • ELF Header e_flags for ARM (Web検索による情報)
  • ARM EABI Specification (Web検索による情報)
  • Go言語のリンカに関する一般的な知識
  • ELFファイルフォーマットに関する一般的な知識
  • ARMアーキテクチャに関する一般的な知識
  • C言語の switch 文と fallthrough に関する知識

[インデックス 13674] ファイルの概要

このコミットは、Go言語のリンカ (cmd/ld) において、Linux/ARMバイナリのELFヘッダフラグを設定する変更を導入しています。これにより、生成されるバイナリがより仕様に準拠するようになります。

コミット

Go言語のリンカ (cmd/ld) が生成するLinux/ARMバイナリのELFヘッダに、適切なフラグ(0x5000002)を設定する変更です。このフラグは、バイナリがエントリポイントを持ち、ARM EABI (Embedded Application Binary Interface) のバージョン5に準拠していることを示します。この変更は、OABI (Old Application Binary Interface) のみで動作するカーネル上での実行動作には影響を与えません。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/1cf27acfed67a25bb1e53115739a7d88efd9997d

元コミット内容

commit 1cf27acfed67a25bb1e53115739a7d88efd9997d
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Thu Aug 23 14:33:41 2012 +0800

    cmd/ld: set ELF header flags for our Linux/ARM binary
    To make it more compliant.
    This won't affect the behavior of running on OABI-only kernels.
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/6475044

変更の背景

この変更の背景には、Go言語が生成するARMアーキテクチャ向けLinuxバイナリのELF (Executable and Linkable Format) ヘッダが、より標準的な仕様に準拠するように改善するという目的があります。

ELFは、Unix系システムで実行可能ファイル、オブジェクトファイル、共有ライブラリなどを表現するための標準的なファイルフォーマットです。ELFヘッダには、ファイルのタイプ、ターゲットアーキテクチャ、エントリポイントのアドレスなど、実行に必要な基本的な情報が含まれています。

特にARMアーキテクチャにおいては、EABI (Embedded Application Binary Interface) と呼ばれる標準が存在します。これは、異なるコンパイラやツールチェインで生成されたコードが相互運用できるように、レジスタの使用方法、スタックフレームのレイアウト、関数呼び出し規約などを定義したものです。EABIには複数のバージョンがあり、このコミットが対象としているのは「Version5 EABI」です。

Goリンカが生成するバイナリが、このEABIの仕様に沿ったELFヘッダフラグを持たない場合でも、多くのLinuxカーネルは互換性レイヤーや柔軟なローダーによって実行を可能にしていました。しかし、より厳密な環境や将来的な互換性を考慮すると、標準に準拠したフラグを設定することが望ましいと判断されました。

コミットメッセージにある「This won't affect the behavior of running on OABI-only kernels.」という記述は、この変更が古いOABI (Old Application Binary Interface) のみをサポートするカーネル上での動作に悪影響を与えないことを保証しています。OABIはEABI以前のARMバイナリインターフェースであり、EABIが普及するにつれて置き換えられていきました。この変更はEABI準拠を目的としているものの、OABI環境との後方互換性も考慮されていることを示しています。

前提知識の解説

ELF (Executable and Linkable Format)

ELFは、Unix系オペレーティングシステム(Linuxを含む)で広く使用されている、実行可能ファイル、オブジェクトファイル、共有ライブラリ、コアダンプなどを格納するための標準ファイルフォーマットです。ELFファイルは、ヘッダ、プログラムヘッダテーブル、セクションヘッダテーブル、およびデータセクションで構成されます。

  • ELFヘッダ (ELF Header): ファイルの先頭に位置し、ELFファイルの基本的な情報(マジックナンバー、クラス、データエンコーディング、バージョン、OS ABI、オブジェクトファイルタイプ、ターゲットアーキテクチャ、エントリポイントアドレス、プログラムヘッダテーブルとセクションヘッダテーブルのオフセットとサイズなど)を格納します。
  • プログラムヘッダテーブル (Program Header Table): 実行時にメモリにロードされるセグメント(コード、データなど)のレイアウトを記述します。
  • セクションヘッダテーブル (Section Header Table): リンク時に使用されるファイルの論理的な構造(コードセクション、データセクション、シンボルテーブルなど)を記述します。

ARMアーキテクチャ

ARM (Advanced RISC Machine) は、モバイルデバイス、組み込みシステム、IoTデバイス、さらにはサーバーやデスクトップPCまで、幅広い分野で利用されているRISC (Reduced Instruction Set Computer) ベースのプロセッサアーキテクチャです。低消費電力と高性能を両立させる設計が特徴です。

EABI (Embedded Application Binary Interface)

EABIは、ARMアーキテクチャ向けのソフトウェア開発におけるバイナリ互換性を保証するための標準です。異なるコンパイラやツールチェインで生成されたコードが、互いにリンクして正しく動作するために必要な規約(レジスタの使用方法、スタックフレームのレイアウト、関数呼び出し規約、データ型のアライメントなど)を定義します。

  • OABI (Old Application Binary Interface): EABI以前のARMバイナリインターフェース。
  • EABI (Embedded Application Binary Interface): OABIに代わる新しい標準。より効率的なコード生成や、C++例外処理、DWARF2デバッグ情報などのサポートが改善されています。EABIには複数のバージョンが存在し、このコミットでは「Version5 EABI」が言及されています。

cmd/ld (Goリンカ)

cmd/ld は、Go言語のツールチェインの一部であるリンカです。Goのコンパイラ (cmd/compile) が生成したオブジェクトファイルや、他のライブラリを結合して、最終的な実行可能バイナリを生成する役割を担います。リンカは、シンボル解決、アドレスの再配置、実行可能ファイルのフォーマット(ELFなど)への変換などを行います。このコミットは、cmd/ld がELFヘッダを生成する際のロジックを変更しています。

技術的詳細

このコミットの技術的詳細の中心は、ELFヘッダの e_flags フィールドに設定される値 0x5000002 です。

ELFヘッダの e_flags フィールドは、プロセッサ固有のフラグを格納するために使用されます。ARMアーキテクチャの場合、このフィールドはARM EABIの仕様に基づいて特定の意味を持ちます。

0x5000002 という値は、以下のように解釈されます(ARM EABIの仕様に基づく):

  • 0x5000000: これは EF_ARM_EABI_VERSION フィールドの一部であり、EABIのバージョンを示します。0x5 はEABIバージョン5を意味します。
  • 0x0000002: これは EF_ARM_ABI_FLOAT_SOFT または EF_ARM_ABI_FLOAT_HARD に関連するビットですが、この文脈では EF_ARM_HASENTRY (0x02) を示唆している可能性が高いです。EF_ARM_HASENTRY は、実行可能ファイルにエントリポイントがあることを示します。

したがって、hdr.flags = 0x5000002 は、生成されるARMバイナリが「EABIバージョン5に準拠しており、かつエントリポイントを持つ実行可能ファイルである」ことをELFヘッダに明示的に示すものです。

コードの変更箇所を見ると、case '5': という部分があります。これは、Goの内部的なアーキテクチャ識別子で、ARMアーキテクチャを指すものと考えられます。Goのリンカは、ターゲットアーキテクチャに応じて異なるELFヘッダ情報を設定する必要があるため、この case 文でARM固有の処理を行っています。

// fallthrough コメントは、この case '5' の処理が完了した後、default: ブロックの処理も引き続き実行されることを示しています。default: ブロックでは、hdr.phoff (プログラムヘッダテーブルのオフセット) や hdr.shoff (セクションヘッダテーブルのオフセット) など、32ビットアーキテクチャに共通のELFヘッダフィールドが設定されます。これは、ARMが32ビットアーキテクチャであるため、ARM固有のフラグ設定に加えて、共通の32ビットELFヘッダ設定も必要であることを意味します。

この変更により、Goリンカが生成するARMバイナリは、より標準的なELF仕様に準拠し、特にEABIバージョン5の要件を満たすようになります。これにより、異なるツールチェインやシステムとの互換性が向上し、より堅牢なバイナリが生成されることが期待されます。

コアとなるコードの変更箇所

--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -52,6 +52,9 @@ elfinit(void)\n 	\tbreak;\n \n 	// 32-bit architectures\n+\tcase '5':\n+\t\thdr.flags = 0x5000002; // has entry point, Version5 EABI\n+\t\t// fallthrough\n \tdefault:\n \t\thdr.phoff = ELF32HDRSIZE;\t/* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */\n \t\thdr.shoff = ELF32HDRSIZE;\t/* Will move as we add PHeaders */

コアとなるコードの解説

このコードスニペットは、Goリンカの elf.c ファイル内の elfinit 関数の一部です。この関数は、ELFヘッダの初期化を担当しています。

変更の核心は、// 32-bit architectures のコメントの下に追加された以下の3行です。

+	case '5':
+		hdr.flags = 0x5000002; // has entry point, Version5 EABI
+		// fallthrough
  • case '5':: この case 文は、Goリンカがターゲットとするアーキテクチャを識別するための内部的なメカニズムの一部です。Goのソースコードでは、異なるアーキテクチャに対して数値や文字で識別子を割り当てることがあります。この場合、'5' はARMアーキテクチャを指しています。リンカは、ビルドターゲットがARMである場合にこのブロックに入ります。

  • hdr.flags = 0x5000002;: これがこのコミットの主要な変更点です。hdr はELFヘッダ構造体を表しており、flags はその中の e_flags フィールドに対応します。 0x5000002 という16進数の値が e_flags に設定されます。前述の「技術的詳細」で解説した通り、この値はARM EABIバージョン5に準拠し、かつバイナリがエントリポイントを持つことを示します。これにより、生成されるELFバイナリがARM EABIの仕様に沿ったものになります。

  • // fallthrough: このコメントは、C言語の switch 文における fallthrough の意図を示しています。通常、case ブロックの最後には break; が置かれ、その case の処理が完了すると switch 文を抜けます。しかし、fallthrough が意図されている場合、break; は置かれず、次の case または default ブロックのコードが続けて実行されます。 この文脈では、ARMアーキテクチャ (case '5') 固有の e_flags 設定を行った後、default: ブロックで定義されている32ビットアーキテクチャ共通のELFヘッダ初期化処理(例: hdr.phoff = ELF32HDRSIZE;)も実行されるようにしています。これは、ARMが32ビットアーキテクチャであるため、ARM固有の設定と共通の32ビット設定の両方が必要だからです。

この変更により、GoリンカはARM Linuxバイナリを生成する際に、より正確で標準に準拠したELFヘッダフラグを設定するようになり、システムとの互換性と堅牢性が向上します。

関連リンク

参考にした情報源リンク

  • GitHub: golang/go commit 1cf27acfed67a25bb1e53115739a7d88efd9997d
  • golang.org/cl/6475044 (Goのコードレビューシステムにおけるこの変更のCL (Change List) ページ)
  • ELF Header e_flags for ARM (Web検索による情報)
  • ARM EABI Specification (Web検索による情報)
  • Go言語のリンカに関する一般的な知識
  • ELFファイルフォーマットに関する一般的な知識
  • ARMアーキテクチャに関する一般的な知識
  • C言語の switch 文と fallthrough に関する知識