[インデックス 11692] ファイルの概要
このコミットは、Go言語のARMアーキテクチャ向けリンカである5l
におけるビルド問題を修正するためのものです。具体的には、シンボルの再定義に関するリンカの診断ロジックを調整し、特定の状況下で正当なシンボル重複がエラーとして扱われないように変更しています。これにより、ARM環境でのGoプログラムのビルドが正常に完了するようになります。
コミット
commit 9af4b0165486ec5b650ac28ff5d087908908cbc5
Author: Rob Pike <r@golang.org>
Date: Wed Feb 8 15:12:56 2012 +1100
5l: attempt to fix arm build
TBR=rsc
R=golang-dev
CC=golang-dev
https://golang.org/cl/5647049
---
src/cmd/5l/obj.c | 2 +--
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 0cc84d0eaf..4a3db99b00 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -540,7 +540,7 @@ loop:
s->type = SBSS;
s->value = 0;
}
- if(s->type != SBSS) {
+ if(s->type != SBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9af4b0165486ec5b650ac28ff5d087908908cbc5
元コミット内容
このコミットは、Go言語のARMアーキテクチャ向けリンカである5l
において、ARMビルドを修正するための試みです。具体的には、src/cmd/5l/obj.c
ファイル内のシンボル再定義チェックロジックに、dupok
フラグの確認を追加することで、誤った再定義エラーの発生を防ぎます。
変更の背景
Go言語のコンパイラツールチェーンは、様々なアーキテクチャをサポートしています。このコミットが作成された当時、ARMアーキテクチャ向けのビルドプロセスにおいて、リンカ(5l
)が特定のシンボルの再定義を誤ってエラーとして報告する問題が発生していました。これは、リンカが本来許容されるべきシンボルの重複を不正なものと判断してしまうことに起因していました。この問題により、ARM環境でGoプログラムをビルドする際にエラーが発生し、開発者がGoをARMデバイスにデプロイすることが困難になっていました。このコミットは、このビルドエラーを解消し、ARM環境でのGoの利用を可能にすることを目的としています。
前提知識の解説
リンカ (Linker)
リンカは、コンパイラによって生成された複数のオブジェクトファイル(機械語コードとデータを含むファイル)と、ライブラリファイル(静的ライブラリや共有ライブラリ)を結合し、実行可能なプログラムやライブラリを生成するソフトウェアツールです。リンカの主な役割は以下の通りです。
- シンボル解決 (Symbol Resolution): オブジェクトファイル内で参照されている関数や変数の名前(シンボル)を、他のオブジェクトファイルやライブラリで定義されている実際のメモリ位置に解決します。
- 再配置 (Relocation): オブジェクトファイル内のコードやデータが、最終的な実行可能ファイル内のどこに配置されるかに応じて、アドレス参照を調整します。
- セクション結合 (Section Merging): 異なるオブジェクトファイル内の同じ種類のセクション(例: コードセクション、データセクション)を結合します。
Go言語のツールチェーンとリンカ 5l
Go言語は、独自のコンパイラとリンカを含むツールチェーンを持っています。Goのリンカは、ターゲットアーキテクチャごとに異なる名前を持っています。例えば、5l
はARMアーキテクチャ向けのリンカを指します。他の例としては、6l
がx86-64、8l
がx86-32向けです。これらのリンカは、Goのコンパイラ(例: 5g
、6g
、8g
)によって生成されたオブジェクトファイルを処理します。
シンボル (Symbol)
プログラミングにおいて、シンボルとは、関数名、変数名、ラベルなど、プログラム内の特定のメモリ位置やエンティティを識別するための名前です。リンカはこれらのシンボルを使って、プログラムの異なる部分を結合します。
シンボルタイプ SBSS
SBSS
は、Goリンカが内部的に使用するシンボルタイプの一つです。これは通常、初期化されていないデータセグメント(BSSセグメント)に属するシンボルを指します。BSSセグメントは、プログラムの開始時にゼロで初期化される静的変数やグローバル変数を格納するために使用されます。
シンボル再定義 (Symbol Redefinition)
シンボル再定義とは、同じ名前のシンボルが複数回定義される状況を指します。通常、これはエラーであり、リンカはプログラムのどの定義を使用すべきか判断できないため、ビルドを停止します。しかし、特定の状況(例: 弱いシンボル、コモンブロックシンボルなど)では、シンボルの重複が許容される場合があります。
dupok
フラグ
dupok
は "duplicate OK" の略で、シンボルが重複していてもリンカがエラーを報告すべきではないことを示すフラグであると推測されます。これは、リンカが特定のシンボルに対して再定義チェックをスキップするためのメカニズムとして機能します。
技術的詳細
このコミットの核心は、リンカがシンボルの再定義を検出するロジックの変更にあります。src/cmd/5l/obj.c
ファイルは、GoのARMリンカ5l
のオブジェクトファイル処理を担当する部分です。
元のコードでは、シンボルs
のタイプがSBSS
でない場合、無条件に「redefinition」エラーを診断していました。これは、SBSS
以外のシンボルは一意であるべきであり、重複は不正であるという前提に基づいています。
if(s->type != SBSS) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
}
しかし、ARMビルドの特定のシナリオでは、SBSS
ではないにもかかわらず、正当な理由でシンボルが重複するケースが存在したと考えられます。例えば、異なるオブジェクトファイルで同じ名前の弱いシンボルが定義されている場合や、特定のランタイム構造が複数の場所で参照されるが、リンカがそれらを単一のエンティティとして扱うべき場合などです。
このコミットでは、この条件に&& !s->dupok
という新しいチェックを追加しています。
if(s->type != SBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
}
この変更により、リンカは以下の条件が両方とも真である場合にのみ、シンボルの再定義エラーを報告するようになります。
- シンボル
s
のタイプがSBSS
ではない。 - シンボル
s
のdupok
フラグがfalse
である(つまり、重複が許容されていない)。
つまり、s->dupok
がtrue
であるシンボルについては、たとえSBSS
でなくても、リンカは再定義エラーを報告しなくなります。これにより、ARMビルドで発生していた誤った再定義エラーが解消され、ビルドが成功するようになります。このdupok
フラグは、リンカが特定のシンボルに対して特別な処理(この場合は再定義の許容)を行うべきであることを示すメタデータとして機能します。
コアとなるコードの変更箇所
変更はsrc/cmd/5l/obj.c
ファイルの以下の部分です。
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -540,7 +540,7 @@ loop:
s->type = SBSS;
s->value = 0;
}
- if(s->type != SBSS) {
+ if(s->type != SBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
コアとなるコードの解説
変更された行は、シンボルの再定義をチェックする条件文です。
-
変更前:
if(s->type != SBSS)
この条件は、「もしシンボルのタイプがSBSS
でなければ」というものでした。SBSS
シンボルは通常、初期化されていないデータであり、リンカが重複を許容する場合があります。しかし、SBSS
以外のシンボル(例えば、コードや初期化済みデータ)は通常、一意であるべきです。このため、SBSS
でなければ再定義エラーとしていました。 -
変更後:
if(s->type != SBSS && !s->dupok)
この条件は、「もしシンボルのタイプがSBSS
でなく、かつそのシンボルが重複を許容しない(dupok
がfalse
)ならば」というものに変わりました。!s->dupok
という条件が追加されたことで、s->dupok
がtrue
であるシンボルについては、たとえs->type != SBSS
であっても、再定義エラーは発生しなくなります。これは、特定のシンボルが設計上重複しても問題ないことをリンカに明示的に伝えるためのメカニズムです。この修正により、ARMビルドで発生していた、本来エラーとすべきでないシンボル重複がエラーとして報告される問題が解決されました。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/
- Go言語のツールチェーンに関する情報: https://golang.org/doc/
- Goのリンカに関するより詳細な情報(Goのソースコードや設計ドキュメント内)
参考にした情報源リンク
- Go言語のソースコード (特に
src/cmd/5l/
ディレクトリ) - Go言語のIssueトラッカーやメーリングリスト(このコミットに関連する議論がある可能性)
- 一般的なリンカの動作とシンボル解決に関するコンピュータサイエンスの文献
- ARMアーキテクチャのリンキングに関する情報
- Go CL (Change List) 5647049: https://golang.org/cl/5647049 (コミットメッセージに記載されているリンク)# [インデックス 11692] ファイルの概要
このコミットは、Go言語のARMアーキテクチャ向けリンカである5l
におけるビルド問題を修正するためのものです。具体的には、シンボルの再定義に関するリンカの診断ロジックを調整し、特定の状況下で正当なシンボル重複がエラーとして扱われないように変更しています。これにより、ARM環境でのGoプログラムのビルドが正常に完了するようになります。
コミット
commit 9af4b0165486ec5b650ac28ff5d087908908cbc5
Author: Rob Pike <r@golang.org>
Date: Wed Feb 8 15:12:56 2012 +1100
5l: attempt to fix arm build
TBR=rsc
R=golang-dev
CC=golang-dev
https://golang.org/cl/5647049
---
src/cmd/5l/obj.c | 2 +--
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 0cc84d0eaf..4a3db99b00 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -540,7 +540,7 @@ loop:
s->type = SBSS;
s->value = 0;
}
- if(s->type != SBSS) {
+ if(s->type != SBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9af4b0165486ec5b650ac28ff5d087908908cbc5
元コミット内容
このコミットは、Go言語のARMアーキテクチャ向けリンカである5l
において、ARMビルドを修正するための試みです。具体的には、src/cmd/5l/obj.c
ファイル内のシンボル再定義チェックロジックに、dupok
フラグの確認を追加することで、誤った再定義エラーの発生を防ぎます。
変更の背景
Go言語のコンパイラツールチェーンは、様々なアーキテクチャをサポートしています。このコミットが作成された当時、ARMアーキテクチャ向けのビルドプロセスにおいて、リンカ(5l
)が特定のシンボルの再定義を誤ってエラーとして報告する問題が発生していました。これは、リンカが本来許容されるべきシンボルの重複を不正なものと判断してしまうことに起因していました。この問題により、ARM環境でGoプログラムをビルドする際にエラーが発生し、開発者がGoをARMデバイスにデプロイすることが困難になっていました。このコミットは、このビルドエラーを解消し、ARM環境でのGoの利用を可能にすることを目的としています。
前提知識の解説
リンカ (Linker)
リンカは、コンパイラによって生成された複数のオブジェクトファイル(機械語コードとデータを含むファイル)と、ライブラリファイル(静的ライブラリや共有ライブラリ)を結合し、実行可能なプログラムやライブラリを生成するソフトウェアツールです。リンカの主な役割は以下の通りです。
- シンボル解決 (Symbol Resolution): オブジェクトファイル内で参照されている関数や変数の名前(シンボル)を、他のオブジェクトファイルやライブラリで定義されている実際のメモリ位置に解決します。
- 再配置 (Relocation): オブジェクトファイル内のコードやデータが、最終的な実行可能ファイル内のどこに配置されるかに応じて、アドレス参照を調整します。
- セクション結合 (Section Merging): 異なるオブジェクトファイル内の同じ種類のセクション(例: コードセクション、データセクション)を結合します。
Go言語のツールチェーンとリンカ 5l
Go言語は、独自のコンパイラとリンカを含むツールチェーンを持っています。Goのリンカは、ターゲットアーキテクチャごとに異なる名前を持っています。例えば、5l
はARMアーキテクチャ向けのリンカを指します。他の例としては、6l
がx86-64、8l
がx86-32向けです。これらのリンカは、Goのコンパイラ(例: 5g
、6g
、8g
)によって生成されたオブジェクトファイルを処理します。
シンボル (Symbol)
プログラミングにおいて、シンボルとは、関数名、変数名、ラベルなど、プログラム内の特定のメモリ位置やエンティティを識別するための名前です。リンカはこれらのシンボルを使って、プログラムの異なる部分を結合します。
シンボルタイプ SBSS
SBSS
は、Goリンカが内部的に使用するシンボルタイプの一つです。これは通常、初期化されていないデータセグメント(BSSセグメント)に属するシンボルを指します。BSSセグメントは、プログラムの開始時にゼロで初期化される静的変数やグローバル変数を格納するために使用されます。
シンボル再定義 (Symbol Redefinition)
シンボル再定義とは、同じ名前のシンボルが複数回定義される状況を指します。通常、これはエラーであり、リンカはプログラムのどの定義を使用すべきか判断できないため、ビルドを停止します。しかし、特定の状況(例: 弱いシンボル、コモンブロックシンボルなど)では、シンボルの重複が許容される場合があります。
dupok
フラグ
dupok
は "duplicate OK" の略で、シンボルが重複していてもリンカがエラーを報告すべきではないことを示すフラグであると推測されます。これは、リンカが特定のシンボルに対して再定義チェックをスキップするためのメカニズムとして機能します。
技術的詳細
このコミットの核心は、リンカがシンボルの再定義を検出するロジックの変更にあります。src/cmd/5l/obj.c
ファイルは、GoのARMリンカ5l
のオブジェクトファイル処理を担当する部分です。
元のコードでは、シンボルs
のタイプがSBSS
でない場合、無条件に「redefinition」エラーを診断していました。これは、SBSS
以外のシンボルは一意であるべきであり、重複は不正であるという前提に基づいています。
if(s->type != SBSS) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
}
しかし、ARMビルドの特定のシナリオでは、SBSS
ではないにもかかわらず、正当な理由でシンボルが重複するケースが存在したと考えられます。例えば、異なるオブジェクトファイルで同じ名前の弱いシンボルが定義されている場合や、特定のランタイム構造が複数の場所で参照されるが、リンカがそれらを単一のエンティティとして扱うべき場合などです。
このコミットでは、この条件に&& !s->dupok
という新しいチェックを追加しています。
if(s->type != SBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
}
この変更により、リンカは以下の条件が両方とも真である場合にのみ、シンボルの再定義エラーを報告するようになります。
- シンボル
s
のタイプがSBSS
ではない。 - シンボル
s
のdupok
フラグがfalse
である(つまり、重複が許容されていない)。
つまり、s->dupok
がtrue
であるシンボルについては、たとえSBSS
でなくても、リンカは再定義エラーを報告しなくなります。これにより、ARMビルドで発生していた誤った再定義エラーが解消され、ビルドが成功するようになります。このdupok
フラグは、リンカが特定のシンボルに対して特別な処理(この場合は再定義の許容)を行うべきであることを示すメタデータとして機能します。
コアとなるコードの変更箇所
変更はsrc/cmd/5l/obj.c
ファイルの以下の部分です。
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -540,7 +540,7 @@ loop:
s->type = SBSS;
s->value = 0;
}
- if(s->type != SBSS) {
+ if(s->type != SBSS && !s->dupok) {
diag("redefinition: %s\n%P", s->name, p);
s->type = SBSS;
s->value = 0;
コアとなるコードの解説
変更された行は、シンボルの再定義をチェックする条件文です。
-
変更前:
if(s->type != SBSS)
この条件は、「もしシンボルのタイプがSBSS
でなければ」というものでした。SBSS
シンボルは通常、初期化されていないデータであり、リンカが重複を許容する場合があります。しかし、SBSS
以外のシンボル(例えば、コードや初期化済みデータ)は通常、一意であるべきです。このため、SBSS
でなければ再定義エラーとしていました。 -
変更後:
if(s->type != SBSS && !s->dupok)
この条件は、「もしシンボルのタイプがSBSS
でなく、かつそのシンボルが重複を許容しない(dupok
がfalse
)ならば」というものに変わりました。!s->dupok
という条件が追加されたことで、s->dupok
がtrue
であるシンボルについては、たとえs->type != SBSS
であっても、再定義エラーは発生しなくなります。これは、特定のシンボルが設計上重複しても問題ないことをリンカに明示的に伝えるためのメカニズムです。この修正により、ARMビルドで発生していた、本来エラーとすべきでないシンボル重複がエラーとして報告される問題が解決されました。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/
- Go言語のツールチェーンに関する情報: https://golang.org/doc/
- Goのリンカに関するより詳細な情報(Goのソースコードや設計ドキュメント内)
参考にした情報源リンク
- Go言語のソースコード (特に
src/cmd/5l/
ディレクトリ) - Go言語のIssueトラッカーやメーリングリスト(このコミットに関連する議論がある可能性)
- 一般的なリンカの動作とシンボル解決に関するコンピュータサイエンスの文献
- ARMアーキテクチャのリンキングに関する情報
- Go CL (Change List) 5647049: https://golang.org/cl/5647049 (コミットメッセージに記載されているリンク)