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

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

このコミットは、Go言語のリンカ(cmd/5l, cmd/6l, cmd/8l)におけるセグメンテーション違反(segfault)のバグを修正するものです。具体的には、重複する定義(特に型ハッシュ関連の関数)を読み込む際に、リンカがLOCALS(ローカル変数情報)やTYPE(型情報)を誤って処理しようとすることで発生する問題に対処しています。

コミット

commit d815a147187c0237a81e84e39035f6275b3fee42
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Mon Mar 25 22:09:55 2013 +0100

    cmd/5l, cmd/6l, cmd/8l: fix segfault on reading LOCALS for a duplicate definition.
    
    Fixes #5105.
    
    R=golang-dev, dave, daniel.morsing, rsc
    CC=golang-dev
    https://golang.org/cl/7965043

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

https://github.com/golang/go/commit/d815a147187c0237a81e84e39035f6275b3fee42

元コミット内容

diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index d38da204a3..f5128c6780 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -608,11 +608,15 @@ loop:
 		break;
 
 	case ALOCALS:
+		if(skip)
+			goto casedef;
 		cursym->locals = p->to.offset;
 		pc++;
 		break;
 
 	case ATYPE:
+		if(skip)
+			goto casedef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 3775df9de5..ab8b22e231 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -597,11 +597,15 @@ loop:
 		goto loop;
 
 	case ALOCALS:
+		if(skip)
+			goto casdef;
 		cursym->locals = p->to.offset;
 		pc++;
 		goto loop;
 	
 	case ATYPE:
+		if(skip)
+			goto casdef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 306e288a35..fda96d09ca 100644
--- a/src/cmd/8l/obj.c
+++ b/test/fixedbugs/issue5105.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5105: linker segfaults on duplicate definition
+// of a type..hash.* function.
+
+package ignored

変更の背景

このコミットは、Go言語のリンカが特定の状況下でセグメンテーション違反(segfault)を起こすバグ(Issue 5105)を修正するために行われました。このバグは、リンカがオブジェクトファイルを処理する際に、既に定義されているシンボル(特に型ハッシュに関連する関数)のLOCALS(ローカル変数情報)やTYPE(型情報)を再度読み込もうとしたときに発生していました。

Go言語のビルドプロセスでは、コンパイラがGoのソースコードをオブジェクトファイルに変換し、その後リンカがこれらのオブジェクトファイルを結合して実行可能ファイルを生成します。この結合プロセス中に、複数のソースファイルやパッケージが同じシンボル(例えば、同じ構造体やインターフェースの型情報)を参照したり、内部的に同じハッシュ値を持つ型を生成したりすることがあります。リンカはこれらの重複を適切に処理し、最終的なバイナリには一意の定義のみを含める必要があります。

しかし、このバグが存在するバージョンでは、リンカが既に処理済みであるべき重複定義のLOCALSTYPEセクションを再度処理しようとすると、内部的な状態が不正になり、メモリへの不正アクセスが発生し、結果としてセグメンテーション違反を引き起こしていました。特に、type..hash.*という形式の関数(Goの型システムが内部的に型の一意性を保証するために使用するハッシュ関数)の重複定義が問題を引き起こすことが、テストケースから示唆されています。

前提知識の解説

  • Go言語のビルドプロセス: Goのソースコードは、まずgo buildコマンドによってコンパイルされ、オブジェクトファイル(.oファイル)が生成されます。その後、これらのオブジェクトファイルとGoランタイムライブラリがリンカによって結合され、最終的な実行可能バイナリが作成されます。
  • リンカ (Linker): リンカは、コンパイラによって生成された複数のオブジェクトファイルやライブラリを結合し、単一の実行可能ファイルまたはライブラリを生成するプログラムです。シンボル解決(未解決の参照を実際の定義に結びつける)や、メモリレイアウトの決定などの重要な役割を担います。
  • cmd/5l, cmd/6l, cmd/8l: これらはGo言語のツールチェインに含まれるリンカの実行ファイル名です。
    • 5l: ARMアーキテクチャ向けのリンカ
    • 6l: AMD64 (x86-64) アーキテクチャ向けのリンカ
    • 8l: x86 (32-bit) アーキテクチャ向けのリンカ これらのリンカは、それぞれ異なるアーキテクチャのオブジェクトファイルを処理しますが、基本的なロジックは共通しています。
  • オブジェクトファイルフォーマット: コンパイラが生成するオブジェクトファイルには、コード(テキストセクション)、データ(データセクション)、シンボルテーブル、リロケーション情報など、様々な情報が含まれています。リンカはこれらのセクションを解析し、結合します。
  • シンボル: プログラム内の関数、変数、型など、名前を持つ実体を指します。リンカはシンボル名を使って、異なるオブジェクトファイル間の参照を解決します。
  • ALOCALSATYPE: これらはGoのオブジェクトファイルフォーマット(またはリンカが内部的に使用する中間表現)における特定のセクションまたは命令の種類を指すものと考えられます。
    • ALOCALS: ローカル変数に関する情報(オフセット、サイズなど)を記述するセクション。
    • ATYPE: 型に関する情報(型の定義、ハッシュ値など)を記述するセクション。
  • セグメンテーション違反 (Segmentation Fault / Segfault): プログラムが、アクセスを許可されていないメモリ領域にアクセスしようとしたときに発生するエラーです。これは通常、ポインタの不正な使用、配列の範囲外アクセス、または解放済みメモリへのアクセスなど、プログラミング上のバグによって引き起こされます。

技術的詳細

このバグは、リンカがオブジェクトファイルをパースする際の内部ループで発生していました。リンカはオブジェクトファイル内の各セクションやシンボルを順次読み込み、処理していきます。この処理中に、ALOCALSATYPEといった特定の種類の情報に遭遇した場合、リンカはそれらを現在のシンボル(cursym)に関連付けたり、プログラムカウンタ(pc)を進めたりする処理を行います。

問題は、skipというフラグが真である場合、つまりリンカが既にこのシンボルを処理済みであるか、または何らかの理由でこの情報をスキップすべきであると判断した場合に発生しました。本来であれば、重複する定義に対しては、その情報を再度処理するのではなく、単にスキップするか、既に存在する定義を再利用するべきです。しかし、バグのあるバージョンでは、skipが真であるにもかかわらず、cursym->locals = p->to.offset;のような代入操作やpc++のようなポインタ操作が実行されていました。

この不正な操作が、cursymが指すメモリ領域が不正であったり、p->to.offsetが有効なオフセットでなかったりした場合に、メモリ破壊や不正なメモリアクセスを引き起こし、最終的にセグメンテーション違反につながっていました。特に、type..hash.*関数のような内部的なシンボルが重複して定義された場合に、この問題が顕在化したと考えられます。

修正は、ALOCALSATYPEの処理ブロックの冒頭にif(skip) goto casedef;(またはcasdef)という条件分岐を追加することによって行われました。これにより、skipフラグが真である場合には、これらの情報に対する具体的な処理(cursym->locals = p->to.offset;など)を完全にスキップし、代わりにcasedef(またはcasdef)というラベルにジャンプします。このcasedefは、おそらくリンカのオブジェクトファイルパースループにおける、現在の命令をスキップして次の命令に進むための共通の処理ブロックであると推測されます。これにより、重複定義に対する不必要な処理が回避され、セグメンテーション違反が防止されます。

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

変更は、Goリンカの主要なバックエンドであるsrc/cmd/5l/obj.csrc/cmd/6l/obj.csrc/cmd/8l/obj.cの3つのファイルにわたっています。これらのファイルは、それぞれ異なるCPUアーキテクチャ(ARM, AMD64, x86)向けのオブジェクトファイル処理ロジックを実装しています。

各ファイルにおいて、以下の2つのcaseブロックに修正が加えられています。

  1. case ALOCALS:
    • ローカル変数情報に関連する処理ブロック。
    • 変更前: cursym->locals = p->to.offset; の行が直接実行されていた。
    • 変更後: if(skip) goto casedef; (または casdef;) が追加され、skipが真の場合はこの行がスキップされるようになった。
  2. case ATYPE:
    • 型情報に関連する処理ブロック。
    • 変更前: pc++; の行が直接実行されていた。
    • 変更後: if(skip) goto casedef; (または casdef;) が追加され、skipが真の場合はこの行がスキップされるようになった。

これらの変更は、リンカがオブジェクトファイル内の命令をループで処理するloop:ラベル内のswitch文の中にあります。

コアとなるコードの解説

Goリンカのobj.cファイル群は、Goコンパイラが出力するオブジェクトファイル(*.o)を読み込み、解析し、最終的な実行可能バイナリにリンクするための中心的なロジックを含んでいます。これらのファイルはC言語で書かれており、Goのツールチェインの低レベルな部分を構成しています。

コードスニペットに見られるloop:switch文、case ALOCALS:case ATYPE:は、リンカがオブジェクトファイル内の各「命令」または「レコード」を順次処理していく典型的なパターンを示しています。

  • loop:: これは、オブジェクトファイル内の命令ストリームを反復処理するための無限ループの開始点を示しています。
  • switch: p->as(おそらく現在の命令の種類を示すフィールド)の値に基づいて、異なる処理パスに分岐します。
  • case ALOCALS::
    • ALOCALSは、オブジェクトファイル内のローカル変数に関するメタデータを示す命令コードです。
    • if(skip) goto casedef;: この行が追加された修正の核心です。skip変数は、現在のシンボルが既に処理済みであるか、または何らかの理由でこの情報を無視すべきであることを示すフラグです。もしskipが真であれば、リンカはcasedef(またはcasdef)というラベルにジャンプし、ALOCALSに関する具体的な処理(cursym->locals = p->to.offset;)をスキップします。
    • cursym->locals = p->to.offset;: cursymは現在処理中のシンボルへのポインタであり、localsはそのシンボルに関連付けられたローカル変数情報のオフセットを格納するフィールドです。p->to.offsetは、オブジェクトファイル内の現在の命令が指すオフセット値です。この行は、現在のシンボルにローカル変数情報のオフセットを関連付けています。
    • pc++;: プログラムカウンタを進め、次の命令を指します。
  • case ATYPE::
    • ATYPEは、オブジェクトファイル内の型に関するメタデータを示す命令コードです。
    • if(skip) goto casedef;: ALOCALSと同様に、skipが真であれば、型情報に関する具体的な処理をスキップし、casedefにジャンプします。
    • pc++;: プログラムカウンタを進め、次の命令を指します。
    • goto loop;: 次の命令を処理するためにループの先頭に戻ります。

この修正の目的は、リンカが重複するシンボル定義(特にtype..hash.*のような内部的な型ハッシュ関数)に遭遇した際に、既に処理済みの情報に対して再度cursym->localscursym->typeのようなフィールドを上書きしようとすることを防ぐことです。このような不正な上書きは、cursymが指すメモリ領域が不正な状態にある場合や、p->to.offsetが期待される値でない場合に、メモリ破壊やセグメンテーション違反を引き起こす可能性がありました。skipフラグによる条件付きジャンプは、この危険な再処理を回避し、リンカの堅牢性を向上させます。

関連リンク

  • Go Issue 5105: https://github.com/golang/go/issues/5105
    • このコミットが修正したバグの公式なIssueトラッカーページ。詳細な議論や再現手順が記載されている可能性があります。
  • Go Code Review 7965043: https://golang.org/cl/7965043
    • この変更がGoのコードレビューシステム(Gerrit)でレビューされた際のページ。レビューコメントや変更の経緯が確認できます。

参考にした情報源リンク

  • Go言語の公式ドキュメント (Go Programming Language Specification, Go Command Documentationなど)
  • Go言語のソースコード(特にsrc/cmd/以下のリンカ関連のコード)
  • Go言語のIssueトラッカー(GitHub Issues)
  • Go言語のコードレビューシステム(Gerrit)
  • 一般的なリンカの動作原理に関する情報(コンピュータサイエンスの教科書やオンラインリソース)
  • セグメンテーション違反に関する一般的な情報(オペレーティングシステム、メモリ管理に関するリソース)
  • C言語のgoto文とラベルに関する情報(C言語の仕様書やチュートリアル)
  • オブジェクトファイルフォーマットに関する情報(ELF, Mach-O, PEなどの仕様)
  • Go言語の型システムと内部的な型ハッシュに関する情報(Goのコンパイラやランタイムの設計に関するドキュメント)

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

このコミットは、Go言語のリンカ(cmd/5l, cmd/6l, cmd/8l)におけるセグメンテーション違反(segfault)のバグを修正するものです。具体的には、重複する定義(特に型ハッシュ関連の関数)を読み込む際に、リンカがLOCALS(ローカル変数情報)やTYPE(型情報)を誤って処理しようとすることで発生する問題に対処しています。

コミット

commit d815a147187c0237a81e84e39035f6275b3fee42
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Mon Mar 25 22:09:55 2013 +0100

    cmd/5l, cmd/6l, cmd/8l: fix segfault on reading LOCALS for a duplicate definition.
    
    Fixes #5105.
    
    R=golang-dev, dave, daniel.morsing, rsc
    CC=golang-dev
    https://golang.org/cl/7965043

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

https://github.com/golang/go/commit/d815a147187c0237a81e84e39035f6275b3fee42

元コミット内容

diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index d38da204a3..f5128c6780 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -608,11 +608,15 @@ loop:
 		break;
 
 	case ALOCALS:
+		if(skip)
+			goto casedef;
 		cursym->locals = p->to.offset;
 		pc++;
 		break;
 
 	case ATYPE:
+		if(skip)
+			goto casedef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 3775df9de5..ab8b22e231 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -597,11 +597,15 @@ loop:
 		goto loop;
 
 	case ALOCALS:
+		if(skip)
+			goto casdef;
 		cursym->locals = p->to.offset;
 		pc++;
 		goto loop;
 	
 	case ATYPE:
+		if(skip)
+			goto casdef;
 		pc++;
 		goto loop;
 
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 306e288a35..fda96d09ca 100644
--- a/src/cmd/8l/obj.c
+++ b/test/fixedbugs/issue5105.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5105: linker segfaults on duplicate definition
+// of a type..hash.* function.
+
+package ignored

変更の背景

このコミットは、Go言語のリンカが特定の状況下でセグメンテーション違反(segfault)を起こすバグ(Issue 5105)を修正するために行われました。このバグは、リンカがオブジェクトファイルを処理する際に、既に定義されているシンボル(特に型ハッシュに関連する関数)のLOCALS(ローカル変数情報)やTYPE(型情報)を再度読み込もうとしたときに発生していました。

Go言語のビルドプロセスでは、コンパイラがGoのソースコードをオブジェクトファイルに変換し、その後リンカがこれらのオブジェクトファイルを結合して実行可能ファイルを生成します。この結合プロセス中に、複数のソースファイルやパッケージが同じシンボル(例えば、同じ構造体やインターフェースの型情報)を参照したり、内部的に同じハッシュ値を持つ型を生成したりすることがあります。リンカはこれらの重複を適切に処理し、最終的なバイナリには一意の定義のみを含める必要があります。

しかし、このバグが存在するバージョンでは、リンカが既に処理済みであるべき重複定義のLOCALSTYPEセクションを再度処理しようとすると、内部的な状態が不正になり、メモリへの不正アクセスが発生し、結果としてセグメンテーション違反を引き起こしていました。特に、type..hash.*という形式の関数(Goの型システムが内部的に型の一意性を保証するために使用するハッシュ関数)の重複定義が問題を引き起こすことが、テストケースから示唆されています。

前提知識の解説

  • Go言語のビルドプロセス: Goのソースコードは、まずgo buildコマンドによってコンパイルされ、オブジェクトファイル(.oファイル)が生成されます。その後、これらのオブジェクトファイルとGoランタイムライブラリがリンカによって結合され、最終的な実行可能バイナリが作成されます。
  • リンカ (Linker): リンカは、コンパイラによって生成された複数のオブジェクトファイルやライブラリを結合し、単一の実行可能ファイルまたはライブラリを生成するプログラムです。シンボル解決(未解決の参照を実際の定義に結びつける)や、メモリレイアウトの決定などの重要な役割を担います。
  • cmd/5l, cmd/6l, cmd/8l: これらはGo言語のツールチェインに含まれるリンカの実行ファイル名です。
    • 5l: ARMアーキテクチャ向けのリンカ
    • 6l: AMD64 (x86-64) アーキテクチャ向けのリンカ
    • 8l: x86 (32-bit) アーキテクチャ向けのリンカ これらのリンカは、それぞれ異なるアーキテクチャのオブジェクトファイルを処理しますが、基本的なロジックは共通しています。
  • オブジェクトファイルフォーマット: コンパイラが生成するオブジェクトファイルには、コード(テキストセクション)、データ(データセクション)、シンボルテーブル、リロケーション情報など、様々な情報が含まれています。リンカはこれらのセクションを解析し、結合します。
  • シンボル: プログラム内の関数、変数、型など、名前を持つ実体を指します。リンカはシンボル名を使って、異なるオブジェクトファイル間の参照を解決します。
  • ALOCALSATYPE: これらはGoのオブジェクトファイルフォーマット(またはリンカが内部的に使用する中間表現)における特定のセクションまたは命令の種類を指すものと考えられます。
    • ALOCALS: ローカル変数に関する情報(オフセット、サイズなど)を記述するセクション。Goのコンパイラが生成する擬似アセンブリ言語において、ローカル変数の管理に関連する内部的な概念です。FP (Frame Pointer) を用いたローカル変数のアドレス指定と関連しています。
    • ATYPE: 型に関する情報(型の定義、ハッシュ値など)を記述するセクション。Goの擬似アセンブリおよびリンカの内部で、型情報の表現と処理に使用される抽象的な概念です。リンカはtype:プレフィックスを持つ型シンボルを扱います。
  • セグメンテーション違反 (Segmentation Fault / Segfault): プログラムが、アクセスを許可されていないメモリ領域にアクセスしようとしたときに発生するエラーです。これは通常、ポインタの不正な使用、配列の範囲外アクセス、または解放済みメモリへのアクセスなど、プログラミング上のバグによって引き起こされます。

技術的詳細

このバグは、リンカがオブジェクトファイルをパースする際の内部ループで発生していました。リンカはオブジェクトファイル内の各セクションやシンボルを順次読み込み、処理していきます。この処理中に、ALOCALSATYPEといった特定の種類の情報に遭遇した場合、リンカはそれらを現在のシンボル(cursym)に関連付けたり、プログラムカウンタ(pc)を進めたりする処理を行います。

問題は、skipというフラグが真である場合、つまりリンカが既にこのシンボルを処理済みであるか、または何らかの理由でこの情報をスキップすべきであると判断した場合に発生しました。本来であれば、重複する定義に対しては、その情報を再度処理するのではなく、単にスキップするか、既に存在する定義を再利用するべきです。しかし、バグのあるバージョンでは、skipが真であるにもかかわらず、cursym->locals = p->to.offset;のような代入操作やpc++のようなポインタ操作が実行されていました。

この不正な操作が、cursymが指すメモリ領域が不正であったり、p->to.offsetが有効なオフセットでなかったりした場合に、メモリ破壊や不正なメモリアクセスを引き起こし、最終的にセグメンテーション違反につながっていました。特に、type..hash.*関数のような内部的なシンボルが重複して定義された場合に、この問題が顕在化したと考えられます。

修正は、ALOCALSATYPEの処理ブロックの冒頭にif(skip) goto casedef;(またはcasdef)という条件分岐を追加することによって行われました。これにより、skipフラグが真である場合には、これらの情報に対する具体的な処理(cursym->locals = p->to.offset;など)を完全にスキップし、代わりにcasedef(またはcasdef)というラベルにジャンプします。このcasedefは、おそらくリンカのオブジェクトファイルパースループにおける、現在の命令をスキップして次の命令に進むための共通の処理ブロックであると推測されます。これにより、重複定義に対する不必要な処理が回避され、セグメンテーション違反が防止されます。

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

変更は、Goリンカの主要なバックエンドであるsrc/cmd/5l/obj.csrc/cmd/6l/obj.csrc/cmd/8l/obj.cの3つのファイルにわたっています。これらのファイルは、それぞれ異なるCPUアーキテクチャ(ARM, AMD64, x86)向けのオブジェクトファイル処理ロジックを実装しています。

各ファイルにおいて、以下の2つのcaseブロックに修正が加えられています。

  1. case ALOCALS:
    • ローカル変数情報に関連する処理ブロック。
    • 変更前: cursym->locals = p->to.offset; の行が直接実行されていた。
    • 変更後: if(skip) goto casedef; (または casdef;) が追加され、skipが真の場合はこの行がスキップされるようになった。
  2. case ATYPE:
    • 型情報に関連する処理ブロック。
    • 変更前: pc++; の行が直接実行されていた。
    • 変更後: if(skip) goto casedef; (または casdef;) が追加され、skipが真の場合はこの行がスキップされるようになった。

これらの変更は、リンカがオブジェクトファイル内の命令をループで処理するloop:ラベル内のswitch文の中にあります。

コアとなるコードの解説

Goリンカのobj.cファイル群は、Goコンパイラが出力するオブジェクトファイル(*.o)を読み込み、解析し、最終的な実行可能バイナリにリンクするための中心的なロジックを含んでいます。これらのファイルはC言語で書かれており、Goのツールチェインの低レベルな部分を構成しています。

コードスニペットに見られるloop:switch文、case ALOCALS:case ATYPE:は、リンカがオブジェクトファイル内の各「命令」または「レコード」を順次処理していく典型的なパターンを示しています。

  • loop:: これは、オブジェクトファイル内の命令ストリームを反復処理するための無限ループの開始点を示しています。
  • switch: p->as(おそらく現在の命令の種類を示すフィールド)の値に基づいて、異なる処理パスに分岐します。
  • case ALOCALS::
    • ALOCALSは、オブジェクトファイル内のローカル変数に関するメタデータを示す命令コードです。
    • if(skip) goto casedef;: この行が追加された修正の核心です。skip変数は、現在のシンボルが既に処理済みであるか、または何らかの理由でこの情報を無視すべきであることを示すフラグです。もしskipが真であれば、リンカはcasedef(またはcasdef)というラベルにジャンプし、ALOCALSに関する具体的な処理(cursym->locals = p->to.offset;)をスキップします。
    • cursym->locals = p->to.offset;: cursymは現在処理中のシンボルへのポインタであり、localsはそのシンボルに関連付けられたローカル変数情報のオフセットを格納するフィールドです。p->to.offsetは、オブジェクトファイル内の現在の命令が指すオフセット値です。この行は、現在のシンボルにローカル変数情報のオフセットを関連付けています。
    • pc++;: プログラムカウンタを進め、次の命令を指します。
  • case ATYPE::
    • ATYPEは、オブジェクトファイル内の型に関するメタデータを示す命令コードです。
    • if(skip) goto casedef;: ALOCALSと同様に、skipが真であれば、型情報に関する具体的な処理をスキップし、casedefにジャンプします。
    • pc++;: プログラムカウンタを進め、次の命令を指します。
    • goto loop;: 次の命令を処理するためにループの先頭に戻ります。

この修正の目的は、リンカが重複するシンボル定義(特にtype..hash.*のような内部的な型ハッシュ関数)に遭遇した際に、既に処理済みの情報に対して再度cursym->localscursym->typeのようなフィールドを上書きしようとすることを防ぐことです。このような不正な上書きは、cursymが指すメモリ領域が不正な状態にある場合や、p->to.offsetが期待される値でない場合に、メモリ破壊やセグメンテーション違反を引き起こす可能性がありました。skipフラグによる条件付きジャンプは、この危険な再処理を回避し、リンカの堅牢性を向上させます。

関連リンク

  • Go Issue 5105: https://github.com/golang/go/issues/5105
    • このコミットが修正したバグの公式なIssueトラッカーページ。詳細な議論や再現手順が記載されている可能性があります。
  • Go Code Review 7965043: https://golang.org/cl/7965043
    • この変更がGoのコードレビューシステム(Gerrit)でレビューされた際のページ。レビューコメントや変更の経緯が確認できます。

参考にした情報源リンク

  • Go言語の公式ドキュメント (Go Programming Language Specification, Go Command Documentationなど)
  • Go言語のソースコード(特にsrc/cmd/以下のリンカ関連のコード)
  • Go言語のIssueトラッカー(GitHub Issues)
  • Go言語のコードレビューシステム(Gerrit)
  • 一般的なリンカの動作原理に関する情報(コンピュータサイエンスの教科書やオンラインリソース)
  • セグメンテーション違反に関する一般的な情報(オペレーティングシステム、メモリ管理に関するリソース)
  • C言語のgoto文とラベルに関する情報(C言語の仕様書やチュートリアル)
  • オブジェクトファイルフォーマットに関する情報(ELF, Mach-O, PEなどの仕様)
  • Go言語の型システムと内部的な型ハッシュに関する情報(Goのコンパイラやランタイムの設計に関するドキュメント)
  • Web検索: "Go linker ALOCALS ATYPE"