[インデックス 18846] ファイルの概要
このコミットは、Go言語のリンカ (cmd/ld
) において、デバッガ acid
がスタックトレースを生成できるようにするための改善を施すものです。具体的には、Plan 9バイナリに対して .frame
シンボルを生成することで、acid
がスタックアンワインド(スタックの巻き戻し)を行う際の能力を向上させます。
コミット
commit b67979320a9214b7d1b75bbd2d11ea5a1aa40323
Author: Anthony Martin <ality@pbrane.org>
Date: Wed Mar 12 18:10:31 2014 -0700
cmd/ld: give acid a fighting chance at unwinding the stack
Acid can't produce a stack trace without .frame symbols.
Of course, it can only unwind through linear stacks but
this is still better than nothing. (I wrote an acid func
to do the full unwind a long time ago but lost it and
haven't worked up the courage to write it again).
Note that these will only be present in the native symbol
table for Plan 9 binaries.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/72450045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/b67979320a9214b7d1b75bbd2d11ea5a1aa40323
元コミット内容
cmd/ld: give acid a fighting chance at unwinding the stack
Acid can't produce a stack trace without .frame symbols.
Of course, it can only unwind through linear stacks but
this is still better than nothing. (I wrote an acid func
to do the full unwind a long time ago but lost it and
haven't worked up the courage to write it again).
Note that these will only be present in the native symbol
table for Plan 9 binaries.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/72450045
変更の背景
この変更の背景には、Go言語のデバッガである acid
が、スタックトレースを正確に生成するために必要な情報が不足していたという問題があります。特に、acid
はスタックフレームの境界を特定するために .frame
シンボルを必要としますが、Goのリンカはこれまでこれらのシンボルを生成していませんでした。
コミットメッセージによると、acid
は .frame
シンボルなしではスタックトレースを生成できませんでした。これはデバッグ作業において大きな制約となります。コミットの作者であるAnthony Martin氏は、以前に acid
で完全なスタックアンワインドを行う関数を作成した経験があるものの、それを失ってしまい、再作成する意欲が湧かなかったと述べています。
このコミットは、完全なスタックアンワインドには至らないものの、少なくとも線形スタック(単純な関数呼び出しの連鎖)のアンワインドを可能にすることで、acid
のデバッグ能力を向上させることを目的としています。これにより、デバッガがより有用な情報を提供できるようになり、開発者がGoプログラムの実行時の問題を診断するのに役立ちます。
また、この変更が特にPlan 9バイナリに限定されている点も重要です。Go言語は元々Plan 9オペレーティングシステムの影響を強く受けており、そのツールチェインの一部はPlan 9の設計思想を継承しています。このコミットは、Plan 9環境におけるGoのデバッグ体験を改善するための具体的なステップと言えます。
前提知識の解説
このコミットを理解するためには、以下の前提知識が必要です。
1. Go言語のリンカ (cmd/ld
)
Go言語のビルドプロセスにおいて、リンカ (cmd/ld
) は非常に重要な役割を担います。コンパイラによって生成されたオブジェクトファイル(.o
ファイル)を結合し、実行可能なバイナリファイルを生成するのがリンカの主な仕事です。この過程で、リンカはシンボル解決、アドレスの再配置、セクションの結合などを行います。
2. デバッガとスタックトレース
デバッガは、プログラムの実行を制御し、その内部状態を検査するためのツールです。スタックトレースは、プログラムがクラッシュしたり、特定のポイントに到達したりしたときに、現在実行中の関数の呼び出し履歴(コールスタック)を表示するものです。これにより、どの関数がどの関数を呼び出し、最終的に現在の実行ポイントに至ったのかを把握でき、問題の原因特定に役立ちます。
3. スタックアンワインド
スタックアンワインド(Stack Unwinding)とは、デバッガがコールスタックを逆方向に辿り、各関数の呼び出し元やローカル変数の状態などを特定するプロセスです。これには、各スタックフレームの開始位置とサイズ、およびレジスタの状態などの情報が必要です。
4. スタックフレーム
関数が呼び出されるたびに、その関数の実行に必要な情報(引数、ローカル変数、戻りアドレスなど)がスタック上に確保されます。この領域を「スタックフレーム」と呼びます。スタックフレームは、関数の呼び出しと戻りによって動的に生成・破棄されます。
5. .frame
シンボル
.frame
シンボルは、デバッガがスタックフレームの境界を特定するために使用するメタデータの一種です。これらのシンボルは、通常、コンパイラやリンカによって生成され、実行可能ファイルのシンボルテーブルに格納されます。デバッガはこれらのシンボルを参照して、スタックアンワインドを正確に行います。
6. acid
デバッガ
acid
は、Plan 9オペレーティングシステムで開発されたデバッガです。Go言語はPlan 9の設計思想を強く継承しているため、初期のGo開発では acid
がデバッグツールとして使用されることがありました。acid
は、そのシンプルさと強力なスクリプト機能で知られています。
7. Plan 9バイナリ
Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Go言語の設計にはPlan 9の哲学が色濃く反映されており、Goのツールチェインの一部はPlan 9の慣習に従っています。Plan 9バイナリは、Plan 9の実行可能ファイル形式に準拠したバイナリを指します。
8. シンボルテーブル
シンボルテーブルは、プログラム内のシンボル(関数名、変数名など)とそのアドレスや型などの情報をマッピングしたデータ構造です。リンカによって生成され、実行可能ファイル内に埋め込まれるか、別途デバッグ情報として提供されます。デバッガはシンボルテーブルを利用して、人間が読める形式でプログラムの状態を表示します。
技術的詳細
このコミットの技術的な核心は、Goリンカ (cmd/ld
) がPlan 9バイナリを生成する際に、各関数のスタックフレームに関する情報を .frame
シンボルとしてシンボルテーブルに追加する点にあります。
具体的には、src/cmd/ld/lib.c
ファイルの genasmsym
関数に以下の3行が追加されています。
// NOTE(ality): acid can't produce a stack trace without .frame symbols
put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
このコードは、各テキストセクション(関数コード)のシンボルを処理するループ内で実行されます。
put
関数は、シンボルテーブルにエントリを追加するための関数です。nil
は、このシンボルが特定の関数に関連付けられていないことを示唆している可能性があります(あるいは、put
関数の最初の引数がシンボル構造体へのポインタであり、ここでは不要なためnil
が渡されている可能性もあります)。".frame"
は、追加されるシンボルの名前です。デバッガacid
がこの名前のシンボルを探してスタックフレーム情報を取得します。'm'
は、シンボルの型を示します。これはおそらく、特定のメタデータやデバッグ情報を示す型コードです。s->locals+PtrSize
は、この.frame
シンボルが指すアドレスを示しています。s->locals
は関数のローカル変数のサイズを示し、PtrSize
はポインタのサイズ(通常は4バイトまたは8バイト)です。これは、スタックフレーム内の特定のオフセット、おそらくローカル変数の開始位置やフレームポインタの次の位置など、スタックフレームの境界を示す重要なポイントを指していると考えられます。- 残りの
0, 0, 0
は、シンボルのサイズ、バージョン、および型情報(Goの型システムにおける型)を示しますが、.frame
シンボルにとってはこれらの値は重要ではないか、あるいはデフォルト値が使用されていることを意味します。
この変更により、Plan 9バイナリのシンボルテーブルには、各関数のスタックフレームに関する .frame
シンボルが追加されます。acid
デバッガは、この .frame
シンボルを読み取ることで、スタックフレームの開始位置を特定し、それに基づいてスタックアンワインドを実行できるようになります。
コミットメッセージにある「Of course, it can only unwind through linear stacks but this is still better than nothing.」という記述は、この .frame
シンボルが提供する情報だけでは、最適化されたコードや非線形なスタック構造(例えば、コルーチンやゴルーチンが複雑に絡み合う場合)における完全なスタックアンワインドは難しいことを示唆しています。しかし、少なくとも単純な関数呼び出しの連鎖においては、acid
がスタックトレースを生成できるようになるため、デバッグの有用性が大幅に向上します。
この変更は、Goのデバッグツールチェインの進化における一歩であり、特にPlan 9環境でのデバッグ体験を改善することを目的としています。
コアとなるコードの変更箇所
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index e0fcd15da5..20383de1e1 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -1341,6 +1341,9 @@ genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*))\
for(s = ctxt->textp; s != nil; s = s->next) {
put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
+ // NOTE(ality): acid can't produce a stack trace without .frame symbols
+ put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
+
for(a=s->autom; a; a=a->link) {
// Emit a or p according to actual offset, even if label is wrong.
// This avoids negative offsets, which cannot be encoded.
コアとなるコードの解説
変更は src/cmd/ld/lib.c
ファイルの genasmsym
関数内で行われています。
genasmsym
関数は、アセンブリシンボルを生成し、シンボルテーブルに追加するための関数です。この関数は、Goプログラム内の各テキストセクション(つまり、各関数)をループ処理し、その関数に関するシンボル情報(関数名、アドレス、サイズなど)を put
関数を使ってシンボルテーブルに書き込みます。
追加された3行は、このループの内側にあります。
// NOTE(ality): acid can't produce a stack trace without .frame symbols
put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
-
// NOTE(ality): acid can't produce a stack trace without .frame symbols
これはコメントであり、このコードが追加された理由を明確に説明しています。acid
デバッガがスタックトレースを生成するためには.frame
シンボルが必要であるという、この変更の直接的な動機を示しています。 -
put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
この行が、実際に.frame
シンボルをシンボルテーブルに追加する処理です。put
: シンボルテーブルにエントリを追加する関数ポインタ。nil
: シンボルが特定のLSym
構造体に関連付けられていないことを示します。これは、.frame
シンボルが関数自体ではなく、そのスタックフレームのメタデータとして扱われるためと考えられます。".frame"
: シンボルの名前。acid
デバッガがこの名前を認識し、スタックフレーム情報として利用します。'm'
: シンボルの型。これは、デバッグ情報やメタデータを示すカスタムシンボル型である可能性があります。s->locals+PtrSize
: シンボルの値(アドレス)。s->locals
は現在の関数のローカル変数の合計サイズを示します。PtrSize
はポインタのサイズ(通常4バイトまたは8バイト)です。この計算は、スタックフレーム内の特定のオフセット、おそらくローカル変数の開始位置やフレームポインタの次の位置など、スタックフレームの境界を示す重要なポイントを指していると考えられます。デバッガはこのアドレスを基にスタックフレームの構造を推測します。0, 0, 0
: 残りの引数は、シンボルのサイズ、バージョン、およびGoの型情報ですが、.frame
シンボルにとってはこれらの値は通常ゼロで十分です。
この変更により、GoのリンカはPlan 9バイナリを生成する際に、各関数のスタックフレームに関する .frame
シンボルをシンボルテーブルに埋め込むようになります。これにより、acid
デバッガはこれらのシンボルを利用して、より正確なスタックアンワインドとスタックトレースの生成が可能になります。
関連リンク
- Go言語のリンカ (
cmd/ld
) のソースコード: https://github.com/golang/go/tree/master/src/cmd/ld - Plan 9 from Bell Labs: https://9p.io/plan9/
- Go言語のデバッグに関するドキュメント(一般的な情報): https://go.dev/doc/gdb (これはGDBに関するものですが、デバッグの概念は共通です)
参考にした情報源リンク
- Go言語のコミット履歴: https://github.com/golang/go/commits/master
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
- Plan 9のデバッガ
acid
に関する情報(一般的な概念): https://9p.io/sys/doc/acid/intro.html - スタックフレームとスタックアンワインドに関する一般的なコンピュータサイエンスの概念。
- シンボルテーブルに関する一般的な情報。
- Go言語のビルドプロセスに関する一般的な情報。
PtrSize
の定義に関するGoのソースコード(例:src/cmd/internal/obj/go.go
など)。LSym
構造体やput
関数の具体的な定義は、Goのリンカのソースコード内で確認できます。
[インデックス 18846] ファイルの概要
このコミットは、Go言語のリンカ (cmd/ld
) において、デバッガ acid
がスタックトレースを生成できるようにするための改善を施すものです。具体的には、Plan 9バイナリに対して .frame
シンボルを生成することで、acid
がスタックアンワインド(スタックの巻き戻し)を行う際の能力を向上させます。
コミット
commit b67979320a9214b7d1b75bbd2d11ea5a1aa40323
Author: Anthony Martin <ality@pbrane.org>
Date: Wed Mar 12 18:10:31 2014 -0700
cmd/ld: give acid a fighting chance at unwinding the stack
Acid can't produce a stack trace without .frame symbols.
Of course, it can only unwind through linear stacks but
this is still better than nothing. (I wrote an acid func
to do the full unwind a long time ago but lost it and
haven't worked up the courage to write it again).
Note that these will only be present in the native symbol
table for Plan 9 binaries.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/72450045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/b67979320a9214b7d1b75bbd2d11ea5a1aa40323
元コミット内容
cmd/ld: give acid a fighting chance at unwinding the stack
Acid can't produce a stack trace without .frame symbols.
Of course, it can only unwind through linear stacks but
this is still better than nothing. (I wrote an acid func
to do the full unwind a long time ago but lost it and
haven't worked up the courage to write it again).
Note that these will only be present in the native symbol
table for Plan 9 binaries.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/72450045
変更の背景
この変更の背景には、Go言語のデバッガである acid
が、スタックトレースを正確に生成するために必要な情報が不足していたという問題があります。特に、acid
はスタックフレームの境界を特定するために .frame
シンボルを必要としますが、Goのリンカはこれまでこれらのシンボルを生成していませんでした。
コミットメッセージによると、acid
は .frame
シンボルなしではスタックトレースを生成できませんでした。これはデバッグ作業において大きな制約となります。コミットの作者であるAnthony Martin氏は、以前に acid
で完全なスタックアンワインドを行う関数を作成した経験があるものの、それを失ってしまい、再作成する意欲が湧かなかったと述べています。
このコミットは、完全なスタックアンワインドには至らないものの、少なくとも線形スタック(単純な関数呼び出しの連鎖)のアンワインドを可能にすることで、acid
のデバッグ能力を向上させることを目的としています。これにより、デバッガがより有用な情報を提供できるようになり、開発者がGoプログラムの実行時の問題を診断するのに役立ちます。
また、この変更が特にPlan 9バイナリに限定されている点も重要です。Go言語は元々Plan 9オペレーティングシステムの影響を強く受けており、そのツールチェインの一部はPlan 9の設計思想を継承しています。このコミットは、Plan 9環境におけるGoのデバッグ体験を改善するための具体的なステップと言えます。
前提知識の解説
このコミットを理解するためには、以下の前提知識が必要です。
1. Go言語のリンカ (cmd/ld
)
Go言語のビルドプロセスにおいて、リンカ (cmd/ld
) は非常に重要な役割を担います。コンパイラによって生成されたオブジェクトファイル(.o
ファイル)を結合し、実行可能なバイナリファイルを生成するのがリンカの主な仕事です。この過程で、リンカはシンボル解決、アドレスの再配置、セクションの結合などを行います。go tool link
として呼び出され、Goのビルドプロセスにおいて不可欠な部分です。
2. デバッガとスタックトレース
デバッガは、プログラムの実行を制御し、その内部状態を検査するためのツールです。スタックトレースは、プログラムがクラッシュしたり、特定のポイントに到達したりしたときに、現在実行中の関数の呼び出し履歴(コールスタック)を表示するものです。これにより、どの関数がどの関数を呼び出し、最終的に現在の実行ポイントに至ったのかを把握でき、問題の原因特定に役立ちます。
3. スタックアンワインド
スタックアンワインド(Stack Unwinding)とは、デバッガがコールスタックを逆方向に辿り、各関数の呼び出し元やローカル変数の状態などを特定するプロセスです。これには、各スタックフレームの開始位置とサイズ、およびレジスタの状態などの情報が必要です。
4. スタックフレーム
関数が呼び出されるたびに、その関数の実行に必要な情報(引数、ローカル変数、戻りアドレスなど)がスタック上に確保されます。この領域を「スタックフレーム」と呼びます。スタックフレームは、関数の呼び出しと戻りによって動的に生成・破棄されます。
5. .frame
シンボル
.frame
シンボルは、デバッガがスタックフレームの境界を特定するために使用するメタデータの一種です。これらのシンボルは、通常、コンパイラやリンカによって生成され、実行可能ファイルのシンボルテーブルに格納されます。デバッガはこれらのシンボルを参照して、スタックアンワインドを正確に行います。アセンブリ言語では、FRAME...ENDF
のような命令がスタックフレームの定義に使用されることがあります。
6. acid
デバッガ
acid
は、Plan 9オペレーティングシステムで開発されたデバッガです。これは、言語インタープリタとして実装された珍しいソースレベルのシンボリックデバッガとして説明されています。acid
言語は、デバッガ自身の言語内でプログラムのリソースを変数として表現し、操作することを可能にします。この設計により、デバッガとターゲットプログラム間の複雑な相互作用や、デバッグタスクのカスタマイズとスクリプト化が可能になります。acid
は、ブレークポイント管理、ステップ実行、スタックトレース、変数、メモリ、レジスタへのアクセスなどの機能を提供します。また、アドレス空間を共有する複数のプロセスをデバッグすることもできます。
7. Plan 9バイナリ
Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Go言語の設計にはPlan 9の哲学が色濃く反映されており、Goのツールチェインの一部はPlan 9の慣習に従っています。GoにはPlan 9への実験的な移植版があり、Linux上でamd64、386、armなどの様々なアーキテクチャ向けにクロスコンパイルされたGoバイナリが提供されています。Goのツールチェインには、アセンブラ (GoAsm)、リソースコンパイラ (GoRC)、リンカ (GoLink) などが含まれます。
8. シンボルテーブル
シンボルテーブルは、プログラム内のシンボル(関数名、変数名など)とそのアドレスや型などの情報をマッピングしたデータ構造です。リンカによって生成され、実行可能ファイル内に埋め込まれるか、別途デバッグ情報として提供されます。デバッガはシンボルテーブルを利用して、人間が読める形式でプログラムの状態を表示します。
技術的詳細
このコミットの技術的な核心は、Goリンカ (cmd/ld
) がPlan 9バイナリを生成する際に、各関数のスタックフレームに関する情報を .frame
シンボルとしてシンボルテーブルに追加する点にあります。
具体的には、src/cmd/ld/lib.c
ファイルの genasmsym
関数に以下の3行が追加されています。
// NOTE(ality): acid can't produce a stack trace without .frame symbols
put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
このコードは、各テキストセクション(関数コード)のシンボルを処理するループ内で実行されます。
put
関数は、シンボルテーブルにエントリを追加するための関数です。nil
は、このシンボルが特定のLSym
構造体に関連付けられていないことを示唆している可能性があります(あるいは、put
関数の最初の引数がシンボル構造体へのポインタであり、ここでは不要なためnil
が渡されている可能性もあります)。".frame"
は、追加されるシンボルの名前です。デバッガacid
がこの名前のシンボルを探してスタックフレーム情報を取得します。'm'
は、シンボルの型を示します。これはおそらく、特定のメタデータやデバッグ情報を示す型コードです。s->locals+PtrSize
は、この.frame
シンボルが指すアドレスを示しています。s->locals
は関数のローカル変数のサイズを示し、PtrSize
はポインタのサイズ(通常は4バイトまたは8バイト)です。これは、スタックフレーム内の特定のオフセット、おそらくローカル変数の開始位置やフレームポインタの次の位置など、スタックフレームの境界を示す重要なポイントを指していると考えられます。- 残りの
0, 0, 0
は、シンボルのサイズ、バージョン、および型情報(Goの型システムにおける型)を示しますが、.frame
シンボルにとってはこれらの値は重要ではないか、あるいはデフォルト値が使用されていることを意味します。
この変更により、Plan 9バイナリのシンボルテーブルには、各関数のスタックフレームに関する .frame
シンボルが追加されます。acid
デバッガは、この .frame
シンボルを読み取ることで、スタックフレームの開始位置を特定し、それに基づいてスタックアンワインドを実行できるようになります。
コミットメッセージにある「Of course, it can only unwind through linear stacks but this is still better than nothing.」という記述は、この .frame
シンボルが提供する情報だけでは、最適化されたコードや非線形なスタック構造(例えば、コルーチンやゴルーチンが複雑に絡み合う場合)における完全なスタックアンワインドは難しいことを示唆しています。しかし、少なくとも単純な関数呼び出しの連鎖においては、acid
がスタックトレースを生成できるようになるため、デバッグの有用性が大幅に向上します。
この変更は、Goのデバッグツールチェインの進化における一歩であり、特にPlan 9環境でのデバッグ体験を改善することを目的としています。
コアとなるコードの変更箇所
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index e0fcd15da5..20383de1e1 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -1341,6 +1341,9 @@ genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*))\
for(s = ctxt->textp; s != nil; s = s->next) {
put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
+ // NOTE(ality): acid can't produce a stack trace without .frame symbols
+ put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
+
for(a=s->autom; a; a=a->link) {
// Emit a or p according to actual offset, even if label is wrong.
// This avoids negative offsets, which cannot be encoded.
コアとなるコードの解説
変更は src/cmd/ld/lib.c
ファイルの genasmsym
関数内で行われています。
genasmsym
関数は、アセンブリシンボルを生成し、シンボルテーブルに追加するための関数です。この関数は、Goプログラム内の各テキストセクション(つまり、各関数)をループ処理し、その関数に関するシンボル情報(関数名、アドレス、サイズなど)を put
関数を使ってシンボルテーブルに書き込みます。
追加された3行は、このループの内側にあります。
// NOTE(ality): acid can't produce a stack trace without .frame symbols
put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
-
// NOTE(ality): acid can't produce a stack trace without .frame symbols
これはコメントであり、このコードが追加された理由を明確に説明しています。acid
デバッガがスタックトレースを生成するためには.frame
シンボルが必要であるという、この変更の直接的な動機を示しています。 -
put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
この行が、実際に.frame
シンボルをシンボルテーブルに追加する処理です。put
: シンボルテーブルにエントリを追加する関数ポインタ。nil
: シンボルが特定のLSym
構造体に関連付けられていないことを示します。これは、.frame
シンボルが関数自体ではなく、そのスタックフレームのメタデータとして扱われるためと考えられます。".frame"
: シンボルの名前。acid
デバッガがこの名前を認識し、スタックフレーム情報として利用します。'm'
: シンボルの型。これは、デバッグ情報やメタデータを示すカスタムシンボル型である可能性があります。s->locals+PtrSize
: シンボルの値(アドレス)。s->locals
は現在の関数のローカル変数の合計サイズを示します。PtrSize
はポインタのサイズ(通常4バイトまたは8バイト)です。この計算は、スタックフレーム内の特定のオフセット、おそらくローカル変数の開始位置やフレームポインタの次の位置など、スタックフレームの境界を示す重要なポイントを指していると考えられます。デバッガはこのアドレスを基にスタックフレームの構造を推測します。0, 0, 0
: 残りの引数は、シンボルのサイズ、バージョン、およびGoの型情報ですが、.frame
シンボルにとってはこれらの値は通常ゼロで十分です。
この変更により、GoのリンカはPlan 9バイナリを生成する際に、各関数のスタックフレームに関する .frame
シンボルをシンボルテーブルに埋め込むようになります。これにより、acid
デバッガはこれらのシンボルを利用して、より正確なスタックアンワインドとスタックトレースの生成が可能になります。
関連リンク
- Go言語のリンカ (
cmd/ld
) のソースコード: https://github.com/golang/go/tree/master/src/cmd/ld - Plan 9 from Bell Labs: https://9p.io/plan9/
- Go言語のデバッグに関するドキュメント(一般的な情報): https://go.dev/doc/gdb (これはGDBに関するものですが、デバッグの概念は共通です)
参考にした情報源リンク
- Go言語のコミット履歴: https://github.com/golang/go/commits/master
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
- Plan 9のデバッガ
acid
に関する情報(一般的な概念): https://9p.io/sys/doc/acid/intro.html - スタックフレームとスタックアンワインドに関する一般的なコンピュータサイエンスの概念。
- シンボルテーブルに関する一般的な情報。
- Go言語のビルドプロセスに関する一般的な情報。
PtrSize
の定義に関するGoのソースコード(例:src/cmd/internal/obj/go.go
など)。LSym
構造体やput
関数の具体的な定義は、Goのリンカのソースコード内で確認できます。- Web検索結果: "Go acid debugger .frame symbols Plan 9 binaries Go linker cmd/ld"