[インデックス 13518] ファイルの概要
このコミットは、Go言語のランタイムにおけるcgo
(C言語との連携機能)がNetBSD上で正しくビルドされるようにするための修正です。具体的には、NetBSD環境で必要となるenviron
および__progname
というシンボルをGoランタイムが明示的に提供するように、src/pkg/runtime/cgo/netbsd.c
という新しいファイルを追加しています。これは、FreeBSDの既存の実装をNetBSD向けにコピーし、適応させたものです。
コミット
- コミットハッシュ:
b4402a49b6c9a87f27c2140beacf46ef95738455
- Author: Benny Siegert bsiegert@gmail.com
- Date: Sun Jul 29 18:51:06 2012 -0400
- Subject: runtime/cgo: fix netbsd build
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/b4402a49b6c9a87f27c2140beacf46ef95738455
元コミット内容
commit b4402a49b6c9a87f27c2140beacf46ef95738455
Author: Benny Siegert <bsiegert@gmail.com>
Date: Sun Jul 29 18:51:06 2012 -0400
runtime/cgo: fix netbsd build
Copy over freebsd.c to netbsd.c.
Fixes #3823.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6398045
--
src/pkg/runtime/cgo/netbsd.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/pkg/runtime/cgo/netbsd.c b/src/pkg/runtime/cgo/netbsd.c
new file mode 100644
index 0000000000..b6403f686c
--- /dev/null
+++ b/src/pkg/runtime/cgo/netbsd.c
@@ -0,0 +1,13 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Supply environ and __progname, because we don't
+// link against the standard NetBSD crt0.o and the
+// libc dynamic library needs them.
+
+char *environ[1];
+char *__progname;
+
+#pragma dynexport environ environ
+#pragma dynexport __progname __progname
変更の背景
このコミットは、Go言語のプログラムがNetBSDオペレーティングシステム上でC言語のコード(cgo
経由)と連携する際に発生していたビルドの問題を解決するために導入されました。
一般的なC言語のプログラムは、crt0.o
(C runtime start-up object file)と呼ばれるオブジェクトファイルにリンクされます。このcrt0.o
は、プログラムのmain
関数が呼び出される前に、環境変数(environ
)やプログラム名(__progname
)などのグローバル変数を初期化する役割を担っています。
Go言語のランタイムは、その独自の起動プロセスとメモリ管理メカニズムを持っているため、標準的なC言語のcrt0.o
にリンクしない場合があります。特に、Goのランタイムが直接OSのシステムコールを呼び出してプログラムを起動するような場合、crt0.o
が提供するはずのenviron
や__progname
といったシンボルが利用できなくなり、結果としてlibc
(C標準ライブラリ)がこれらのシンボルを必要とする際に問題が発生します。
NetBSD環境では、libc
が動的ライブラリとしてリンクされる際に、これらのシンボルを期待していました。Goのランタイムがcrt0.o
を介さずに起動すると、これらのシンボルが未定義となり、ビルドエラーや実行時エラーを引き起こす可能性がありました。このコミットは、この問題を解決するために、Goランタイム自身がこれらのシンボルを明示的に定義し、エクスポートすることで、libc
の要件を満たすようにしています。
コミットメッセージにある「Fixes #3823」は、この問題がGoのIssueトラッカーで報告されていたことを示しています。
前提知識の解説
cgo
cgo
は、Go言語のプログラムからC言語の関数を呼び出したり、C言語のデータ型を扱ったりするためのGoの機能です。これにより、既存のCライブラリをGoプログラムから利用したり、パフォーマンスが重要な部分をCで記述したりすることが可能になります。cgo
を使用すると、GoコンパイラはCコードをコンパイルし、Goコードとリンクするための特別な処理を行います。
Goランタイム (runtime)
Go言語のランタイムは、Goプログラムの実行を管理するシステムです。これには、ガベージコレクション、ゴルーチンのスケジューリング、チャネルの操作、メモリ管理、システムコールへのインターフェースなどが含まれます。Goプログラムは、OS上で直接実行されるのではなく、このランタイムの上で動作します。
NetBSD
NetBSDは、オープンソースのUNIXライクなオペレーティングシステムであり、BSD系OSの一つです。移植性が非常に高く、多くの異なるハードウェアアーキテクチャで動作することで知られています。
environ
environ
は、C言語のプログラムにおいて、環境変数を格納するグローバル変数です。これは通常、char **environ
として宣言され、NULLで終端される文字列ポインタの配列として、KEY=VALUE
形式の環境変数文字列へのポインタを保持します。getenv()
などの関数は、このenviron
配列を検索して環境変数の値を取得します。
__progname
__progname
は、プログラムの実行ファイル名を格納するグローバル変数です。多くのUNIX系システムでは、main
関数の第一引数であるargv[0]
から初期化されます。デバッグやログ出力などでプログラム名が必要な場合に使用されます。
crt0.o
crt0.o
(C runtime zero object file)は、C言語のプログラムが実行を開始する際に最初にロードされるオブジェクトファイルです。これは、プログラムのエントリポイント(通常は_start
シンボル)を含み、main
関数が呼び出される前に、スタックのセットアップ、環境変数の初期化(environ
の設定)、コマンドライン引数の解析(argc
, argv
の設定)、標準I/Oストリームの初期化など、基本的なランタイム環境のセットアップを行います。
libc
(C標準ライブラリ)
libc
は、C言語の標準ライブラリであり、ファイルI/O、文字列操作、メモリ管理、数学関数、プロセス制御など、基本的なシステム機能を提供する関数の集合です。多くのCプログラムは、これらの関数を利用するためにlibc
にリンクされます。動的リンクの場合、プログラムの実行時にlibc
の共有ライブラリがロードされます。
#pragma dynexport
#pragma dynexport
は、特定のシンボル(変数や関数)を動的リンカが利用できるようにエクスポートするためのコンパイラ固有のディレクティブです。これは、共有ライブラリ(ダイナミックリンクライブラリ)から特定のシンボルを外部に公開する際に使用されます。このコミットの文脈では、Goランタイムが定義したenviron
と__progname
を、libc
などの外部ライブラリが動的に参照できるようにするために使用されています。
技術的詳細
Go言語のランタイムは、OSの起動メカニズムと密接に連携して動作します。通常のCプログラムがcrt0.o
を介して起動し、main
関数に制御が渡されるのに対し、Goプログラムは独自のruntime
パッケージがプログラムのエントリポイントとなり、OSから直接制御を受け取ることがあります。この場合、crt0.o
が通常行う環境のセットアップ(environ
や__progname
の初期化など)がスキップされる可能性があります。
NetBSDのlibc
は、動的リンクされた際に、これらのグローバルシンボル(environ
と__progname
)が利用可能であることを期待します。もしGoランタイムがこれらのシンボルを定義せず、かつcrt0.o
もリンクされない場合、libc
は未定義のシンボルを参照しようとしてエラーとなります。
このコミットの解決策は、Goランタイムの一部として、NetBSD固有のCファイル(netbsd.c
)を追加することです。このファイル内で、environ
と__progname
を明示的に宣言し、#pragma dynexport
ディレクティブを使用して、これらのシンボルが動的リンカによって外部に公開されるようにします。これにより、libc
がこれらのシンボルを必要とする際に、Goランタイムが提供する定義を参照できるようになり、ビルドおよび実行時の問題を回避します。
「Copy over freebsd.c to netbsd.c」という記述は、FreeBSD環境でも同様の問題が存在し、既に解決策が実装されていたことを示唆しています。NetBSDとFreeBSDはどちらもBSD系のOSであり、システム起動やlibc
の挙動に類似点があるため、FreeBSDの解決策をNetBSDに適用することができたと考えられます。
コアとなるコードの変更箇所
diff --git a/src/pkg/runtime/cgo/netbsd.c b/src/pkg/runtime/cgo/netbsd.c
new file mode 100644
index 0000000000..b6403f686c
--- /dev/null
+++ b/src/pkg/runtime/cgo/netbsd.c
@@ -0,0 +1,13 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Supply environ and __progname, because we don't
+// link against the standard NetBSD crt0.o and the
+// libc dynamic library needs them.
+
+char *environ[1];
+char *__progname;
+
+#pragma dynexport environ environ
+#pragma dynexport __progname __progname
コアとなるコードの解説
追加されたsrc/pkg/runtime/cgo/netbsd.c
ファイルの内容は以下の通りです。
-
著作権表示:
// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
Goプロジェクトの標準的な著作権表示です。
-
コメントによる目的説明:
// Supply environ and __progname, because we don't // link against the standard NetBSD crt0.o and the // libc dynamic library needs them.
このコードの目的を明確に説明しています。Goランタイムが標準のNetBSD
crt0.o
にリンクしないため、libc
動的ライブラリが必要とするenviron
と__progname
を提供する必要があることを述べています。 -
environ
の宣言:char *environ[1];
environ
グローバル変数を宣言しています。これはchar
ポインタの配列として定義されており、環境変数文字列へのポインタを保持します。[1]
というサイズは、少なくとも1つの要素(通常はNULL終端のため)を保持できることを示していますが、実際の環境変数のリストはGoランタイムの内部で管理され、必要に応じてこのポインタが更新されるか、あるいはlibc
がこのシンボルを単に存在することだけを期待している可能性があります。 -
__progname
の宣言:char *__progname;
__progname
グローバル変数を宣言しています。これはプログラム名文字列へのポインタを保持します。 -
#pragma dynexport
ディレクティブ:#pragma dynexport environ environ #pragma dynexport __progname __progname
この2行がこの修正の核心です。
#pragma dynexport
は、コンパイラに対して、指定されたシンボル(ここではenviron
と__progname
)を動的リンカが外部から参照できるようにエクスポートするよう指示します。これにより、Goランタイムがビルドされた際に、これらのシンボルが共有ライブラリの外部インターフェースとして利用可能になり、libc
などの他の動的リンクされたライブラリがこれらを正しく解決できるようになります。
このファイルは、GoランタイムがNetBSD上で動作する際の、C言語とのインターフェース層の一部として機能し、OS固有のリンキング要件を満たすための重要な役割を果たしています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/b4402a49b6c9a87f27c2140beacf46ef95738455
- Go Issue #3823 (このコミットによって修正された問題): https://go.dev/issue/3823 (GoのIssueトラッカーのURLは変更されている可能性がありますが、当時の参照は
https://golang.org/issue/3823
でした。)
参考にした情報源リンク
- コミットメッセージと変更されたコード
- C言語の
crt0.o
、environ
、__progname
に関する一般的な知識 - Go言語の
cgo
およびランタイムに関する一般的な知識 - BSD系OSのシステムプログラミングに関する一般的な知識