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

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

本コミットは、GoランタイムがNetBSD上で使用するシグナルABIのバージョンを、バージョン3からバージョン2へ変更するものです。これにより、NetBSDのnetbsd32互換モードにおけるGoバイナリの実行互換性が向上します。

コミット

commit 79473d6b1cec225d498f300c67a89fa589c48855
Author: Joel Sing <jsing@google.com>
Date:   Sun Aug 26 20:57:47 2012 +1000

    runtime: use netbsd signal ABI v2
    
    Use version 2 of the NetBSD signal ABI - both version 2 and version 3
    are supported by the kernel, with near identical behaviour. However,
    the netbsd32 compat code does not allow version 3 to be used, which
    prevents Go netbsd/386 binaries from running in compat mode on a
    NetBSD amd64 kernel. Switch to version 2 of the ABI, which is the
    same version currently used by NetBSD's libc.
    
    R=minux.ma
    CC=golang-dev
    https://golang.org/cl/6476068

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

https://github.com/golang/go/commit/79473d6b1cec225d498f300c67a89fa589c48855

元コミット内容

runtime: use netbsd signal ABI v2

Use version 2 of the NetBSD signal ABI - both version 2 and version 3
are supported by the kernel, with near identical behaviour. However,
the netbsd32 compat code does not allow version 3 to be used, which
prevents Go netbsd/386 binaries from running in compat mode on a
NetBSD amd64 kernel. Switch to version 2 of the ABI, which is the
same version currently used by NetBSD's libc.

変更の背景

この変更の主な背景は、NetBSDのnetbsd32互換モードにおけるGoバイナリの実行互換性の問題です。

NetBSDカーネルはシグナルABIのバージョン2とバージョン3の両方をサポートしており、その動作はほぼ同じです。しかし、netbsd32互換コードがバージョン3のABIの使用を許可していませんでした。この制約により、NetBSD/amd64カーネル上でnetbsd32互換モードを使用してNetBSD/386向けのGoバイナリを実行しようとすると、問題が発生し、実行が妨げられていました。

この問題を解決するため、Goランタイムが使用するシグナルABIのバージョンを、NetBSDのlibcが現在使用しているバージョンと同じバージョン2に切り替えることが決定されました。これにより、netbsd32互換モードでのGoバイナリの実行が可能になり、互換性が向上します。

前提知識の解説

NetBSD シグナルABI (Application Binary Interface)

シグナルABIは、オペレーティングシステムがプロセスにシグナル(ソフトウェア割り込み)を通知し、プロセスがそれに応答する方法を定義するインターフェースです。これには、シグナルハンドラの呼び出し規約、シグナルフレームの構造、およびカーネルとユーザー空間間のシグナル関連のシステムコールが含まれます。

NetBSDにおけるシグナルABIは、主に「シグナルトランポリン」を中心に構築されています。シグナルトランポリンは、シグナルハンドラの実行後にプロセスの状態をクリーンアップする役割を担う小さなアセンブリコードです。このトランポリンは、シグナルハンドラの呼び出しのためにユーザーコンテキストを準備するカーネルのsendsig()関数と連携して動作します。

NetBSDのシグナルABIのバージョン管理は、__sigtramp_<flavor>_<version>という命名規則で行われます。

  • <flavor>はシグナルハンドラのタイプを示します。
    • sigcontext: 従来のBSDスタイルのシグナルハンドラ。古いバイナリとの互換性のために維持されていますが、現在は非推奨です。
    • siginfo: POSIXスタイルのシグナルハンドラ。現代的で推奨されるアプローチです。
  • <version>はシグナルトランポリンのABIバージョンを指定します。

このコミットの時点では、POSIXスタイルのsiginfoハンドラの場合、バージョン2 (__sigtramp_siginfo_2) が標準的なABIとして使用されていました。

NetBSD netbsd32 互換モード

netbsd32互換モードは、64ビットのNetBSDシステム上で32ビットのNetBSDバイナリを実行可能にする機能です。これは、古いアプリケーションや32ビットアーキテクチャ向けにコンパイルされたソフトウェアを64ビットのNetBSD環境で実行する際に特に有用です。

この機能は、compat_netbsd32モジュールによって実現されます。このモジュールは、32ビットバイナリの引数を、LP64(64ビット)システム上のカーネルが期待する64ビットの引数に変換することで、32ビットバイナリの実行を可能にします。例えば、NetBSD/amd64上でNetBSD/i386の実行ファイルを動作させることができます。

このモードを利用するには、NetBSDカーネルがCOMPAT_NETBSD32およびEXEC_ELF32オプションで設定されているか、これらの機能がカーネルモジュールとしてロードされている必要があります。また、動的にリンクされた32ビットプログラムの場合、対応する32ビット共有ライブラリとダイナミックリンカが不可欠です。NetBSD 5.0以降では、これらの必要な32ビットコンポーネントはベースシステムに直接含まれ、/usr以下にインストールされます。

技術的詳細

この変更は、GoランタイムがNetBSD上でシグナルを処理する際に使用するABIバージョンを明示的に指定する部分に焦点を当てています。具体的には、sigactionシステムコールを呼び出す際に渡されるABIバージョン番号を3から2に変更します。

sigactionシステムコールは、シグナルハンドラのインストール、変更、または検査を行うために使用されます。このシステムコールは、シグナルハンドラの設定に加えて、シグナル処理の動作を制御するための様々なフラグや、シグナルハンドラが呼び出される際のコンテキストに関する情報(シグナルABIバージョンなど)を受け取ります。

コミットメッセージにあるように、NetBSDカーネルはシグナルABIのバージョン2と3の両方をサポートしていますが、netbsd32互換コードがバージョン3の使用を許可していませんでした。これは、32ビットバイナリが64ビットカーネル上で動作する際に、シグナル処理のメカニズムに特定の制約があることを示唆しています。バージョン3のABIが何らかの形で32ビットと64ビットの間の変換で問題を引き起こすか、あるいは単にnetbsd32互換レイヤーがバージョン3のシグナルABIを正しくエミュレートまたは変換できない可能性があります。

Goランタイムがバージョン2のABIを使用するように変更することで、NetBSDのlibcが使用しているバージョンと一致させ、netbsd32互換モードでのGoバイナリの実行を可能にします。これは、Goがシステムコールを直接呼び出す際に、OSの既存のライブラリ(libc)との互換性を確保することの重要性を示しています。異なるABIバージョンを使用すると、シグナルハンドラの呼び出し規約やスタックフレームのレイアウトが異なり、予期せぬ動作やクラッシュを引き起こす可能性があります。

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

変更は、GoランタイムのNetBSD向けアセンブリコードファイルにあります。

  1. src/pkg/runtime/sys_netbsd_386.s (NetBSD/386アーキテクチャ向け)
  2. src/pkg/runtime/sys_netbsd_amd64.s (NetBSD/amd64アーキテクチャ向け)

それぞれのファイルで、runtime·sigaction関数内のシグナルABIバージョンを設定する部分が変更されています。

diff --git a/src/pkg/runtime/sys_netbsd_386.s b/src/pkg/runtime/sys_netbsd_386.s
index 8b5d201e6b..75a38f820e 100644
--- a/src/pkg/runtime/sys_netbsd_386.s
+++ b/src/pkg/runtime/sys_netbsd_386.s
@@ -164,7 +164,7 @@ TEXT runtime·sigaction(SB),7,$24
  	MOVSL			// arg 3 - oact
  	LEAL	runtime·sigreturn_tramp(SB), AX
  	STOSL			// arg 4 - tramp
-	MOVL	$3, AX
+	MOVL	$2, AX
  	STOSL			// arg 5 - vers
  	MOVL	$340, AX		// sys___sigaction_sigtramp
  	INT	$0x80
diff --git a/src/pkg/runtime/sys_netbsd_amd64.s b/src/pkg/runtime/sys_netbsd_amd64.s
index b13800c47e..f5feb48418 100644
--- a/src/pkg/runtime/sys_netbsd_amd64.s
+++ b/src/pkg/runtime/sys_netbsd_amd64.s
@@ -183,7 +183,7 @@ TEXT runtime·sigaction(SB),7,$-8
  	MOVQ	24(SP), DX		// arg 3 - osa
  					// arg 4 - tramp
  	LEAQ	runtime·sigreturn_tramp(SB), R10
-	MOVQ	$3, R8			// arg 5 - version
+	MOVQ	$2, R8			// arg 5 - vers
  	MOVL	$340, AX		// sys___sigaction_sigtramp
  	SYSCALL
  	JCC	2(PC)

コアとなるコードの解説

これらのアセンブリコードの変更は、sigactionシステムコールを呼び出す直前に、シグナルABIのバージョン番号をレジスタにロードする命令を変更しています。

src/pkg/runtime/sys_netbsd_386.s (32-bit x86)

-	MOVL	$3, AX
+	MOVL	$2, AX
 	STOSL			// arg 5 - vers
  • MOVL $3, AX: 以前は、即値3AXレジスタ(32ビットモードでの汎用レジスタ)に移動していました。これは、シグナルABIバージョン3を指定していました。
  • MOVL $2, AX: 変更後、即値2AXレジスタに移動します。これにより、シグナルABIバージョン2が指定されます。
  • STOSL: AXレジスタの内容を、sigactionシステムコールの5番目の引数(バージョン番号)としてスタックに格納します。

src/pkg/runtime/sys_netbsd_amd64.s (64-bit x86-64)

-	MOVQ	$3, R8			// arg 5 - version
+	MOVQ	$2, R8			// arg 5 - vers
  • MOVQ $3, R8: 以前は、即値3R8レジスタ(64ビットモードでの汎用レジスタ)に移動していました。これは、シグナルABIバージョン3を指定していました。
  • MOVQ $2, R8: 変更後、即値2R8レジスタに移動します。これにより、シグナルABIバージョン2が指定されます。
  • 64ビットシステムコール規約では、引数は通常レジスタで渡されます。R8は、このコンテキストで5番目の引数(バージョン番号)を保持するために使用されます。

どちらの変更も、sigactionシステムコールに渡されるシグナルABIバージョン番号を、バージョン3からバージョン2に直接変更することを目的としています。これにより、netbsd32互換モードでのGoバイナリの実行における互換性の問題が解消されます。

関連リンク

参考にした情報源リンク