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

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

このコミットは、Go言語のツールチェイン、特にcmd/8lリンカにDragonFly BSDオペレーティングシステム(386アーキテクチャ向け)のサポートを追加するものです。これにより、GoプログラムをDragonFly BSD/386環境向けにビルドできるようになります。

コミット

commit fd0af9b56c56d293f4ca9396184dd452615933ee
Author: Joel Sing <jsing@google.com>
Date:   Sat Aug 31 09:33:38 2013 -0700

    cmd/8l: add support for dragonfly/386
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/13328045

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

https://github.com/golang/go/commit/fd0af9b56c56d293f4ca9396184dd452615933ee

元コミット内容

cmd/8l: add support for dragonfly/386

このコミットは、Go言語のリンカである8lに、DragonFly BSDオペレーティングシステムと386アーキテクチャの組み合わせ(dragonfly/386)に対するサポートを追加します。

変更の背景

Go言語は、その設計当初からクロスコンパイルを強力にサポートしており、異なるオペレーティングシステムやアーキテクチャ向けにバイナリを生成できることが特徴です。このコミットの背景には、Goプログラムがより多くのプラットフォームで動作できるように、DragonFly BSDという特定のUNIX系オペレーティングシステムへの対応を拡充するという目的があります。

Goのツールチェインは、各OS/アーキテクチャの組み合わせ(GOOS/GOARCH)に対応するために、リンカやアセンブラなどのコンポーネントが特定のプラットフォーム固有のバイナリフォーマット(ELF、Mach-Oなど)やシステムコール規約を理解し、適切にバイナリを生成する必要があります。このコミットは、DragonFly BSD/386向けのELFバイナリ生成に必要な変更をリンカに加えるものです。

前提知識の解説

Go言語のクロスコンパイル

Go言語は、GOOS(ターゲットOS)とGOARCH(ターゲットアーキテクチャ)という環境変数を設定することで、現在の開発環境とは異なるOSやアーキテクチャ向けの実行ファイルを簡単にビルドできます。例えば、Linux上でWindows向けの実行ファイルをビルドすることが可能です。この機能は、Goのビルドツールチェイン(コンパイラ、アセンブラ、リンカなど)が、ターゲットプラットフォームの特性を理解していることによって実現されます。

Go言語のリンカ (cmd/8l, cmd/6l, cmd/5lなど)

Go言語の初期のツールチェインでは、各アーキテクチャ(例: 386, amd64, arm)に対応するリンカが個別の名前で提供されていました。

  • 8l: 386 (x86 32-bit) アーキテクチャ用リンカ
  • 6l: amd64 (x86 64-bit) アーキテクチャ用リンカ
  • 5l: arm アーキテクチャ用リンカ これらのリンカは、コンパイルされたオブジェクトファイル(.oファイル)を結合し、実行可能なバイナリを生成する役割を担います。実行ファイルのフォーマット(ELF, Mach-O, PEなど)や、システムコール、スレッドローカルストレージ(TLS)の扱いなど、OS固有のリンキング規則に対応する必要があります。

DragonFly BSD

DragonFly BSDは、FreeBSD 4.8からフォークしたオープンソースのUNIX系オペレーティングシステムです。高性能でスケーラブルなシステムを目指しており、特にSMP(Symmetric Multi-Processing)環境でのパフォーマンス向上に注力しています。他のBSD系OSと同様に、ELF(Executable and Linkable Format)を主要な実行ファイルフォーマットとして使用しています。

ELF (Executable and Linkable Format)

ELFは、UNIX系システムで広く使われている実行ファイル、オブジェクトファイル、共有ライブラリの標準フォーマットです。プログラムのコード、データ、シンボル情報、セクション情報などがELFフォーマットの構造に従って配置されます。リンカは、このELFフォーマットの仕様に従って最終的な実行ファイルを生成します。

TLS (Thread Local Storage)

TLSは、マルチスレッドプログラミングにおいて、各スレッドが自分専用のデータを持つための仕組みです。Goのランタイムは、ガベージコレクションやスケジューラなどの内部処理のためにTLSを頻繁に利用します。OSごとにTLSのアクセス方法やオフセットの計算方法が異なるため、リンカはターゲットOSのTLS規約に合わせてコードを調整する必要があります。

技術的詳細

このコミットは、Goの8lリンカがDragonFly BSD/386向けのバイナリを正しく生成できるように、以下の3つのファイルに修正を加えています。

  1. src/cmd/8l/asm.c:

    • このファイルは、アセンブリコードの生成やプラットフォーム固有の処理を行う部分です。
    • asmb() 関数内で、ELF形式のバイナリを生成する asmbelf(symo) の呼び出し箇所に Hdragonfly ケースが追加されています。これは、DragonFly BSDもELFバイナリを使用するため、既存のFreeBSD, NetBSD, OpenBSDと同様の処理パスを通るようにするためです。
  2. src/cmd/8l/obj.c:

    • このファイルは、リンカが認識するヘッダタイプ(HEADTYPE)や、コマンドラインオプションの処理に関連する定義を含んでいます。
    • Header headers[] 配列に "dragonfly", Hdragonfly が追加され、リンカが -H dragonfly オプションを認識し、内部的に Hdragonfly というヘッダタイプとして扱うことができるようになります。
    • コメントブロックに -H dragonfly -Tx -Rx is DragonFly ELF32 という説明が追加され、このオプションがDragonFly ELF32バイナリを生成することを示しています。
    • main() 関数内で、外部リンカを使用できないケースや、TLSオフセットの調整が必要なケース(0(GS)4(GS)-8(GS)-4(GS) に変換する処理)に Hdragonfly が追加されています。これは、DragonFly BSDにおけるTLSの扱いが他のBSD系OSやLinuxと類似しているため、同様の処理を適用する必要があることを意味します。特に、ELFシステムでは通常、%gs レジスタを基準とした負のオフセットでTLSにアクセスします。
  3. src/cmd/ld/doc.go:

    • このファイルは、Goリンカ(ld)のドキュメントを生成するためのGoソースファイルです。
    • -H dragonfly オプションの説明が更新され、以前は (only in 6l) となっていた箇所が (only in 6l/8l) に変更されています。これは、DragonFly BSDのサポートが386(8l)とamd64(6l)の両方のアーキテクチャで利用可能になったことを反映しています。

これらの変更により、Goのビルドシステムは GOOS=dragonfly GOARCH=386 を指定してビルドする際に、8lリンカがDragonFly BSD向けの適切なELF32バイナリを生成できるようになります。

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

src/cmd/8l/asm.c

diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index f7e33b7c6c..3be37ea22c 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -847,6 +847,7 @@ asmb(void)
 	case Hfreebsd:
 	case Hnetbsd:
 	case Hopenbsd:
+	case Hdragonfly:
 		asmbelf(symo);
 		break;
 	case Hwindows:

src/cmd/8l/obj.c

diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 316d79f451..e049de7b07 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -53,6 +53,7 @@ Header headers[] = {\
 	"msdoscom", Hmsdoscom,\
 	"msdosexe", Hmsdosexe,\
 	"darwin", Hdarwin,\
+\t"dragonfly", Hdragonfly,\
 	"linux", Hlinux,\
 	"freebsd", Hfreebsd,\
 	"netbsd", Hnetbsd,\
@@ -69,6 +70,7 @@ Header headers[] = {\
  *\t-Hmsdoscom -Tx -Rx		is MS-DOS .COM
  *\t-Hmsdosexe -Tx -Rx		is fake MS-DOS .EXE
  *\t-Hdarwin -Tx -Rx		is Apple Mach-O
+ *\t-Hdragonfly -Tx -Rx		is DragonFly ELF32
  *\t-Hlinux -Tx -Rx			is Linux ELF32
  *\t-Hfreebsd -Tx -Rx		is FreeBSD ELF32
  *\t-Hnetbsd -Tx -Rx		is NetBSD ELF32
@@ -153,6 +155,7 @@ main(int argc, char *argv[])
 		sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
 		break;
 	case Hdarwin:
+\tcase Hdragonfly:
 	case Hfreebsd:
 	case Hlinux:
 	case Hnetbsd:
@@ -242,6 +245,7 @@ main(int argc, char *argv[])
 	case Hfreebsd:
 	case Hnetbsd:
 	case Hopenbsd:
+\tcase Hdragonfly:
 		/*
 		 * ELF uses TLS offsets negative from %gs.
 		 * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).

src/cmd/ld/doc.go

diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
index 06b4116247..2adda25f22 100644
--- a/src/cmd/ld/doc.go
+++ b/src/cmd/ld/doc.go
@@ -33,7 +33,7 @@ Options new in this version:\
 		linker. This flag cannot be used when $GOOS is windows.
 	-H darwin     (only in 6l/8l)
 		Write Apple Mach-O binaries (default when $GOOS is darwin)
-\t-H dragonfly  (only in 6l)\
+\t-H dragonfly  (only in 6l/8l)\
 		Write DragonFly ELF binaries (default when $GOOS is dragonfly)
 	-H linux
 		Write Linux ELF binaries (default when $GOOS is linux)

コアとなるコードの解説

src/cmd/8l/asm.c の変更

asmb() 関数は、最終的なバイナリのアセンブリコードを生成する際に、ターゲットOSのタイプに基づいて異なる処理を行います。HdragonflyHfreebsd, Hnetbsd, Hopenbsd と同じ asmbelf(symo) パスに追加されたことは、DragonFly BSDが他のBSD系OSと同様にELFバイナリフォーマットを使用しており、GoリンカがELFバイナリを生成するための共通のロジックを適用できることを示しています。

src/cmd/8l/obj.c の変更

  1. Header headers[] への追加: この配列は、リンカが認識する -H オプションの引数と、それに対応する内部的なヘッダタイプ(HEADTYPE)のマッピングを定義しています。"dragonfly", Hdragonfly の追加により、リンカはコマンドラインで -H dragonfly が指定された場合に、それをDragonFly BSD向けのビルドとして認識できるようになります。

  2. コメントの更新: -H dragonfly オプションがDragonFly ELF32バイナリを生成するという説明が追加され、リンカの機能が明確化されています。

  3. main() 関数内の case Hdragonfly: の追加:

    • 外部リンカとの互換性チェック: case Hdarwin: のブロックに Hdragonfly が追加されています。これは、Darwin(macOS)と同様に、DragonFly BSDでも特定の条件下で外部リンカの使用が制限される可能性があることを示唆しています。Goのリンカは、内部リンカと外部リンカの両方をサポートしていますが、OSによっては外部リンカとの連携に制約がある場合があります。
    • TLSオフセットの調整: case Hfreebsd: などのブロックに Hdragonfly が追加されています。このブロックは、ELFシステムにおけるTLS(Thread Local Storage)のアクセス方法を調整するものです。具体的には、0(GS)4(GS) といったTLS変数への参照を、%gs レジスタを基準とした負のオフセット(-8(GS)-4(GS))に変換しています。これは、ELFシステムにおけるTLSの一般的な実装パターンであり、GoランタイムがTLSを正しく利用するために必要な調整です。DragonFly BSDもこのパターンに従うため、同様の処理が適用されます。

src/cmd/ld/doc.go の変更

-H dragonfly オプションの説明が (only in 6l) から (only in 6l/8l) に変更されたことは、このコミットが386アーキテクチャ(8lリンカ)へのDragonFly BSDサポートを追加したことを直接的に示しています。これにより、Goのドキュメントが実際のリンカの機能と一致するようになります。

これらの変更は、GoのビルドシステムがDragonFly BSD/386という新しいターゲットプラットフォームを認識し、そのプラットフォーム固有のバイナリフォーマットやランタイムの要件(特にTLSの扱い)に合わせて、正しく実行ファイルを生成できるようにするための基盤を構築しています。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特に src/cmd/8l および src/cmd/ld ディレクトリ)
  • ELFフォーマットの仕様に関する一般的な情報
  • TLS (Thread Local Storage) の実装に関する一般的な情報
  • DragonFly BSDのシステムプログラミングに関する情報 (必要に応じて)