[インデックス 18808] ファイルの概要
このコミットは、Goコンパイラ(cmd/gc
)におけるamd64p32
アーキテクチャ向けのオブジェクトファイルのGOARCH
設定の修正に関するものです。具体的には、オブジェクトファイルヘッダに書き込まれるアーキテクチャ情報が誤っていた点を修正しています。
コミット
commit e09ac3cf2a93e7db6950a9fc2926d2846f7fb1c9
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date: Fri Mar 7 23:18:07 2014 +0100
cmd/gc: correct GOARCH in object files for amd64p32.
LGTM=dave
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/72260045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e09ac3cf2a93e7db6950a9fc2926d2846f7fb1c9
元コミット内容
cmd/gc: correct GOARCH in object files for amd64p32.
このコミットは、cmd/gc
(Goコンパイラ)がamd64p32
アーキテクチャ用のオブジェクトファイルを生成する際に、オブジェクトファイル内に記録されるGOARCH
(Goアーキテクチャ)の値が正しくない問題を修正するものです。
変更の背景
Goコンパイラは、コンパイルされたコードをオブジェクトファイルとして出力します。これらのオブジェクトファイルには、そのファイルがどのオペレーティングシステム(GOOS
)とアーキテクチャ(GOARCH
)向けにビルドされたかを示すメタデータが含まれています。このメタデータは、リンカが複数のオブジェクトファイルを結合して実行可能ファイルを生成する際に、互換性を確認するために非常に重要です。
amd64p32
は、64ビットのAMD64(x86-64)アーキテクチャ上で動作するものの、ポインタサイズが32ビットに制限された特殊な環境を指します。これは、メモリ使用量を削減したり、特定のレガシーシステムとの互換性を保つために使用されることがあります。
このコミット以前は、cmd/gc
がamd64p32
向けのオブジェクトファイルを生成する際に、オブジェクトファイルヘッダに誤ったGOARCH
情報(おそらく一般的なamd64
など)を書き込んでいたと考えられます。これにより、リンカがオブジェクトファイルを正しく認識できず、ビルドエラーや予期せぬランタイムエラーが発生する可能性がありました。この修正は、amd64p32
環境でのGoプログラムのビルドと実行の信頼性を確保するために必要でした。
前提知識の解説
- Goコンパイラ (
cmd/gc
): Go言語の公式コンパイラです。Goのソースコードを機械語に変換し、オブジェクトファイルを生成します。 - オブジェクトファイル: コンパイラによって生成される中間ファイルで、機械語コード、データ、シンボル情報などが含まれます。これらはまだ実行可能ファイルではありません。
- リンカ: 複数のオブジェクトファイルやライブラリを結合し、最終的な実行可能ファイルを生成するツールです。リンカはオブジェクトファイルのメタデータ(
GOOS
,GOARCH
など)を読み取り、互換性を確認します。 GOOS
とGOARCH
: Goのビルド環境変数を指します。GOOS
: ターゲットとするオペレーティングシステム(例:linux
,windows
,darwin
)。GOARCH
: ターゲットとするCPUアーキテクチャ(例:amd64
,arm
,386
)。- これらの変数は、クロスコンパイルを行う際に特に重要です。
amd64p32
:amd64
アーキテクチャのバリアントの一つで、ポインタサイズが32ビットに制限されています。通常のamd64
はポインタサイズが64ビットです。このようなポインタサイズが異なる環境では、データ構造のレイアウトやアライメントが異なるため、正確なアーキテクチャ情報の伝達が不可欠です。- オブジェクトファイルヘッダ: オブジェクトファイルの先頭に位置するメタデータ領域で、ファイルの種類、アーキテクチャ、OS、シンボルテーブルの位置など、ファイルの内容を解釈するために必要な情報が格納されています。
技術的詳細
Goコンパイラ(cmd/gc
)は、オブジェクトファイルを生成する際に、そのファイルがどの環境向けにビルドされたかを示す文字列をオブジェクトファイルヘッダに書き込みます。この文字列は、go object <GOOS> <GOARCH> <GOVERSION> <EXPSTRING>
のような形式で構成されます。
このコミットの修正箇所は、src/cmd/gc/obj.c
ファイル内のdumpobj
関数にあります。この関数は、オブジェクトファイルのヘッダ情報を書き出す役割を担っています。
修正前は、Bprint(bout, "go object %s %s %s %s\\n", getgoos(), thestring, getgoversion(), expstring());
という行がありました。ここで、thestring
という変数がGOARCH
の情報を保持していると推測されますが、amd64p32
の場合にこのthestring
が正しくamd64p32
を表現していなかったか、あるいは別の汎用的な値(例: amd64
)を返していた可能性があります。
修正後は、Bprint(bout, "go object %s %s %s %s\\n", getgoos(), getgoarch(), getgoversion(), expstring());
に変更されています。ここでgetgoarch()
という関数が明示的に呼び出されています。getgoarch()
は、現在のビルドターゲットの正確なGOARCH
文字列を返すGoコンパイラ内部の関数です。これにより、amd64p32
のような特定のアーキテクチャバリアントに対しても、正しいGOARCH
情報がオブジェクトファイルに書き込まれるようになります。
この変更により、リンカはamd64p32
向けのオブジェクトファイルを正しく識別し、他のオブジェクトファイルやライブラリとの互換性を適切にチェックできるようになります。これは、クロスコンパイル環境や、特定のポインタサイズを要求する特殊な環境でGoをビルドする際の堅牢性を高める上で非常に重要です。
コアとなるコードの変更箇所
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -64,7 +64,7 @@ dumpobj(void)
memset(arhdr, 0, ArhdrSize);
Bwrite(bout, arhdr, ArhdrSize);
startobj = Boffset(bout);
- Bprint(bout, "go object %s %s %s %s\\n", getgoos(), thestring, getgoversion(), expstring());
+ Bprint(bout, "go object %s %s %s %s\\n", getgoos(), getgoarch(), getgoversion(), expstring());
}
Bprint(bout, "\n!\n");
コアとなるコードの解説
変更はsrc/cmd/gc/obj.c
ファイルのdumpobj
関数内の一行です。
-
変更前:
Bprint(bout, "go object %s %s %s %s\\n", getgoos(), thestring, getgoversion(), expstring());
この行では、オブジェクトファイルのヘッダに書き込む文字列をフォーマットしています。
getgoos()
はOS、getgoversion()
はGoのバージョン、expstring()
は追加の実験的な文字列を返します。問題は2番目の%s
に渡されているthestring
変数でした。amd64p32
のような特定のアーキテクチャの場合に、このthestring
が期待されるGOARCH
の値を返していなかったため、オブジェクトファイルに誤ったアーキテクチャ情報が記録されていました。 -
変更後:
Bprint(bout, "go object %s %s %s %s\\n", getgoos(), getgoarch(), getgoversion(), expstring());
thestring
の代わりにgetgoarch()
関数が直接呼び出されています。getgoarch()
は、Goコンパイラが認識している現在のターゲットアーキテクチャの正確な文字列(例:amd64p32
)を返すように設計されています。これにより、オブジェクトファイルヘッダに常に正しいGOARCH
情報が書き込まれることが保証され、amd64p32
環境でのビルドの信頼性が向上しました。
この修正は、Goコンパイラが生成するオブジェクトファイルのメタデータの正確性を確保し、特に特殊なアーキテクチャバリアントにおけるビルドプロセスの堅牢性を高める上で重要な役割を果たします。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Goのクロスコンパイルに関するドキュメント: https://go.dev/doc/install/source#environment (Goの環境変数
GOOS
とGOARCH
について)
参考にした情報源リンク
- Goのコミット履歴: https://github.com/golang/go/commits/master
- Goのコードレビューシステム (Gerrit): https://go.dev/cl/72260045 (元のコードレビューページ)
amd64p32
に関する情報 (一般的なLinuxディストリビューションでの使用例など):- Debian Wiki: https://wiki.debian.org/amd64p32
- Gentoo Wiki: https://wiki.gentoo.org/wiki/Project:AMD64/32-bit_ABI
- Goコンパイラの内部構造に関する一般的な情報 (Goのソースコードや関連する設計ドキュメント)
src/cmd/gc/obj.c
のソースコード (Goリポジトリ内)- Goのツールチェインに関するブログ記事やドキュメント (例: "Go's Toolchain" by Russ Cox)