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

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

このコミットは、Go言語のツールチェインの一部である src/cmd/5l/obj.c ファイルに対する変更です。cmd/5l は、Go言語のARMアーキテクチャ向けリンカ(5l はARMアーキテクチャを指す古い慣習的な名称)のソースコードの一部であり、obj.c はそのリンカの主要なオブジェクトファイル処理ロジックを含んでいます。具体的には、リンカの main 関数内で linkmode のチェックを行っている箇所が修正されています。

コミット

cmd/5l: fix arm build

Fixes build. One part of ../misc/cgo/test appears to be unhappy but this does not cause the build to fail.

R=rsc, r
CC=golang-dev
https://golang.org/cl/7769047

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

https://github.com/golang/go/commit/85773e6bc2d800de8598fdda7602d2b6e61f1039

元コミット内容

cmd/5l: fix arm build

Fixes build. One part of ../misc/cgo/test appears to be unhappy but this does not cause the build to fail.

R=rsc, r
CC=golang-dev
https://golang.org/cl/7769047

変更の背景

このコミットの主な背景は、Go言語のARMアーキテクチャ向けビルドにおける問題の修正です。コミットメッセージには「Fixes build」と明記されており、ARM環境でのGoプログラムのコンパイルおよびリンクプロセスが正常に完了しない、あるいは予期せぬエラーが発生する状況があったことが示唆されます。

特に、linkmode の比較において、正しい列挙型定数 LinkInternal ではなく、誤って Linkinternal (小文字の 'i') が使用されていたことが原因で、リンカが正しく動作しない、または意図しないパスを通ってしまう可能性がありました。このようなタイプミスは、コンパイラによっては警告やエラーとして検出されない場合があり、実行時にのみ問題が顕在化することがあります。

また、コミットメッセージには「One part of ../misc/cgo/test appears to be unhappy but this does not cause the build to fail.」という記述があります。これは、cgo (GoとC言語の相互運用機能) のテストスイートの一部がこの変更によって影響を受ける可能性を示唆していますが、それがビルド全体の失敗には繋がらないという判断がなされています。これは、リンカの修正が cgo の特定のテストケースに間接的な影響を与えたものの、その影響が致命的ではないと判断されたことを意味します。

前提知識の解説

このコミットを理解するためには、以下のGo言語のツールチェインと関連技術に関する知識が必要です。

  • Go言語のツールチェイン: Go言語は、ソースコードから実行可能ファイルを生成するための一連のツール(コンパイラ、アセンブラ、リンカなど)を提供します。これらは通常、go build コマンドを通じて利用されます。
  • cmd/5l: Go言語のリンカの一つです。Goのツールチェインでは、各アーキテクチャに対応するリンカが用意されており、5l はARMアーキテクチャ(GOARCH=arm)向けのリンカを指します。Goの初期のツールチェインでは、各アーキテクチャに数字と文字の組み合わせで名前が付けられていました(例: 8l はamd64、6l は386)。
  • リンカ (Linker): コンパイラやアセンブラによって生成されたオブジェクトファイル(機械語コードやデータを含む)を結合し、実行可能なプログラムやライブラリを生成するツールです。外部ライブラリの参照解決や、メモリ上の配置なども行います。
  • linkmode: Go言語のリンカにおける内部的な設定変数の一つで、リンクのモードを制御します。Goのリンカは、GoのランタイムとCのライブラリをどのようにリンクするかなど、いくつかの異なるリンクモードをサポートしています。
  • LinkInternal: linkmode 変数が取りうる値の一つで、Goのリンカが内部的なリンクモードを使用することを示します。これは、Goのランタイムと標準ライブラリがGoのリンカによって完全にリンクされることを意味し、外部のCリンカ(例: gcc)に依存しない、自己完結型のバイナリを生成する際に用いられます。
  • ARMアーキテクチャ: Advanced RISC Machineの略で、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。Go言語はクロスコンパイルを強力にサポートしており、異なるアーキテクチャ向けのバイナリを生成できます。
  • cgo: Go言語とC言語のコードを相互に呼び出すためのGoの機能です。cgo を使用すると、既存のCライブラリをGoプログラムから利用したり、GoのコードをCから呼び出したりすることができます。cgo を使用するプログラムは、通常のGoプログラムとは異なるリンクプロセスを必要とすることがあります。

技術的詳細

このコミットの技術的な詳細は、src/cmd/5l/obj.c ファイル内の main 関数における linkmode 変数の比較ロジックの修正に集約されます。

元のコードでは、linkmode != Linkinternal という条件式が使用されていました。ここで Linkinternal は、Goのリンカが内部的に使用するリンクモードを示す列挙型定数 LinkInternal のタイプミスです。Go言語では、識別子は大文字と小文字を区別するため、LinkinternalLinkInternal は異なるものとして扱われます。

このタイプミスにより、リンカは常に linkmodeLinkinternal とは異なるものと判断し、diag("only -linkmode=internal is supported"); というエラーメッセージを出力して errorexit() を呼び出し、プログラムを終了させていた可能性があります。あるいは、Linkinternal という未定義のシンボルが使用された場合、コンパイルエラーになるか、あるいは特定の環境下で未定義の動作を引き起こす可能性がありました。

修正後のコードでは、linkmode != LinkInternal となり、正しい列挙型定数 LinkInternal と比較されるようになりました。これにより、リンカは意図した通りに linkmode の値をチェックし、LinkInternal モードでのみ動作を継続するようになります。

この修正は、特にARMアーキテクチャ向けのビルドにおいて重要です。Goのクロスコンパイル環境では、特定のアーキテクチャ向けのリンカが正しく動作することが不可欠です。このタイプミスが原因でARMビルドが失敗していた場合、この修正によってARM環境でのGoプログラムのビルドが可能になり、開発者はARMデバイス向けにGoアプリケーションをデプロイできるようになります。

コミットメッセージにある ../misc/cgo/test の言及は、このリンカの変更が cgo のテストに何らかの影響を与えたことを示唆しています。リンカの動作変更は、特にC言語との連携を伴う cgo のような複雑なシステムにおいて、予期せぬ副作用を引き起こす可能性があります。しかし、コミットメッセージは、この影響がビルドの失敗には繋がらないと述べており、修正の正当性を強調しています。

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

--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -136,7 +136,7 @@ main(int argc, char *argv[])
 	if(argc != 1)
 		usage();

-	if(linkmode != Linkinternal) {
+	if(linkmode != LinkInternal) {
 		diag("only -linkmode=internal is supported");
 		errorexit();
 	}

コアとなるコードの解説

変更箇所は src/cmd/5l/obj.c ファイルの main 関数内、具体的には136行目付近の if 文の条件式です。

  • 変更前 (- で示される行):

    if(linkmode != Linkinternal) {
    

    ここでは、リンカの現在のリンクモードを示す変数 linkmode が、Linkinternal という値と等しくないかどうかをチェックしています。しかし、Linkinternal はGoのリンカが内部的に定義している正しい列挙型定数 LinkInternal のタイプミスです。C言語(Goのツールチェインの多くはCで書かれています)では、識別子は大文字と小文字を区別するため、このタイプミスはコンパイルエラーを引き起こすか、あるいは未定義のシンボルとして扱われ、リンカの動作に問題を引き起こしていました。

  • 変更後 (+ で示される行):

    if(linkmode != LinkInternal) {
    

    修正後は、LinkInternal という正しい列挙型定数が使用されています。これにより、linkmode 変数がGoのリンカがサポートする「内部リンクモード」である LinkInternal と一致しない場合にのみ、エラーメッセージが表示され、プログラムが終了するようになります。これは、リンカが LinkInternal モードでのみ動作することを強制するための意図されたロジックであり、タイプミスが修正されたことで、このロジックが正しく機能するようになりました。

この一文字の変更は、GoのARMビルドが正しく行われるために不可欠な修正であり、Goツールチェインの堅牢性を高める上で重要な役割を果たしています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント (Go toolchain, cross-compilation, cgoに関する情報)
  • Go言語のソースコード (特に cmd/5l やリンカ関連のコード)
  • Go言語のIssueトラッカーやメーリングリスト (過去のビルド問題やリンカに関する議論)
  • Go言語のリンカの内部動作に関する技術記事や解説
  • C言語における識別子の大文字・小文字の区別に関する一般的な情報