[インデックス 1217] ファイルの概要
このコミットは、Go言語のリンカである6l
におけるデバッガが使用するmachテーブル内のシンボルテーブルの位置記録に関するバグ修正です。具体的には、シンボルテーブルが移動された際に、machテーブルが正しい場所を記録していなかった問題に対処しています。
コミット
commit 284a50c109495973def8b9e7d94fa329a207a99e
Author: Russ Cox <rsc@golang.org>
Date: Fri Nov 21 16:13:11 2008 -0800
fix 6l bug - moved symbol table without
recording correct place in mach tables
used by debuggers.
R=r
DELTA=4 (0 added, 2 deleted, 2 changed)
OCL=19810
CL=19849
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/284a50c109495973def8b9e7d94fa329a207a99e
元コミット内容
fix 6l bug - moved symbol table without
recording correct place in mach tables
used by debuggers.
変更の背景
このコミットは、Go言語の初期開発段階におけるリンカ6l
のバグ修正です。6l
は、Goプログラムをコンパイルした際に生成されるオブジェクトファイルをリンクし、実行可能ファイルを生成する役割を担っていました。デバッガが正しく機能するためには、実行可能ファイル内のシンボル情報(変数名、関数名、行番号など)が正確に参照できる必要があります。
コミットメッセージによると、このバグはシンボルテーブルがメモリ内で移動された際に発生しました。リンカがシンボルテーブルを再配置したにもかかわらず、デバッガがシンボル情報を解決するために使用する「machテーブル」(おそらくMach-O形式の実行可能ファイルにおけるシンボル関連のメタデータ)が、その新しい位置を正しく記録していなかったと考えられます。結果として、デバッガはシンボルを正しく解決できず、デバッグ体験に支障をきたしていたと推測されます。
前提知識の解説
- リンカ (Linker): コンパイラによって生成された複数のオブジェクトファイル(機械語コードとシンボル情報を含む)を結合し、単一の実行可能ファイルやライブラリを生成するプログラムです。リンカは、異なるオブジェクトファイル間で参照されるシンボル(関数や変数)を解決し、それらのアドレスを決定します。
- シンボルテーブル (Symbol Table): プログラム内の識別子(変数名、関数名など)とその属性(型、スコープ、メモリ上のアドレスなど)を格納するデータ構造です。コンパイラやリンカ、デバッガがプログラムの構造を理解し、シンボルを解決するために使用します。
- デバッガ (Debugger): プログラムの実行を制御し、その内部状態(変数の値、実行パスなど)を検査することで、バグを発見・修正するためのツールです。デバッガはシンボルテーブルを利用して、ソースコードの変数名や関数名と、実行時のメモリ上のアドレスを対応付けます。
- Mach-O (Mach Object): AppleのmacOSやiOSで使用される実行可能ファイル、オブジェクトファイル、共有ライブラリのフォーマットです。Mach-Oファイルは、ヘッダ、ロードコマンド、セグメント、セクションなどから構成され、シンボルテーブルやデバッグ情報も含まれます。
6l
が生成する実行可能ファイルがMach-O形式であった場合、machsymseg
関数はMach-Oのシンボル関連のセクションを操作していた可能性があります。 6l
: Go言語の初期のツールチェインにおけるリンカの一つです。Go言語はクロスコンパイルを重視しており、6l
は64ビットIntelアーキテクチャ(amd64)向けのリンカを指していました。Goのツールチェインは、ターゲットアーキテクチャごとに異なるリンカ(例:8l
for 386,5l
for ARM)を持っていました。
技術的詳細
このコミットは、src/cmd/6l/asm.c
ファイル内の変更です。asm.c
は、リンカのバックエンドの一部であり、アセンブリコードの生成やオブジェクトファイルの構造化に関連する処理を行っていたと考えられます。
変更点を見ると、machsymseg
という関数が呼び出されている箇所が修正されています。この関数は、おそらくMach-O形式の実行可能ファイルにおけるシンボルセグメント(またはシンボルテーブルに関連するセクション)の情報を設定するためのものです。
元のコードでは、machsymseg
の呼び出しにおいて、シンボルテーブルとラインカバレッジ情報(lcsize
)のファイルオフセットを計算するために、v
という変数が使用されていました。v
は、データセクションのサイズ(datsize
)とシンボルテーブルのサイズ(symsize
)に基づいてインクリメントされていました。
// 変更前
v += rnd(datsize, INITRND);
machsymseg(v,symsize); /* fileoffset,filesize */
v += symsize;
machsymseg(v,lcsize); /* fileoffset,filesize */
このコードは、シンボルテーブルがメモリ上で移動された際に、v
がその新しいオフセットを正確に反映していなかった可能性を示唆しています。つまり、v
が指すアドレスが、実際にシンボルテーブルが配置されたアドレスとずれてしまっていたため、デバッガが参照するmachテーブル内の情報が不正になっていたと考えられます。
修正後のコードでは、machsymseg
の呼び出しでv
の代わりにsymo
という変数が使用されています。
// 変更後
machsymseg(symo+8,symsize); /* fileoffset,filesize */
machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */
symo
は、おそらくシンボルテーブルの開始オフセットを正確に保持している変数であると推測されます。symo+8
というオフセットが使われているのは、Mach-Oのシンボルテーブルの構造や、特定のヘッダ情報が8バイト分存在するためかもしれません。この変更により、machsymseg
関数はシンボルテーブルとラインカバレッジ情報の正しいファイルオフセットを受け取るようになり、デバッガがこれらの情報を正確に解決できるようになりました。
コアとなるコードの変更箇所
src/cmd/6l/asm.c
ファイルの asmb
関数内。
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -409,10 +409,8 @@ asmb(void)\
7, 5, /* protects */
0, 0); /* sections flags */
- v += rnd(datsize, INITRND);
- machsymseg(v,symsize); /* fileoffset,filesize */
- v += symsize;
- machsymseg(v,lcsize); /* fileoffset,filesize */
+ machsymseg(symo+8,symsize); /* fileoffset,filesize */
+ machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */
}
break;
case 7:
コアとなるコードの解説
変更は、asmb
関数内の特定のcase
ブロック(おそらくMach-O形式の出力に関連する部分)で行われています。
-
削除された行:
v += rnd(datsize, INITRND); machsymseg(v,symsize); /* fileoffset,filesize */ v += symsize; machsymseg(v,lcsize); /* fileoffset,filesize */
これらの行は、
v
という変数を使ってシンボルテーブルとラインカバレッジ情報のオフセットを計算し、machsymseg
に渡していました。rnd(datsize, INITRND)
は、データセクションのサイズを特定の境界(INITRND
)にアラインメントするための関数です。この計算方法が、シンボルテーブルの実際の配置とずれていたことが問題でした。 -
追加された行:
machsymseg(symo+8,symsize); /* fileoffset,filesize */ machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */
これらの行では、
v
の代わりにsymo
という変数が使用されています。symo
は、シンボルテーブルの開始オフセットを正確に保持していると推測されます。+8
というオフセットは、Mach-Oのシンボルテーブルの構造や、その前に存在する特定のメタデータ(例えば、シンボルテーブルのサイズやオフセットを示すヘッダ)のサイズを考慮している可能性があります。これにより、machsymseg
はシンボルテーブルとラインカバレッジ情報の正しいファイルオフセットを受け取るようになり、デバッガがこれらの情報を正確に解決できるようになりました。
この修正は、リンカが生成する実行可能ファイルの内部構造、特にデバッグ情報に関連する部分の正確性を向上させるものであり、Go言語のデバッグ体験の安定化に貢献しました。
関連リンク
- Go言語の初期のリンカに関する議論やドキュメントは、現在のGoの公式ドキュメントからは見つけにくい可能性があります。当時のメーリングリストやGoの初期のソースコードリポジトリを深く掘り下げる必要があるかもしれません。
- Mach-Oファイルフォーマットに関する一般的な情報は、Appleの開発者ドキュメントや関連する技術記事で確認できます。
参考にした情報源リンク
- Go言語のGitHubリポジトリ (コミットの直接リンク)
- Mach-Oファイルフォーマットに関する一般的な情報源 (例: Wikipedia, Apple Developer Documentation)
- リンカ、シンボルテーブル、デバッガに関する一般的なコンピュータサイエンスの知識。
- Go言語の初期のツールチェインに関する歴史的な情報(Goのブログ記事や初期の設計ドキュメントなど)。