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

[インデックス 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)に対応するUreg386UregArmUregAmd64という具体的な名前に変更されました。

この変更自体は、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上でビルドされる際のヘッダーファイルのインクルードパスと構造体名の不整合です。

  1. 問題の発生源:

    • Goランタイムの以前の変更(CL 49090043)により、レジスタ情報を保持する構造体Uregが、アーキテクチャ固有のUreg386UregArmUregAmd64にリネームされました。これは、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という名前が見つからない、あるいはUregUreg386が異なる型であると認識し、エラーを出力しました。
  2. 解決策:

    • このコミットは、GoのlibmachがPlan 9上で使用するヘッダーファイルのインクルードパスを変更することで問題を解決します。
    • 具体的には、include/plan9/ureg_amd64.hinclude/plan9/ureg_arm.hinclude/plan9/ureg_x86.hの各ファイルで、絶対パス(例: "/amd64/include/ureg.h")でPlan 9のシステムヘッダーをインクルードする代わりに、相対パス(例: "../ureg_amd64.h")でGo自身のuregヘッダーをインクルードするように変更します。
    • これにより、libmachはPlan 9のシステムが提供する汎用的なUreg構造体ではなく、Goランタイムが定義するアーキテクチャ固有のUreg386UregArmUregAmd64構造体を使用するようになります。
    • この修正により、Goの新しい命名規則とPlan 9のシステムヘッダーとの間の競合が解消され、Plan 9上でのGoのビルドが再び可能になります。

この変更は、Goが複数のオペレーティングシステムとアーキテクチャをサポートする上で、それぞれの環境固有のシステムヘッダーやABI(Application Binary Interface)との整合性をどのように維持しているかを示す良い例です。

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

このコミットでは、以下の3つのファイルが変更されています。

  1. include/plan9/ureg_amd64.h
  2. include/plan9/ureg_arm.h
  3. 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.hureg_x86.h)を参照することを意味します。これらのファイルは、Goランタイムが定義する正しいアーキテクチャ固有のUreg構造体(UregAmd64UregArmUreg386)を含んでいます。

結果として、libmachはPlan 9のシステムヘッダーではなく、Goランタイムが期待する形式のレジスタ情報構造体を使用するようになり、ビルドエラーが解消されます。これは、Goがクロスプラットフォーム対応を行う上で、各プラットフォームのシステムヘッダーとGo自身の内部定義との間の整合性をどのように管理しているかを示す典型的な例です。

関連リンク

  • Goのコードレビューシステム (Gerrit) 上の関連する変更リスト: https://golang.org/cl/49260043
  • このコミットが修正した問題の原因となった変更リスト (CL 49090043) については、Gerritで検索することで詳細が見つかる可能性があります。

参考にした情報源リンク