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

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

このコミットは、GoランタイムにおけるWindowsビルドの問題を修正するものです。具体的には、runtime·badsignalというシンボル名をruntime·badsignal2に変更することで、Windows環境でのビルドエラーを解消しています。

コミット

commit 4a4d48328bb3f24aad5b25ac55c42a561d4a6341
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri Jul 12 05:06:43 2013 +0800

    runtime: fix build for windows.
    
    R=golang-dev
    CC=golang-dev
    https://golang.org/cl/11188043

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

https://github.com/golang/go/commit/4a4d48328bb3f24aad5b25ac55c42a561d4a6341

元コミット内容

runtime: fix build for windows.

R=golang-dev
CC=golang-dev
https://golang.org/cl/11188043

変更の背景

このコミットの背景には、Go言語のランタイムがWindows環境でビルドされる際に発生していたシンボル名の衝突問題があります。Goランタイムは、OSの低レベルな機能と直接やり取りするために、アセンブリ言語で書かれたコードを含んでいます。特にWindowsのような特定のOSでは、システムが予約している関数名やシンボル名が存在し、Goランタイム内で定義されたシンボルがこれらと偶然一致してしまうと、リンカーエラーやビルド失敗の原因となります。

badsignalという名前は、シグナルハンドリングに関連するエラー処理を示すためにGoランタイム内で使用されていた可能性があります。しかし、Windowsのシステムライブラリやヘッダーファイルに同名のシンボルが存在したため、ビルドプロセス中に名前の衝突が発生し、コンパイルが通らない状況が生じていました。この問題は、Go言語がクロスプラットフォーム対応を進める上で、各OS固有の制約に直面した典型的な例と言えます。

この修正は、特定の環境(この場合はWindows)でのビルドの安定性を確保し、Go言語のクロスコンパイル能力を維持するために不可欠でした。シンボル名をわずかに変更するだけで問題を回避できる場合、それは最も影響が少なく、かつ効果的な解決策となります。

前提知識の解説

Goランタイム (Go Runtime)

Goランタイムは、Go言語で書かれたプログラムを実行するために必要な基盤となるソフトウェアです。これには、ガベージコレクタ、スケジューラ(ゴルーチンの管理)、メモリ管理、システムコールインターフェースなどが含まれます。Goプログラムは、コンパイル時にこのランタイムとリンクされ、単一の実行可能ファイルを生成します。ランタイムの一部は、パフォーマンスやOSとの直接的なやり取りのために、C言語やアセンブリ言語で書かれています。

アセンブリ言語 (.sファイル)

Go言語のソースコードには、.s拡張子を持つファイルが含まれることがあります。これらはアセンブリ言語で書かれたファイルであり、特定のCPUアーキテクチャ(例: 386はIntel/AMDの32ビットアーキテクチャ、amd64は64ビットアーキテクチャ)やOS(例: windows)に特化した低レベルな処理を記述するために使用されます。アセンブリ言語は、OSのカーネル機能へのアクセス、コンテキストスイッチ、特定のレジスタ操作など、Go言語の高級な機能では直接扱えない部分を実装する際に用いられます。

シンボル (Symbol)

プログラミングにおいて、シンボルとは、変数、関数、クラスなどのプログラム要素を一意に識別するための名前です。コンパイルおよびリンクのプロセスにおいて、これらのシンボルはメモリ上の特定のアドレスに関連付けられます。異なるモジュールやライブラリが同じシンボル名を持つ場合、リンカーはどの定義を使用すべきか判断できず、シンボル衝突(Symbol Collision)と呼ばれるエラーが発生することがあります。

シグナルハンドリング (Signal Handling)

シグナルは、オペレーティングシステムがプロセスに対して非同期に通知を送信するメカニズムです。例えば、プログラムの異常終了(セグメンテーション違反)、Ctrl+Cによる中断、タイマーの満了などがシグナルとして通知されます。シグナルハンドリングは、これらのシグナルを受信した際に、プログラムがどのように応答するかを定義するプロセスです。Goランタイムは、プログラムの安定性と堅牢性を保つために、OSからのシグナルを適切に処理するメカニズムを持っています。badsignalのようなシンボルは、おそらく不正なシグナルやシグナル処理におけるエラー状態を扱うための内部関数に関連していたと考えられます。

Windowsビルド

Go言語はクロスプラットフォーム対応を重視しており、Windows、Linux、macOSなど様々なOSで動作するバイナリを生成できます。Windows環境でのビルドは、他のUnix系OSとは異なるAPIやシステムコール、リンカーの挙動を持つため、特に低レベルなランタイムコードにおいては、OS固有の調整が必要となることがあります。

技術的詳細

このコミットの技術的な核心は、Goランタイムのアセンブリコードにおけるシンボル名の変更です。具体的には、src/pkg/runtime/sys_windows_386.ssrc/pkg/runtime/sys_windows_amd64.sの2つのファイルで、runtime·badsignalというシンボルがruntime·badsignal2にリネームされています。

アセンブリ言語では、TEXTディレクティブは関数の開始を宣言し、その後に続くシンボル名がその関数のエントリポイントとなります。runtime·badsignal(SB)という表記は、runtimeパッケージ内のbadsignalという関数シンボルを指し、(SB)はStatic Baseを意味し、シンボルが静的にリンクされることを示します。

この変更は、Windows環境でのビルド時に、Goランタイムが定義するruntime·badsignalというシンボルが、Windowsのシステムライブラリやヘッダーファイルに存在する別のシンボルと名前が衝突していたために行われました。このようなシンボル衝突は、特にC/C++で書かれたライブラリをリンクする際や、OSが予約している名前を使用している場合に発生しやすい問題です。

シンボル名をbadsignalからbadsignal2へとわずかに変更することで、この衝突を回避し、Windows上でのGoランタイムのビルドを成功させています。これは、機能的な変更ではなく、ビルドシステムにおける互換性の問題を解決するための純粋なリファクタリングです。

変更された2つのファイルは、それぞれ32ビット(sys_windows_386.s)と64ビット(sys_windows_amd64.s)のWindowsアーキテクチャ向けのアセンブリコードを含んでいます。これは、両方のアーキテクチャで同じシンボル衝突の問題が発生していたことを示唆しています。

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

変更は以下の2つのファイルで行われています。

  1. src/pkg/runtime/sys_windows_386.s (32ビットWindows向けランタイムアセンブリ)
  2. src/pkg/runtime/sys_windows_amd64.s (64ビットWindows向けランタイムアセンブリ)

それぞれのファイルで、TEXT runtime·badsignal(SB)の定義と、その関数を呼び出しているCALL runtime·badsignal(SB)の箇所が、TEXT runtime·badsignal2(SB)CALL runtime·badsignal2(SB)に変更されています。

src/pkg/runtime/sys_windows_386.s の変更点

--- a/src/pkg/runtime/sys_windows_386.s
+++ b/src/pkg/runtime/sys_windows_386.s
@@ -38,7 +38,7 @@ TEXT runtime·asmstdcall(SB),7,$0
  
  	RET
  
-TEXT	runtime·badsignal(SB),7,$24
+TEXT	runtime·badsignal2(SB),7,$24
  	// stderr
  	MOVL	$-12, 0(SP)
  	MOVL	SP, BP
@@ -86,7 +86,7 @@ TEXT runtime·sigtramp(SB),7,$28
  	MOVL	m(CX), AX
  	CMPL	AX, $0
  	JNE	2(PC)
-\tCALL	runtime·badsignal(SB)
+\tCALL	runtime·badsignal2(SB)
  
  	MOVL	g(CX), CX
  	MOVL	CX, 8(SP)

src/pkg/runtime/sys_windows_amd64.s の変更点

--- a/src/pkg/runtime/sys_windows_amd64.s
+++ b/src/pkg/runtime/sys_windows_amd64.s
@@ -60,7 +60,7 @@ loadregs:
  
  	RET
  
-TEXT runtime·badsignal(SB),7,$48
+TEXT runtime·badsignal2(SB),7,$48
  	// stderr
  	MOVQ	$-12, CX // stderr
  	MOVQ	CX, 0(SP)
@@ -118,7 +118,7 @@ TEXT runtime·sigtramp(SB),7,$0
  	MOVQ	m(CX), AX
  	CMPQ	AX, $0
  	JNE	2(PC)
-\tCALL	runtime·badsignal(SB)
+\tCALL	runtime·badsignal2(SB)
  
  	MOVQ	g(CX), CX
  	MOVQ	CX, 16(SP)

コアとなるコードの解説

このコミットのコード変更は非常にシンプルで、runtime·badsignalというシンボル名をruntime·badsignal2に変更しているだけです。

  • TEXT runtime·badsignal(SB),7,$24 (または $48) から TEXT runtime·badsignal2(SB),7,$24 (または $48) への変更: これは、badsignalという名前の関数の定義を、badsignal2という新しい名前に変更している部分です。TEXTディレクティブはアセンブリ言語における関数のエントリポイントを宣言します。(SB)はStatic Baseを意味し、シンボルが静的にリンクされることを示します。$24$48は、その関数のスタックフレームサイズを示している可能性があります。

  • CALL runtime·badsignal(SB) から CALL runtime·badsignal2(SB) への変更: これは、変更されたbadsignal関数を呼び出している箇所を、新しい名前badsignal2で呼び出すように修正している部分です。CALL命令は、指定されたシンボル(関数)に制御を移すために使用されます。

この変更は、Goランタイムの内部的な動作やロジックには一切影響を与えません。単に、Windows環境でのビルド時に発生する可能性のあるシンボル名の衝突を回避するための、純粋な名前変更です。これにより、GoプログラムがWindows上で正しくコンパイルおよびリンクされるようになります。

関連リンク

  • Go言語の公式ドキュメント: https://golang.org/doc/
  • Go言語のランタイムに関する情報: Goのソースコードリポジトリ内のsrc/runtimeディレクトリを参照。

参考にした情報源リンク