> Source: https://www.ymotongpoo.com/works/goblog-ja/debug-status/


# Goコードのデバッグ(現状報告)

[Debugging Go code (a status report)](https://go.dev/blog/debug-status) by Luuk van Dijk

デバッグでは、変数を調べるための気の利いたprint文をいくつか仕込むことや、スタックトレースを得るための適切な位置に置いたpanicに勝るものはありません。ただ、忍耐力かソースコードのどちらかが足りないこともあり、そういうときには優れたデバッガが大きな助けになります。だからこそ、これまでの複数のリリースを通じて、Goのgcリンカ(6lと8l)がGNUデバッガGDBをサポートする機能を改善してきました。

最新のリリース(2010年11月2日)では、6lと8lのリンカがELF(Linux、FreeBSD)またはMach-O(Mac OS X)バイナリを書き出す際にDWARF3のデバッグ情報を出力するようになりました。このDWARFのコードは十分に充実しており、次のようなことができます。

* GDBバージョン7.xでGoプログラムを読み込む
* Go、C、アセンブリの各ソースファイルを行番号付きですべて一覧表示する(Goランタイムの一部はCとアセンブリで書かれています)
* 行番号を指定してブレークポイントを設定し、コードをステップ実行する
* スタックトレースを表示し、スタックフレームを調べる
* ほとんどの変数のアドレスを見つけて、その内容を表示する

まだいくつか不便な点があります。

* 出力されるDWARFコードは、Mac OS Xに付属するGDBバージョン6.xでは読み込めません。標準のOS X版GDBでもDWARFの出力を読み込めるようにするパッチは喜んで受け入れますが、それが修正されるまでは、OS X上で使うにはGDB 7.xをダウンロードしてビルドし、インストールする必要があります。ソースは [http://sourceware.org/gdb/download/](http://sourceware.org/gdb/download/) にあります。OS X特有の事情により、`chgrp procmod` と `chmod g+s` を実行して、ローカルのファイルシステム上にバイナリをインストールする必要があります。
* 名前はパッケージ名で修飾されており、GDBはGoのパッケージを理解しないため、各項目をフルネームで参照しなければなりません。たとえば、パッケージ `main` にある変数 `v` は、シングルクォートで囲んだ `'main.v'` として参照する必要があります。この結果、変数名や関数名のタブ補完は機能しません。
* レキシカルスコープの情報はいくぶん分かりにくくなっています。同じ名前の変数が複数ある場合、n番目のインスタンスには「#n」という形式のサフィックスが付きます。これは修正する予定ですが、コンパイラとリンカの間でやり取りされるデータにいくつか変更が必要になります。
* スライスと文字列の変数は、ランタイムライブラリ内部の構造そのままの形で表示されます。`{data = 0x2aaaaab3e320, len = 1, cap = 1}` のような見た目になります。スライスの場合、要素を調べるにはdataポインタを参照解決する必要があります。

まだ動かないものもあります。

* チャンネル、関数、インターフェース、マップの変数は調べられません。
* 型情報が付与されているのはGoの変数だけで、ランタイムのC変数には付与されていません。
* WindowsとARMのバイナリにはDWARFのデバッグ情報が含まれておらず、そのためGDBで調べることはできません。

今後数ヶ月のうちに、コンパイラとリンカを変更するか、GDB向けのPython拡張を使うことで、これらの問題に対処していく予定です。それまでの間、Goプログラマの皆さんがこのよく知られたデバッグツールに、より良い形でアクセスできるようになることを願っています。

追記として、DWARF情報はGDB以外のツールからも読み込めます。たとえば、Linuxではシステム全体を対象としたプロファイラであるsysprofと組み合わせて使えます。

By Luuk van Dijk

