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

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

このコミットは、GoランタイムがWindows/386アーキテクチャ上で例外処理を行う方法を、従来のStructured Exception Handling (SEH) からVectored Exception Handling (VEH) へと変更するものです。この変更は、Goの独自のスタック管理とSEHの間の根本的な非互換性を解決し、ランタイムの安定性と保守性を向上させることを目的としています。これにより、Windows 2000のサポートが終了し、Windows XP以降が必須となりました。

コミット

commit 3750904a7efc36aa4f604497b53a9dc1ea67492b
Author: Russ Cox <rsc@golang.org>
Date:   Mon Mar 24 21:22:16 2014 -0400

    runtime: use VEH, not SEH, for windows/386 exception handling
    
    Structured Exception Handling (SEH) was the first way to handle
    exceptions (memory faults, divides by zero) on Windows.
    The S might as well stand for "stack-based": the implementation
    interprets stack addresses in a few different ways, and it gets
    subtly confused by Go's management of stacks. It's also something
    that requires active maintenance during cgo switches, and we've
    had bugs in that maintenance in the past.
    
    We have recently come to believe that SEH cannot work with
    Go's stack usage. See http://golang.org/issue/7325 for details.
    
    Vectored Exception Handling (VEH) is more like a Unix signal
    handler: you set it once for the whole process and forget about it.
    
    This CL drops all the SEH code and replaces it with VEH code.
    Many special cases and 7 #ifdefs disappear.
    
    VEH was introduced in Windows XP, so Go on windows/386 will
    now require Windows XP or later. The previous requirement was
    Windows 2000 or later. Windows 2000 immediately preceded
    Windows XP, so Windows 2000 is the only affected version.
    Microsoft stopped supporting Windows 2000 in 2010.
    See http://golang.org/s/win2000-golang-nuts for details.
    
    Fixes #7325.

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

https://github.com/golang/go/commit/3750904a7efc36aa4f604497b53a9dc1ea67492b

元コミット内容

このコミットは、GoランタイムがWindows/386環境での例外処理にStructured Exception Handling (SEH) ではなくVectored Exception Handling (VEH) を使用するように変更します。SEHはスタックベースの例外処理メカニズムであり、Goのスタック管理と相性が悪く、過去に多くのバグの原因となっていました。VEHはUnixのシグナルハンドラに似ており、プロセス全体で一度設定すればよく、Goのスタック管理との競合が少ないため、より堅牢な例外処理を実現します。この変更により、SEH関連のコードが削除され、多くの特殊ケースや条件付きコンパイルディレクティブが不要になります。また、VEHはWindows XPで導入されたため、GoのWindows/386版はWindows XP以降を必要とするようになり、Windows 2000のサポートは終了しました。

変更の背景

Goランタイムは、その効率的な並行処理モデルを実現するために、独自の軽量なゴルーチンスタック管理を採用しています。ゴルーチンは小さなスタックで開始し、必要に応じて動的にスタックを拡張します(コピーイングスタック)。しかし、Windowsの従来の例外処理メカニズムであるStructured Exception Handling (SEH) は、スタックベースであり、例外ハンドラがスタック上の特定の情報に依存していました。

Goのスタック管理とSEHの間の非互換性は、特にWindows/386環境で深刻な問題を引き起こしていました。Goランタイムがスタックを切り替える際、SEHが期待するスタックレイアウトと実際のスタックが一致しないことがあり、これがランタイムの不安定性やクラッシュの原因となっていました。具体的には、divmod.exeのようなテストプログラムが、ゼロ除算エラーに対してGoのパニック/リカバリメカニズムが機能せず、Windowsの未処理例外としてクラッシュする問題(Issue #7325)が発生していました。これは、GoのSEHハンドラがSEHチェーンから削除されてしまうことに起因していました。

この問題は、Goのスタックコピアが例外ハンドラのスタックを正しくトレースバックできないことにも関連していました。Go開発チームは、SEHがGoのスタック使用と根本的に両立できないと判断し、より現代的でスタックに依存しないVectored Exception Handling (VEH) への移行を決定しました。

また、VEHはWindows XPで導入された機能であり、Windows 2000では利用できませんでした。Windows 2000は2010年にMicrosoftのサポートが終了しており、Goコミュニティ内でもWindows 2000のユーザーベースが非常に少ないという認識がありました。そのため、古いOSのサポートを維持することによる開発負担と、VEHへの移行によるランタイムの安定性向上というメリットを比較検討した結果、Windows 2000のサポートを終了し、Windows XP以降を必須とすることが決定されました。

前提知識の解説

Structured Exception Handling (SEH)

Structured Exception Handling (SEH) は、Windowsが提供する例外処理メカニズムの一つで、主にC/C++言語の拡張として提供されてきました。ハードウェア例外(メモリ違反、ゼロ除算など)やソフトウェア例外を処理するために使用されます。

  • スタックベース: SEHはスタックフレームにハンドラを登録する形式を取ります。例外が発生すると、システムはコールスタックを遡り、最も最近にインストールされた例外ハンドラを探します。
  • キーワード: Microsoft Visual C++では、__try, __except, __finally といったキーワードを用いてSEHを実装します。
  • スレッド固有: SEHハンドラはスレッドごとに設定され、管理されます。
  • __finallyブロック: 例外の発生有無にかかわらず、必ず実行されるコードブロックを定義できます。リソースの解放などに利用されます。
  • 32ビットSEH: スタック上に _EXCEPTION_REGISTRATION_RECORD 構造体のリンクリストを構築してハンドラを管理します。
  • 問題点: Goのような独自のスタック管理を行うランタイムでは、スタックのレイアウトが頻繁に変化するため、SEHが期待するスタック情報との不整合が生じやすく、不安定性の原因となることがありました。

Vectored Exception Handling (VEH)

Vectored Exception Handling (VEH) は、Windows XPで導入された、SEHを拡張するより新しい例外処理メカニズムです。

  • プロセス全体: SEHがスレッド固有であるのに対し、VEHハンドラはプロセス全体に適用されます。例外が発生すると、コールスタック上のどこで発生したかに関わらず、登録されたVEHハンドラが呼び出されます。
  • 登録: AddVectoredExceptionHandler 関数を使用して、実行時にVEHハンドラを登録します。
  • 優先順位: VEHハンドラはSEHハンドラよりも高い優先順位を持ちます。例外が発生した場合、まずVEHハンドラが呼び出され、その後にSEHハンドラが呼び出されます。
  • スタック非依存: VEHハンドラは特定のスタックフレームに紐付けられていないため、Goのようなカスタムスタック管理を行うシステムにとって、SEHよりもはるかに適しています。
  • 用途: グローバルな例外監視、デバッグ、ロギング、セキュリティ目的などに利用されます。

Goのスタック管理

Goランタイムは、効率的な並行処理を実現するために、独自のゴルーチンスタック管理モデルを採用しています。

  • 動的スタック成長: Goのゴルーチンは、OSスレッドのように固定された大きなスタックを割り当てるのではなく、小さな初期スタック(例えば2KB)で開始します。
  • コピーイングスタック: ゴルーチンがより多くのスタック領域を必要とする場合、Goランタイムは新しいより大きなメモリセグメントを割り当て、既存のスタック内容を新しい場所にコピーし、古いセグメントを解放します。このメカニズムにより、多数のゴルーチンが過剰なメモリを消費することなく並行して実行できます。
  • OSスレッドとの区別: Goのゴルーチンは、OSスレッドよりもはるかに軽量です。Goランタイムは、少数のOSスレッド上に多数のゴルーチンを多重化して実行します。
  • Windows固有の考慮事項: Windows上では、Goランタイムがスタックを直接管理し、OSが提供する個別のスタックには依存しません。これにより、Goのスタック管理とWindowsのSEHとの間に非互換性が生じることがありました。

Windows 2000サポート終了の背景

GoがWindows 2000のサポートを終了した背景には、技術的な問題とコミュニティの合意がありました。

  • VEHの非互換性: 前述の通り、Goのスタック管理とSEHの間の問題は、VEHへの移行によって解決されました。しかし、VEHはWindows XPで導入された機能であり、Windows 2000では利用できませんでした。このため、Windows 2000をサポートし続けることは、Goランタイムの安定性を犠牲にするか、あるいはWindows 2000専用の複雑な例外処理ロジックを維持する必要があることを意味しました。
  • OSのサポート終了: Microsoftは2010年にWindows 2000のサポートを公式に終了していました。これは、セキュリティアップデートやバグ修正が提供されないことを意味し、GoがこのOSをサポートし続けることの意義が薄れていました。
  • ユーザーベースの減少: Goコミュニティ内では、Windows 2000をGoの開発やデプロイに使用しているユーザーが非常に少ないという認識がありました。
  • 開発負担: 古く、サポートされていないOSとの互換性を維持することは、Go開発者にとって不釣り合いな負担となっていました。特に、その環境に特有のデバッグに関する専門知識が不足していることも問題でした。

これらの理由から、Go 1.3以降ではWindows 2000のサポートを終了し、Windows XP以降を必須とすることが決定されました。

技術的詳細

このコミットにおける技術的な変更の核心は、GoランタイムがWindows上での例外処理にSEHを完全に廃止し、VEHを導入した点にあります。

  1. SEH関連コードの削除:

    • src/pkg/runtime/cgocall.c から SEHUnwind 構造体や runtime·getseh(), runtime·setseh() の呼び出しが削除されました。これは、Cgo呼び出し中にSEHの状態を保存・復元するロジックが不要になったためです。
    • src/pkg/runtime/runtime.h から SEH および SEHUnwind 構造体の定義、そして GOOSARCH_windows_386 マクロや runtime·getseh(), runtime·setseh() の宣言が削除されました。これにより、SEHに関連するデータ構造やAPIがランタイムから完全に排除されました。
    • src/pkg/runtime/proc.c では、mstartneedm 関数内で m->seh を設定する #ifdef GOOSARCH_windows_386 ブロックが削除されました。これは、各M(マシン、OSスレッドに相当)にSEHフレームを関連付ける必要がなくなったためです。
    • src/pkg/runtime/sys_windows_386.s から、SEHフレームのセットアップと削除を行うアセンブリコード(runtime·install_exception_handlerruntime·remove_exception_handlerruntime·getsehruntime·setseh)が削除されました。
    • src/pkg/runtime/syscall_windows_test.go から、SEHの復元をテストする TestCallbackPanicLocked 内のSEH関連のチェックが削除されました。
  2. VEHの導入:

    • src/pkg/runtime/os_windows.cruntime·AddVectoredExceptionHandler の動的インポートが追加されました。これは、VEHハンドラを登録するためのWindows APIです。
    • runtime·osinit() 関数内で、runtime·stdcall(runtime·AddVectoredExceptionHandler, 2, (uintptr)1, (uintptr)runtime·sigtramp); が呼び出されるようになりました。これにより、Goのシグナルハンドラである runtime·sigtramp がVEHハンドラとして登録されます。引数 (uintptr)1 は、ハンドラが最初に追加されることを意味します。
    • src/pkg/runtime/sys_windows_386.sruntime·sigtramp 関数が、VEHハンドラとして機能するように変更されました。この関数は、Windowsから呼び出されるVEHハンドラのエントリポイントとなり、例外レコードとコンテキストポインタを受け取ります。
      • 以前のSEHベースの sigtramp は、スタック上のSEHフレームを操作していましたが、新しいVEHベースの sigtramp は、プロセス全体で例外を処理する役割を担います。
      • runtime·sighandler を呼び出し、例外の種類に応じてGoのパニック処理やクラッシュ処理を行います。
      • DBG_PRINTEXCEPTION_C (0x40010006) のようなデバッガ向け例外を無視するロジックが追加されました。
      • ハンドラが例外を処理した場合は -1 を返し、他のハンドラに渡す場合は 0 を返すというVEHの規約に従うようになりました。
  3. Windows 2000互換性の影響:

    • VEHはWindows XPで導入されたため、この変更によりGoのWindows/386版はWindows XP以降のOSを必要とするようになりました。Windows 2000はVEHをサポートしていないため、Go 1.3以降はWindows 2000では動作しなくなりました。これは、Goランタイムの安定性向上と引き換えに、古いOSのサポートを終了するというトレードオフでした。

これらの変更により、GoランタイムはWindows上での例外処理をより堅牢かつシンプルに行えるようになり、Goのスタック管理との競合による不安定性の問題が解消されました。

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

このコミットにおける主要なコード変更は、以下のファイルに集中しています。

  • src/pkg/runtime/cgocall.c: SEH関連の構造体 SEHUnwind の使用と、runtime·getseh()runtime·setseh() の呼び出しが削除されました。
  • src/pkg/runtime/os_windows.c: runtime·AddVectoredExceptionHandler の動的インポートが追加され、runtime·osinit() 関数内でVEHハンドラとして runtime·sigtramp が登録されるようになりました。また、SEH関連の SetProcessPriorityBoost の動的ロードが簡素化されました。
  • src/pkg/runtime/os_windows_386.c: runtime·sighandler 関数がVEHハンドラからの呼び出しを想定して変更され、例外処理のロジックが調整されました。
  • src/pkg/runtime/proc.c: m 構造体から seh フィールドへの参照が削除され、SEHフレームの管理ロジックが排除されました。
  • src/pkg/runtime/runtime.h: SEH および SEHUnwind 構造体の定義、GOOSARCH_windows_386 マクロ、runtime·getseh()runtime·setseh() の宣言が削除されました。
  • src/pkg/runtime/sys_windows_386.s: runtime·sigtramp アセンブリ関数がVEHハンドラとして再実装され、SEHフレームのセットアップ/削除を行うアセンブリ関数(runtime·install_exception_handlerruntime·remove_exception_handlerruntime·getsehruntime·setseh)が削除されました。
  • src/pkg/runtime/syscall_windows_test.go: SEHの復元をテストするロジックが削除されました。

具体的な変更例:

src/pkg/runtime/os_windows.c の変更 (VEHハンドラの登録)

--- a/src/pkg/runtime/os_windows.c
+++ b/src/pkg/runtime/os_windows.c
@@ -8,6 +8,7 @@
  #include "os_GOOS.h"
  #include "../../cmd/ld/textflag.h"
  
+#pragma dynimport runtime·AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
  #pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
  #pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
  #pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
@@ -86,26 +90,18 @@ getproccount(void)
  void
  runtime·osinit(void)
  {
-	void *kernel32;
-	void *SetProcessPriorityBoost;
-
  	runtime·externalthreadhandlerp = (uintptr)runtime·externalthreadhandler;
  
+	runtime·stdcall(runtime·AddVectoredExceptionHandler, 2, (uintptr)1, (uintptr)runtime·sigtramp);
  	runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
  	runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1);
  	runtime·ncpu = getproccount();
-
-	kernel32 = runtime·stdcall(runtime·LoadLibraryA, 1, "kernel32.dll");
-	if(kernel32 != nil) {
-		// Windows dynamic priority boosting assumes that a process has different types
-		// of dedicated threads -- GUI, IO, computational, etc. Go processes use
-		// equivalent threads that all do a mix of GUI, IO, computations, etc.
-		// In such context dynamic priority boosting does nothing but harm, so we turn it off.
-		SetProcessPriorityBoost = runtime·stdcall(runtime·GetProcAddress, 2, kernel32, "SetProcessPriorityBoost");
-		if(SetProcessPriorityBoost != nil)  // supported since Windows XP
-		\truntime·stdcall(SetProcessPriorityBoost, 2, (uintptr)-1, (uintptr)1);
-		runtime·GetQueuedCompletionStatusEx = runtime·stdcall(runtime·GetProcAddress, 2, kernel32, "GetQueuedCompletionStatusEx");
-	}
+	
+	// Windows dynamic priority boosting assumes that a process has different types
+	// of dedicated threads -- GUI, IO, computational, etc. Go processes use
+	// equivalent threads that all do a mix of GUI, IO, computations, etc.
+	// In such context dynamic priority boosting does nothing but harm, so we turn it off.
+	runtime·stdcall(runtime·SetProcessPriorityBoost, 2, (uintptr)-1, (uintptr)1);
  }

src/pkg/runtime/runtime.h の変更 (SEH関連構造体の削除)

--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -83,8 +83,6 @@ typedef	struct	Hchan		Hchan;
 typedef	struct	Complex64	Complex64;
 typedef	struct	Complex128	Complex128;
 typedef	struct	LibCall		LibCall;
-typedef	struct	SEH		SEH;
-typedef	struct	SEHUnwind		SEHUnwind;
 typedef	struct	WinCallbackContext	WinCallbackContext;
 typedef	struct	Timers		Timers;
 typedef	struct	Timer		Timer;
@@ -241,18 +239,6 @@ struct	LibCall
 	uintptr	err;	// error number
 };
 
-struct	SEH
-{
-	void*	prev;
-	void*	handler;
-};
-
-struct	SEHUnwind
-{
-	SEHUnwind*	link;
-	SEH*	seh;
-};
-
 // describes how to handle callback
 struct	WinCallbackContext
 {
@@ -303,15 +289,6 @@ struct	G
 	uintptr	end[];
 };
 
-// Define a symbol for windows/386 because that is the only
-// system with SEH handling, and we end up checking that
-// repeatedly.
-#ifdef GOOS_windows
-#ifdef GOARCH_386
-#define GOOSARCH_windows_386
-#endif
-#endif
-
 struct	M
 {
 	G*	g0;		// goroutine with scheduling stack
@@ -394,8 +371,6 @@ struct	M
 	int8*	notesig;
 	byte*	errstr;
 #endif
-	SEH*	seh;
-	SEHUnwind*	sehunwind;
 	uintptr	end[];
 };
 
@@ -975,16 +950,6 @@ void*	runtime·funcdata(Func*, int32);
 int32	runtime·setmaxthreads(int32);
 G*	runtime·timejump(void);
 
-// On Windows 386, we have functions for saving and restoring
-// the SEH values; elsewhere #define them away.
-#ifdef GOOSARCH_windows_386
-SEH*	runtime·getseh(void);
-void	runtime·setseh(SEH*);
-#else
-#define runtime·getseh() nil
-#define runtime·setseh(x) do{}while(0)
-#endif
-
 #pragma	varargck	argpos	runtime·printf	1
 #pragma	varargck	type	"c"	int32
 #pragma	varargck	type	"d"	int32

コアとなるコードの解説

src/pkg/runtime/os_windows.c の変更

このファイルは、GoランタイムがWindowsオペレーティングシステムと対話するための低レベルな関数を含んでいます。 変更前は、SetProcessPriorityBoost のような一部のWindows APIが動的にロードされていました。これは、それらのAPIがすべてのWindowsバージョンで利用可能ではないためです。 変更後、最も重要なのは runtime·AddVectoredExceptionHandler の動的インポートと、runtime·osinit() 関数内でのその呼び出しです。

#pragma dynimport runtime·AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"

この行は、kernel32.dll から AddVectoredExceptionHandler 関数を動的にロードするための指示です。Goランタイムは、実行時にこの関数へのポインタを取得し、それを使用してVEHハンドラを登録します。

runtime·stdcall(runtime·AddVectoredExceptionHandler, 2, (uintptr)1, (uintptr)runtime·sigtramp);

このコードは、Goランタイムの初期化時に実行されます。

  • runtime·AddVectoredExceptionHandler: 登録するVEHハンドラ関数へのポインタです。
  • 2: 関数の引数の数です。
  • (uintptr)1: FirstHandler パラメータに相当し、このハンドラがVEHチェーンの最初に追加されることを意味します。これにより、Goのハンドラが他のVEHハンドラやSEHハンドラよりも先に例外を処理する機会を得ます。
  • (uintptr)runtime·sigtramp: Goランタイムのシグナルハンドラである runtime·sigtramp 関数へのポインタです。この関数が、Windowsからの例外通知を受け取る実際のハンドラとなります。

この変更により、Goランタイムは起動時にプロセス全体にわたる例外ハンドラを登録し、Goのスタック管理に起因するSEHの問題を回避できるようになります。

src/pkg/runtime/runtime.h の変更

このヘッダーファイルは、Goランタイムの内部データ構造とAPIの定義を含んでいます。 変更前は、SEHに関連する SEH および SEHUnwind 構造体、そして GOOSARCH_windows_386 マクロが定義されていました。

-typedef	struct	SEH		SEH;
-typedef	struct	SEHUnwind		SEHUnwind;
// ...
-struct	SEH
-{
-	void*	prev;
-	void*	handler;
-};
-
-struct	SEHUnwind
-{
-	SEHUnwind*	link;
-	SEH*	seh;
-};
// ...
-#ifdef GOOS_windows
-#ifdef GOARCH_386
-#define GOOSARCH_windows_386
-#endif
-#endif
// ...
-	SEH*	seh;
-	SEHUnwind*	sehunwind;
// ...
-#ifdef GOOSARCH_windows_386
-SEH*	runtime·getseh(void);
-void	runtime·setseh(SEH*);
-#else
-#define runtime·getseh() nil
-#define runtime·setseh(x) do{}while(0)
-#endif

これらの定義は、SEHがGoランタイムの内部でどのように管理されていたかを示しています。SEH 構造体はSEHフレームのリンクリストを構成し、SEHUnwind はCgo呼び出し時のSEH状態の保存に使用されていました。GOOSARCH_windows_386 マクロは、Windows/386固有のSEHロジックを条件付きでコンパイルするために使用されていました。

これらの定義が削除されたことは、GoランタイムがSEHを完全に放棄し、その内部状態からSEHに関連するすべての概念を取り除いたことを意味します。これにより、コードベースが大幅に簡素化され、SEHに起因する複雑なバグの可能性が排除されました。

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

このアセンブリファイルは、Windows/386アーキテクチャに特化した低レベルなランタイム関数を含んでいます。特に runtime·sigtramp 関数は、例外処理のコア部分です。

変更前は、runtime·sigtramp はSEHハンドラとして機能し、スタック上のSEHフレームを操作していました。また、runtime·install_exception_handlerruntime·remove_exception_handler といったSEHフレームをセットアップ/削除する関数が存在しました。

変更後、runtime·sigtramp はVEHハンドラとして再実装されました。

TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
	MOVL	ptrs+0(FP), DI
	SUBL	$28, SP
	MOVL	0(DI), BX // ExceptionRecord*
	MOVL	4(DI), CX // Context*

	// ... (省略: 例外発生時のPCチェックロジック)

	// save callee-saved registers
	MOVL	BX, 12(SP)
	MOVL	BP, 16(SP)
	MOVL	SI, 20(SP)
	MOVL	DI, 24(SP)

	// fetch g
	get_tls(DX)
	MOVL	m(DX), AX
	CMPL	AX, $0
	JNE	2(PC)
	CALL	runtime·badsignal2(SB)
	MOVL	g(DX), DX
	// call sighandler(ExceptionRecord*, Context*, G*)
	MOVL	BX, 0(SP)
	MOVL	CX, 4(SP)
	MOVL	DX, 8(SP)
	CALL	runtime·sighandler(SB)

	// restore callee-saved registers
	MOVL	24(SP), DI
	MOVL	20(SP), SI
	MOVL	16(SP), BP
	MOVL	12(SP), BX

vehret:
	ADDL	$28, SP
	// RET 4 (return and pop 4 bytes parameters)
	BYTE $0xC2; WORD $4
	RET // unreached; make assembler happy

この新しい runtime·sigtramp は、WindowsのVEHメカニズムによって直接呼び出されます。

  • ExceptionRecord*Context* へのポインタを引数として受け取ります。これらは例外に関する詳細情報と、例外発生時のCPUレジスタの状態を含んでいます。
  • Goの g(ゴルーチン)と m(OSスレッド)のコンテキストを取得し、runtime·sighandler C関数を呼び出します。これにより、Goランタイムのより高レベルな例外処理ロジックが実行されます。
  • runtime·sighandler からの戻り値に基づいて、例外が処理されたか(-1)または他のハンドラに渡されるべきか(0)をWindowsに通知します。
  • RET 4 は、VEHハンドラの呼び出し規約に従って、スタックから4バイトの引数をポップして戻ることを意味します。

また、SEHフレームを操作していた以下の関数が完全に削除されました。

  • TEXT runtime·install_exception_handler(SB)
  • TEXT runtime·remove_exception_handler(SB)
  • TEXT runtime·getseh(SB)
  • TEXT runtime·setseh(SB)

これらのアセンブリ関数の削除は、SEHベースの例外処理メカニズムがGoランタイムから完全に排除されたことを明確に示しています。

関連リンク

参考にした情報源リンク