golang でビルド時に最適化をオフにする

Go のプログラムのデバッグ時に gdb が便利だよということは Debugging Go code with GDB に書いてあるのですが, gdb で変数の調査をしようとしたときに, ローカル変数の値がレジスタに載っていて表示されない場合があります. もちろんレジスタを見れば分かるわけですが... 今回はレジスタを見ずに変数の調査をしたい場合があると仮定することにします. メーリングリストあたりを検索したところ go build に -gcflags '-N -l' をつけると最適化をオフにすることができるようです [1,2]

例を見てみましょう. 以下のような 1 から 9 までの整数の和を求めるコードがあったとします. 

 

このコードの 14 行目の変数 n の値を調査したいとします. コードをコンパイルして gdbデバッグすると以下のような結果になります. 使用した Go のバージョンは 1.0.2 です.

40行目を見ていただくと分かるように, n の値は "No symbol "n" in current context." となっていて print では値がわかりません. この場合, 変数 n の値はレジスタに載っているのでレジスタを参照する必要があります. 

 

それではビルド時に -gcflags '-N -l' をつけて最適化をオフにしてビルドしてみます.

 37, 38 行目を見てもらうと分かる通り, n の値が print で表示できるようになりました. ちなみに関数 sum() 内のローカル変数 sum の値も表示できるようになります.

とここまで書いておいてなんですが, 実はレジスタを参照して n の値を調べるのは難しくはありません. 例を以下に示します (もちろん変数 sum の値を調べることも可能です).

41 行目で rip レジスタ (インストラクションポインタ) の内容を調べると, 43 行目で関数 sum が呼ばれることが分かるので, 44行目でその結果が ecx レジスタに格納されるという予想がつきます.  実際に ecx レジスタの値を表示すると関数 sum の結果が入っていることがわかります (57, 58 行目).

ちなみに gdb を使ったデバッグの仕方については以下の本の 2章 (0x200) プログラミングの部分に分かりやすく書かれています.

Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際

Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際

[1] https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/6m8bZYik8Ss

[2] http://code.google.com/p/go/issues/detail?id=3363