土曜日, 12月 26, 2015

LLDBでGoのデバッグをする その1

環境

環境は以下の通りです。

  • OS X El Capitan 10.11.2
  • lldb-340.4.119
  • go version go1.5 darwin/amd64

LLDBはxcodeについてきたものです。

やってみる

デバッグ対象のコードは、やっつけですがこんな感じです。ファイル名はmain.goとしました。

package main

import "fmt"

func main() {
   a := 10
   fmt.Printf("Add1(10) == %d\n", Add1(a))
}

// Add1 ...
func Add1(i int) int {
   return i + 1
}

LLDBでデバッグするために、-gcflags '-N -l' というオプションをつけてビルドします。

$ go build -gcflags '-N -l' main.go
$ ls
main    main.go

lldbコマンドに作成されたファイルを渡してみます。

$ lldb main
(lldb) target create "main"
Current executable set to 'main' (x86_64).
(lldb) 

ここから先はlldbの操作になります。とりあえず q と打つとlldbから抜けられることだけは覚えてください。

デバッグを開始するには run または r と打ちます。

(lldb) run
Process 22044 launched: '/Users/kmtr/misc/c/main' (x86_64)
Add1(10) == 11
Process 22044 exited with status = 0 (0x00000000) 
(lldb)  

無事実行されました。
これではデバッグにならないので、ブレイクポイントを打ちます。
試しに6行目と12行目に打ってみます。ブレイクポイントを打つ方法はいくつかありますが、行番号指定の場合 b ソースファイル名:行番号 が楽です。

(lldb) b main.go:6
Breakpoint 1: where = main`main.main + 31 at main.go:6, address = 0x000000000000205f
(lldb) b main.go:12
Breakpoint 2: where = main`main.Add1 + 9 at main.go:12, address = 0x0000000000002199
(lldb) 

br list もしくは b と打つと、現在のブレイクポイントの一覧が表示されます。
br delete ブレイクポイント番号 で対象のブレイクポイントを削除できます。
2番のブレイクポイントを消した後、再度ブレイクポイントを一覧表示して削除されることを確認してみてください。

ブレイクポイントを打った状態で再び run すると、こんな感じに止まります。

   3    import "fmt"
   4    
   5    func main() {
-> 6        a := 10
   7        fmt.Printf("Add1(10) == %d\n", Add1(a))
   8    }
   9    
(lldb)      

ステップオーバーは n です。打ってみるとカーソルが7行目に移ると思います。fr v 変数名 で変数の中身を表示できるので打ってみます。

(lldb) fr v a
(long) a = 10
(lldb) 

なぜかlongですが、とりあえずの確認には十分です。
現在のブレイクポイント周辺のソースを再表示する場合は f と打ちます。

ソースレベルでのステップインは s です。7行目で実行すると次のようにAdd1関数の中に入ると思います。

   9    
   10   // Add1 ...
   11   func Add1(i int) int {
-> 12       return i + 1
   13   }
(lldb) 

fr v と変数名を指定せずに打つと、現在のフレームの変数が全て表示されます。

(lldb) fr v
(long) i = 10
(long) ~r1 = 0
(lldb) 

(~r1 てなんだろう、、、)

c と打つと、次のブレイクポイント、もしくは終了するまで停止せずに実行されます。

(lldb) c
Process 22103 resuming
Add1(10) == 11
Process 22103 exited with status = 0 (0x00000000) 
(lldb) 

LLDBの使い方は、The LLDB Debugger のgdbとの比較がわかりやすいです。
watchが効かないという話も見かけましたが、少なくとも私の環境では問題ありませんでした。

感想

少ししか使っていないので、どこまでちゃんと動くのか、GDBとの差がどれだけあるかわからないけど、LLDBでもデバッグはできそうです。

続くかもしれない。

0 件のコメント: