[インデックス 12697] ファイルの概要
このコミットは、Go言語のデバッグに関する公式ドキュメントである doc/debugging_with_gdb.html
ファイルに対する更新です。このドキュメントは、GoプログラムをGDB (GNU Debugger) を使用してデバッグする方法について解説しており、Go開発者がGoアプリケーションの実行時挙動を詳細に調査するための重要な情報源となっています。
コミット
- コミットハッシュ:
9dbfda5857ca5481135c960ead3e9bce153cc8b6
- 作者: Shenghou Ma minux.ma@gmail.com
- コミット日時: 2012年3月21日 (水) 00:42:53 +0800
- 変更ファイル:
doc/debugging_with_gdb.html
(1ファイル変更) - 変更行数: 39行追加, 38行削除
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9dbfda5857ca5481135c960ead3e9bce153cc8b6
元コミット内容
doc/debugging_with_gdb: format & content update
R=adg, lvd
CC=golang-dev
https://golang.org/cl/5845065
変更の背景
このコミットの背景には、Go言語のデバッグ体験の改善と、ドキュメントの正確性および読みやすさの向上が挙げられます。当時のGo言語はまだ発展途上にあり、デバッグツールやその利用方法に関する情報も継続的に更新されていました。特にGDBとの連携は、Goのランタイム特性(goroutine、チャネルなど)を考慮する必要があり、そのための具体的な手順や注意点を明確にすることが求められていました。
このコミットは、主に以下の目的で実施されました。
- 情報の正確性の向上: GDBのバージョンアップやGoツールチェインの変更に伴い、古い情報や不正確な記述を修正する。
- デバッグ手順の明確化: GDBコマンドの例をより具体的に示し、Go特有のデバッグ要素(goroutine、チャネル、メソッドなど)の扱い方を分かりやすく説明する。
- ドキュメントのフォーマット改善: 読みやすさを向上させるために、コードブロックの整形やテキストの調整を行う。
- Goテストバイナリ名の変更への対応:
go test -c
コマンドによって生成されるテストバイナリの命名規則が変更されたことに対応し、ドキュメントの例を更新する。
前提知識の解説
このコミットの変更内容を理解するためには、以下の技術的知識が前提となります。
- GDB (GNU Debugger): GNUプロジェクトが開発した、様々なプログラミング言語に対応する強力なコマンドラインデバッガ。プログラムの実行を一時停止させたり、変数の値を検査したり、スタックトレースを表示したりする機能を提供します。
- DWARF (Debugging With Arbitrary Record Formats): プログラムのデバッグ情報を格納するための標準的なフォーマット。コンパイラやリンカによって生成され、GDBのようなデバッガがソースコードレベルでのデバッグを可能にするために利用します。Goの
gc
ツールチェインは、DWARFv3形式のデバッグ情報を生成します。 gc
ツールチェイン: Go言語の公式コンパイラおよびツールセット。Goソースコードをコンパイルし、実行可能なバイナリを生成します。go build -ldflags "-s"
: Goのビルドコマンドgo build
にリンカフラグ-ldflags "-s"
を渡すことで、生成されるバイナリからデバッグ情報(DWARF情報)を削除できます。これにより、バイナリのサイズを削減できますが、GDBでのデバッグは困難になります。go test -c
: Goのテストコマンドgo test
に-c
フラグを付けると、テストを実行する代わりに、テストバイナリをコンパイルして指定されたディレクトリに保存します。このバイナリは、GDBでデバッグするために使用できます。GOROOT
: Goのインストールディレクトリを示す環境変数。Goの標準ライブラリやツールチェインが配置されています。- Goランタイム (runtime): Goプログラムの実行を管理するシステム。goroutineのスケジューリング、メモリ管理、ガベージコレクション、チャネル通信などを担当します。GDBでGoプログラムをデバッグする際には、Goランタイムの内部構造を理解することが役立ちます。
- Goroutine: Go言語における軽量な並行処理の単位。OSのスレッドよりもはるかに軽量で、数百万のgoroutineを同時に実行することも可能です。GDBはGoのランタイムサポートを通じてgoroutineを認識し、個々のgoroutineのスタックトレースを表示できます。
- チャネル (Channel): Go言語におけるgoroutine間の通信手段。チャネルを通じて値の送受信を行うことで、安全な並行処理を実現します。GDBでチャネルの内部状態を検査することも可能です。
- Goのメソッドとレシーバ: Goでは、型に紐付けられた関数をメソッドと呼びます。メソッドはレシーバ(メソッドが操作するインスタンス)を持ち、ポインタレシーバと値レシーバがあります。GDBでは、Goのメソッドは特定の命名規則(例:
pkg.(*MyType).Meth
)で表示されます。
技術的詳細
このコミットは、doc/debugging_with_gdb.html
ファイル内の複数の箇所にわたる変更を含んでいます。主な変更点は以下の通りです。
- GDBバージョンの表記修正:
Mac OSX
をMac OS X
に修正し、より正確な表記にしています。 - デバッグ情報削除のコマンド例の追加:
-s
フラグを使用してデバッグ情報を省略する際の具体的なコマンド例go build -ldflags "-s" prog.go
が追加されました。これにより、ユーザーはどのようにデバッグ情報を削除できるかを明確に理解できます。 - GDBコマンドの追加と説明の改善:
list
コマンドの説明にset breakpoints and disassemble
が追加され、disas
コマンドが明示的にリストアップされました。bt
(backtrace) コマンドの説明にShow backtraces
が追加され、スタックフレームのアンワインドだけでなく、バックトレースの表示も強調されています。
- テストバイナリ名の変更:
- 以前は
gotest
コマンドを実行すると6.out
という名前のテストバイナリが生成されると記述されていましたが、go test -c
コマンドを使用することでregexp.test
という名前のバイナリが生成されるように変更されました。これに伴い、GDBの起動コマンドやシンボル読み込みの出力例も6.out
からregexp.test
に更新されています。これはGoツールチェインの進化に伴う変更を反映したものです。
- 以前は
- GoメソッドのGDBでの表現の明確化:
regexp.(*Regexp).doParse
の例がregexp.(*Regexp).String
に変更されました。これは、より一般的なString()
メソッドを例に挙げることで、ユーザーがGoのメソッドがGDBでどのように表示されるかを理解しやすくするためと考えられます。また、以前の記述にあった(Note that the second dot is a "middot," an artifact of Go’s internal representation of methods.)
という説明が削除されました。これは、GDBの表示が改善されたか、あるいはその内部的な詳細がユーザーにとって重要でなくなったためかもしれません。
- クロージャによる参照変数の表記修正:
&
が&
に修正され、HTMLエンティティの正しい表記になりました。 - GDB出力例のパス修正: GDBの出力例に含まれるファイルパスが、
lvd/g/src/pkg/
からuser/go/src/pkg/
に変更されています。これは、ドキュメントの例がより一般的なユーザー環境を反映するように調整されたものです。 - チャネルのGDB表示の修正:
hchan<*testing.T>
のHTMLエンティティがhchan<*testing.T>
に修正され、<
と>
が正しくエスケープされるようになりました。 - スライスのGDB表示の修正:
slc->
のHTMLエンティティがslc->
に修正され、->
が正しくエスケープされるようになりました。 - マップのGDB表示の修正:
hash<int,string>*
のHTMLエンティティがhash<int,string>*
に修正され、<
と>
が正しくエスケープされるようになりました。
これらの変更は、Goのデバッグに関するドキュメントをより正確で、最新で、かつユーザーフレンドリーにするための継続的な努力の一環です。
コアとなるコードの変更箇所
diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html
index 84cc488db8..1ac1c1fd8a 100644
--- a/doc/debugging_with_gdb.html
+++ b/doc/debugging_with_gdb.html
@@ -13,13 +13,14 @@ Besides this overview you might want to consult the
<p>
When you compile and link your Go programs with the <code>gc</code> toolchain
-on Linux, Mac OSX or FreeBSD, the resulting binaries contain DWARFv3
-debugging information that recent versions (>7.1) of the GDB debugger can
+on Linux, Mac OS X or FreeBSD, the resulting binaries contain DWARFv3
+debugging information that recent versions (>7.1) of the GDB debugger can
use to inspect a live process or a core dump.
</p>
<p>
-Pass the <code>\'-s\'</code> flag to the linker to omit the debug information.\n+Pass the <code>\'-s\'</code> flag to the linker to omit the debug information\n+(for example, <code>go build -ldflags \"-s\" prog.go</code>).\n </p>
@@ -28,7 +29,7 @@ Pass the <code>\'-s\'</code> flag to the linker to omit the debug information.
<ul>
<li>
Show file and line number for code
-and set breakpoints:\n+, set breakpoints and disassemble:\n <pre>(gdb) <b>list</b>\n (gdb) <b>list <i>line</i></b>\n (gdb) <b>list <i>file.go</i>:<i>line</i></b>\n@@ -37,7 +38,7 @@ and set breakpoints:\n (gdb) <b>disas</b></pre>\n </li>
<li>
-Unwind stack frames:\n+Show backtraces and unwind stack frames:\n <pre>(gdb) <b>bt</b>\n (gdb) <b>frame <i>n</i></b></pre>\n </li>
@@ -101,7 +102,7 @@ the Go source distribution. It depends on some special magic types
<code>runtime.g</code>) that the linker
(<a href=\"/src/cmd/ld/dwarf.c\">src/cmd/ld/dwarf.c</a>) ensures are described in
the DWARF code.\n-</ines\n+</p>\n
<p>
If you\'re interested in what the debugging information looks like, run
@@ -128,26 +129,26 @@ the form <code>pkg.(*MyType).Meth</code>.\n <p>
In this tutorial we will inspect the binary of the
<a href=\"/pkg/regexp/\">regexp</a> package\'s unit tests. To build the binary,\n-change to <code>$GOROOT/src/pkg/regexp</code> and run <code>gotest</code>.\n-This should produce an executable file named <code>6.out</code>.\n+change to <code>$GOROOT/src/pkg/regexp</code> and run <code>go test -c</code>.\n+This should produce an executable file named <code>regexp.test</code>.\n </p>
<h3 id=\"Getting_Started\">Getting Started</h3>
<p>
-Launch GDB, debugging <code>6.out</code>:\n+Launch GDB, debugging <code>regexp.test</code>:\n </p>
<pre>
-$ <b>gdb 6.out</b>\n+$ <b>gdb regexp.test</b>\n GNU gdb (GDB) 7.2-gg8
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv 3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
Type \"show copying\" and \"show warranty\" for licensing/warranty details.
This GDB was configured as \"x86_64-linux\".
-Reading symbols from /home/user/go/src/pkg/regexp/6.out...\n+Reading symbols from /home/user/go/src/pkg/regexp/regexp.test...\n done.
Loading Go Runtime support.
(gdb)
@@ -164,7 +165,7 @@ pass your <code>$GOROOT</code> with the <code>\'-d\'</code> flag:\n </p>
<pre>
-$ <b>gdb 6.out -d $GOROOT</b>\n+$ <b>gdb regexp.test -d $GOROOT</b>\n </pre>
<p>
@@ -217,14 +218,13 @@ package is known to GDB as <code>\'regexp.Compile\'</code>.\n
<p>
Methods must be qualified with the name of their receiver types. For example,\n-the <code>*Regexp</code> type’s <code>doParse</code> method is known as\n-<code>\'regexp.*Regexp.doParse\'</code>. (Note that the second dot is a \"middot,\"\n-an artifact of Go’s internal representation of methods.)\n+the <code>*Regexp</code> type’s <code>String</code> method is known as\n+<code>\'regexp.(*Regexp).String\'</code>.\n </p>
<p>
Variables that shadow other variables are magically suffixed with a number in the debug info.\n-Variables referenced by closures will appear as pointers magically prefixed with \'&\'.\n+Variables referenced by closures will appear as pointers magically prefixed with \'&\'.\n </p>
<h3 id=\"Setting_breakpoints\">Setting breakpoints</h3>
@@ -244,7 +244,7 @@ Run the program:\n
<pre>
(gdb) <b>run</b>\n-Starting program: /home/lvd/g/src/pkg/regexp/6.out \n+Starting program: /home/user/go/src/pkg/regexp/regexp.test\n
Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
148 func TestFind(t *testing.T) {
@@ -287,16 +287,18 @@ The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked
<pre>
(gdb) <b>goroutine 1 bt</b>\n-#0 0x000000000040facb in runtime.gosched () at /home/lvd/g/src/pkg/runtime/proc.c:873\n+#0 0x000000000040facb in runtime.gosched () at /home/user/go/src/pkg/runtime/proc.c:873\n #1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)\n- at /home/lvd/g/src/pkg/runtime/chan.c:342\n-#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/lvd/g/src/pkg/runtime/chan.c:423\n-#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)} 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/lvd/g/src/pkg/testing/testing.go:201\n-#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)} 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})\n- at /home/lvd/g/src/pkg/testing/testing.go:168\n-#5 0x0000000000400dc1 in main.main () at /home/lvd/g/src/pkg/regexp/_testmain.go:98\n-#6 0x00000000004022e7 in runtime.mainstart () at /home/lvd/g/src/pkg/runtime/amd64/asm.s:78\n-#7 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243\n+ at /home/user/go/src/pkg/runtime/chan.c:342\n+#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/pkg/runtime/chan.c:423\n+#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)}\n+ 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/pkg/testing/testing.go:201\n+#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)} \n+ 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})\n+at /home/user/go/src/pkg/testing/testing.go:168\n+#5 0x0000000000400dc1 in main.main () at /home/user/go/src/pkg/regexp/_testmain.go:98\n+#6 0x00000000004022e7 in runtime.mainstart () at /home/user/go/src/pkg/runtime/amd64/asm.s:78\n+#7 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243\n #8 0x0000000000000000 in ?? ()\n </pre>
@@ -307,7 +309,7 @@ The stack frame shows we’re currently executing the <code>regexp.TestFind</cod\n <pre>
(gdb) <b>info frame</b>\n Stack level 0, frame at 0x7ffff7f9ff88:\n- rip = 0x425530 in regexp.TestFind (/home/lvd/g/src/pkg/regexp/find_test.go:148); \n+ rip = 0x425530 in regexp.TestFind (/home/user/go/src/pkg/regexp/find_test.go:148); \n saved rip 0x430233
called by frame at 0x7ffff7f9ffa8
source language minimal.
@@ -346,12 +348,12 @@ $1 = (struct testing.T *) 0xf840688b60\n $1 = (struct testing.T *) 0xf840688b60\n (gdb) p *t\n $2 = {errors = \"\", failed = false, ch = 0xf8406f5690}\n-(gdb) p *t->ch\n-$3 = struct hchan<*testing.T>\n+(gdb) p *t->ch\n+$3 = struct hchan<*testing.T>\n </pre>
<p>
-That <code>struct hchan<*testing.T></code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it\'s contents.\n+That <code>struct hchan<*testing.T></code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it\'s contents.\n </p>
<p>
@@ -384,7 +386,7 @@ We can step into the <code>String</code>function call with <code>\"s\"</code>:\n
<pre>
(gdb) <b>s</b>\n-regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/lvd/g/src/pkg/regexp/regexp.go:97\n+regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/user/go/src/pkg/regexp/regexp.go:97\n 97 func (re *Regexp) String() string {
</pre>
@@ -394,14 +396,13 @@ Get a stack trace to see where we are:\n
<pre>
(gdb) <b>bt</b>\n-(gdb) bt\n #0 regexp.(*Regexp).String (re=0xf84068d070, noname=void)\n- at /home/lvd/g/src/pkg/regexp/regexp.go:97\n+ at /home/user/go/src/pkg/regexp/regexp.go:97\n #1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60)\n- at /home/lvd/g/src/pkg/regexp/find_test.go:151\n+ at /home/user/go/src/pkg/regexp/find_test.go:151\n #2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)\n- at /home/lvd/g/src/pkg/testing/testing.go:156\n-#3 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243\n+ at /home/user/go/src/pkg/testing/testing.go:156\n+#3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243\n ....\n </pre>
@@ -442,7 +443,7 @@ you can look inside the runtime representation to do that (tab completion helps\n
(gdb) <b>p slc</b>\n $11 = []int = {0, 0}\n-(gdb) <b>p slc-></b><i><TAB></i>\n+(gdb) <b>p slc-></b><i><TAB></i>\n array slc len \n (gdb) <b>p slc->array</b>\n $12 = (int *) 0xf84057af00
@@ -463,7 +464,7 @@ $24 = 4\n </pre>
<p>
-Channels and maps are \'reference\' types, which gdb shows as pointers to C++-like types <code>hash<int,string>*</code>. Dereferencing will trigger prettyprinting\n+Channels and maps are \'reference\' types, which gdb shows as pointers to C++-like types <code>hash<int,string>*</code>. Dereferencing will trigger prettyprinting\n </p>
<p>
コアとなるコードの解説
上記の差分は、doc/debugging_with_gdb.html
ファイルに対する具体的な変更を示しています。
- 行13-14:
Mac OSX
をMac OS X
に修正し、より正確なOS表記にしています。 - 行16-18: デバッグ情報を省略するための
go build -ldflags "-s" prog.go
という具体的なコマンド例が追加されました。これにより、ユーザーはデバッグ情報を含まないバイナリを生成する方法をすぐに理解できます。 - 行29-30: GDBの
list
コマンドの説明にset breakpoints and disassemble
が追加され、disas
コマンドが明示的に例として示されました。これは、GDBの基本的なデバッグ機能の網羅性を高めるものです。 - 行38-39: GDBの
bt
(backtrace) コマンドの説明にShow backtraces
が追加されました。これにより、スタックフレームのアンワインドだけでなく、バックトレースの表示も強調され、より包括的な説明になっています。 - 行102-103: 閉じタグが
</ines
から</p>
に修正されました。これはHTMLの構文エラーの修正です。 - 行130-132: テストバイナリの生成方法が
gotest
からgo test -c
に変更され、生成されるバイナリ名が6.out
からregexp.test
に更新されました。これはGoツールチェインの変更を反映した重要な更新です。 - 行138-140, 146-148, 166-167: 上記のテストバイナリ名の変更に伴い、GDBの起動コマンドやシンボル読み込みの出力例が
6.out
からregexp.test
に一貫して更新されています。 - 行220-222: GoのメソッドがGDBでどのように表示されるかの例が
regexp.(*Regexp).doParse
からregexp.(*Regexp).String
に変更されました。また、Goの内部表現に関する詳細な注釈が削除されました。これは、ドキュメントの簡潔性と、ユーザーがより一般的なメソッドの例で理解できるようにするための変更です。 - 行225-226: クロージャによる参照変数の表記
&
が正しいHTMLエンティティ&
に修正されました。 - 行247-248, 290-291, 310-311, 387-388, 397-398, 400-401, 403-404: GDBの出力例に含まれるファイルパスが、
lvd/g/src/pkg/
からuser/go/src/pkg/
に変更されています。これは、ドキュメントの例がより一般的なユーザー環境を反映するように調整されたものです。 - 行349-350, 353-354: チャネルのGDB表示
hchan<*testing.T>
のHTMLエンティティがhchan<*testing.T>
に修正され、<
と>
が正しくエスケープされるようになりました。 - 行446-447: スライスのGDB表示
slc->
のHTMLエンティティがslc->
に修正され、->
が正しくエスケープされるようになりました。 - 行467-468: マップのGDB表示
hash<int,string>*
のHTMLエンティティがhash<int,string>*
に修正され、<
と>
が正しくエスケープされるようになりました。
これらの変更は、Goのデバッグに関するドキュメントの正確性、網羅性、およびユーザーフレンドリーさを向上させるためのものです。特に、Goツールチェインの変更に合わせたテストバイナリ名の更新や、GDBコマンドのより詳細な説明は、Go開発者にとって非常に有用な改善と言えます。
関連リンク
参考にした情報源リンク
- Go言語のソースコード (GitHub)
- GDBドキュメント
- Go Wiki: DebuggingGoPrograms (このコミットの対象ドキュメントの最新版)
- Go Modules: go test -c (Go 1.11以降の
go test -c
の挙動に関する情報) - HTML Entities for < and > (HTMLエンティティに関する情報)