[インデックス 18195] ファイルの概要
このコミットは、Go言語のランタイムにおけるlibmach
ライブラリがPlan 9オペレーティングシステム上でGoのureg
ヘッダーを使用するように修正するものです。具体的には、以前の変更によってUreg
構造体の名称が変更されたことによるビルドエラーを解決します。
コミット
commit 43108ee53a62bdbafc16a1224eeed3c0e2fa71a6
Author: David du Colombier <0intro@gmail.com>
Date: Wed Jan 8 23:34:11 2014 +0100
libmach: use Go's ureg headers on Plan 9
The CL 49090043 renamed Ureg structures to Ureg386,
UregArm and UregAmd64. This broke build on Plan 9,
since ureg_x86.h includes /386/include/ureg.h, which
declares a structure named Ureg instead of Ureg386.
R=golang-codereviews, bradfitz
CC=golang-codereviews, rsc
https://golang.org/cl/49260043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/43108ee53a62bdbafc16a1224eeed3c0e2fa71a6
元コミット内容
libmach: use Go's ureg headers on Plan 9
The CL 49090043 renamed Ureg structures to Ureg386,
UregArm and UregAmd64. This broke build on Plan 9,
since ureg_x86.h includes /386/include/ureg.h, which
declares a structure named Ureg instead of Ureg386.
変更の背景
このコミットの背景には、Go言語のランタイムにおけるレジスタ情報構造体(Ureg
)の命名規則の変更があります。以前の変更(CL 49090043
)により、汎用的なUreg
構造体が、特定のアーキテクチャ(x86、ARM、AMD64)に対応するUreg386
、UregArm
、UregAmd64
という具体的な名前に変更されました。
この変更自体は、Goランタイムの内部的な整合性を高めるためのものと考えられます。しかし、この変更がPlan 9オペレーティングシステム上でのGoのビルドプロセスに予期せぬ影響を与えました。Plan 9のシステムヘッダーファイル(例: /386/include/ureg.h
)が、依然として汎用的なUreg
という名前の構造体を宣言していたため、Goの新しい命名規則と競合が発生し、ビルドエラーを引き起こしていました。
このコミットは、このビルドエラーを解決し、GoランタイムがPlan 9上で正しくコンパイルされるようにするためのものです。
前提知識の解説
このコミットを理解するためには、以下の前提知識が必要です。
- Go言語のランタイム (Go Runtime): Goプログラムの実行を管理する低レベルのコンポーネントです。ガベージコレクション、スケジューリング、システムコールなど、多くの重要な機能を提供します。オペレーティングシステムと密接に連携して動作します。
- Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステムです。Unixの概念をさらに推し進め、すべてのリソースをファイルとして表現する「Everything is a file」という哲学を持っています。Go言語はPlan 9の影響を強く受けており、Goの初期開発者の中にはPlan 9の開発者が多く含まれています。
ureg
構造体 (User Register Structure): オペレーティングシステムにおいて、ユーザーモードのプログラムが実行中に使用するCPUレジスタの状態を保存するためのデータ構造です。これは、シグナルハンドリング、デバッグ、コンテキストスイッチなどの際に、プロセスの状態を保存・復元するために使用されます。アーキテクチャによってレジスタセットが異なるため、通常はアーキテクチャ固有の定義を持ちます。libmach
: Go言語のツールチェインの一部であり、デバッガやプロファイラなどのツールが、異なるアーキテクチャやオペレーティングシステム上の実行ファイルやコアダンプを解析するために使用するライブラリです。プロセスのメモリレイアウト、レジスタ情報、スタックトレースなどを抽象化して提供します。CL
(Change List): Goプロジェクトにおける変更の単位です。GoのコードレビューシステムであるGerritで管理されます。CL 49090043
は、このコミットの前にUreg
構造体の名前変更を行った特定の変更セットを指します。- ヘッダーファイル (
.h
ファイル): C言語やC++において、関数や構造体、マクロなどの宣言を含むファイルです。他のソースファイルからこれらの宣言を参照するためにインクルードされます。このコミットでは、Plan 9のシステムヘッダーとGoのヘッダーのインクルードパスが問題となっています。 - インクルードパス: コンパイラがヘッダーファイルを検索するディレクトリのリストです。
#include
ディレクティブで指定されたファイル名に基づいて、コンパイラはこのパスを探索します。
技術的詳細
このコミットが解決しようとしている問題は、GoランタイムがPlan 9上でビルドされる際のヘッダーファイルのインクルードパスと構造体名の不整合です。
-
問題の発生源:
- Goランタイムの以前の変更(
CL 49090043
)により、レジスタ情報を保持する構造体Ureg
が、アーキテクチャ固有のUreg386
、UregArm
、UregAmd64
にリネームされました。これは、Goの内部でより明確な命名規則と型安全性を確保するためと考えられます。 - しかし、Plan 9オペレーティングシステムには、独自のシステムヘッダーファイル(例:
/386/include/ureg.h
)が存在します。これらのヘッダーファイルは、依然として汎用的なUreg
という名前の構造体を定義していました。 - Goの
libmach
ライブラリがPlan 9上でビルドされる際、GoのコードはPlan 9のシステムヘッダーをインクルードする必要がありました。特に、include/plan9/ureg_x86.h
のようなファイルは、"/386/include/ureg.h"
をインクルードしていました。 - この結果、Goのコードが期待する
Ureg386
などの構造体名と、Plan 9のシステムヘッダーが提供するUreg
という構造体名との間で不一致が生じ、コンパイルエラーが発生しました。コンパイラは、Ureg386
という名前が見つからない、あるいはUreg
とUreg386
が異なる型であると認識し、エラーを出力しました。
- Goランタイムの以前の変更(
-
解決策:
- このコミットは、Goの
libmach
がPlan 9上で使用するヘッダーファイルのインクルードパスを変更することで問題を解決します。 - 具体的には、
include/plan9/ureg_amd64.h
、include/plan9/ureg_arm.h
、include/plan9/ureg_x86.h
の各ファイルで、絶対パス(例:"/amd64/include/ureg.h"
)でPlan 9のシステムヘッダーをインクルードする代わりに、相対パス(例:"../ureg_amd64.h"
)でGo自身のureg
ヘッダーをインクルードするように変更します。 - これにより、
libmach
はPlan 9のシステムが提供する汎用的なUreg
構造体ではなく、Goランタイムが定義するアーキテクチャ固有のUreg386
、UregArm
、UregAmd64
構造体を使用するようになります。 - この修正により、Goの新しい命名規則とPlan 9のシステムヘッダーとの間の競合が解消され、Plan 9上でのGoのビルドが再び可能になります。
- このコミットは、Goの
この変更は、Goが複数のオペレーティングシステムとアーキテクチャをサポートする上で、それぞれの環境固有のシステムヘッダーやABI(Application Binary Interface)との整合性をどのように維持しているかを示す良い例です。
コアとなるコードの変更箇所
このコミットでは、以下の3つのファイルが変更されています。
include/plan9/ureg_amd64.h
include/plan9/ureg_arm.h
include/plan9/ureg_x86.h
それぞれのファイルで、インクルードパスが絶対パスから相対パスに変更されています。
include/plan9/ureg_amd64.h
の変更:
--- a/include/plan9/ureg_amd64.h
+++ b/include/plan9/ureg_amd64.h
@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "/amd64/include/ureg.h"
+#include "../ureg_amd64.h"
include/plan9/ureg_arm.h
の変更:
--- a/include/plan9/ureg_arm.h
+++ b/include/plan9/ureg_arm.h
@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "/arm/include/ureg.h"
+#include "../ureg_arm.h"
include/plan9/ureg_x86.h
の変更:
--- a/include/plan9/ureg_x86.h
+++ b/include/plan9/ureg_x86.h
@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "/386/include/ureg.h"
+#include "../ureg_x86.h"
コアとなるコードの解説
変更された各ファイルは、GoランタイムがPlan 9上で特定のアーキテクチャ(AMD64、ARM、x86)のレジスタ情報を扱うためのヘッダーファイルです。
元のコードでは、以下のように絶対パスでPlan 9のシステムヘッダーをインクルードしていました。
#include "/amd64/include/ureg.h" // または /arm/include/ureg.h, /386/include/ureg.h
これは、Plan 9のシステムが提供するureg.h
ファイルを参照することを意図していました。しかし、前述の通り、このシステムヘッダーはGoの新しい命名規則(Ureg386
など)と互換性のないUreg
という構造体を定義していました。
このコミットによる変更は、インクルードパスを以下のように相対パスに変更します。
#include "../ureg_amd64.h" // または ../ureg_arm.h, ../ureg_x86.h
この相対パスは、Go自身のソースツリー内にあるureg_amd64.h
(またはureg_arm.h
、ureg_x86.h
)を参照することを意味します。これらのファイルは、Goランタイムが定義する正しいアーキテクチャ固有のUreg
構造体(UregAmd64
、UregArm
、Ureg386
)を含んでいます。
結果として、libmach
はPlan 9のシステムヘッダーではなく、Goランタイムが期待する形式のレジスタ情報構造体を使用するようになり、ビルドエラーが解消されます。これは、Goがクロスプラットフォーム対応を行う上で、各プラットフォームのシステムヘッダーとGo自身の内部定義との間の整合性をどのように管理しているかを示す典型的な例です。
関連リンク
- Goのコードレビューシステム (Gerrit) 上の関連する変更リスト: https://golang.org/cl/49260043
- このコミットが修正した問題の原因となった変更リスト (CL 49090043) については、Gerritで検索することで詳細が見つかる可能性があります。
参考にした情報源リンク
- Go言語の公式ドキュメント (Go Runtime, Plan 9に関する情報): https://golang.org/doc/
- Plan 9 from Bell Labs 公式サイト: https://9p.io/plan9/
ureg
構造体に関する一般的な情報 (オペレーティングシステムのカーネル開発やデバッグの文脈):- Linuxカーネルにおける
ureg
構造体 (例:struct pt_regs
): https://www.kernel.org/doc/html/latest/core-api/ptrace.html - Unix系システムのシグナルハンドリングとコンテキスト: https://man7.org/linux/man-pages/man7/signal.7.html
- Linuxカーネルにおける
libmach
に関する情報 (Goのデバッグツールや内部構造に関する議論):- Goのソースコードリポジトリ: https://github.com/golang/go
- Goのデバッグに関するブログ記事やドキュメント (例:
go tool pprof
,go tool trace
など)
- C言語の
#include
ディレクティブとインクルードパスに関する情報:- GCCのドキュメント: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html
- C言語のプリプロセッサに関する一般的な解説