kenshin

mac下用gdb调试Go程序

| Comments

安装gdb

MAC OS X安装Xcode时,会带一个6.x版本的gdb,只支持DWARF2。 而Go的编译文件默认是包含 DWARFv3 调试信息,因此需要升级gdb版本到7.1或以上。 安装步骤:

1
2
3
4
5
6
$ curl -O http://ftp.gnu.org/gnu/gdb/gdb-7.3.1.tar.gz
$ tar -xzf gdb-3.7.1.tar.gzma
$ cd gdb-7.3.1
$ ./configure
$ make
$ [sudo] make install 

通过上面的步骤安装完后,gdb7.3 会安装到/usr/local/bin/gdb,原来的gdb 6.x在/usr/bin/gdb。 这个时候直接执行gdb,默认使用的还是gdb 6.x(依赖于你的$PATH设置)。如果想显示调用gdb 7.3就得使用绝对路径, /usr/local/bin/gdb 。因为我需要用Xcode调试iOS程序,所以要保证gdb 6.x依然可用,否则可以用/usr/local/bin/下的gdb 替换/usr/bin下面的,这样每次调用就不需要使用绝对路径了。
剩下的事情就和操作系统无关了。

使用步骤

1 . 编译

1
$ go build -gcflags "-N -l" test.go 关闭内联优化,便于输出调试信息

2 . 进入gdb环境

1
$ sudo /usr/local/bin/gdb test   //默认的gdb是6.X版本,因此要指定路径

3 . 载入golang运行时支持

1
(gdb) source /usr/local/go/src/pkg/runtime/runtime-gdb.py

4 . gdb下一些调试命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(gdb) l main.main    #查看源代码代码

(gdb) b 50            #设置断点

(gdb) info b      #查看断点信息
  Num     Type           Disp Enb Address            What
  1       breakpoint     keep y   0x0000000000002239 in main.main at /Users/kenshin/workspace/gogo/test.go:50

(gdb) run             #运行,直到触发断点中断

(gdb) n           #继续执行下一行

(gdb) s           #进入函数/方法

(gdb) info locals   #查看局部变量ma
    err = {tab = 0x0, data = 0xc2000bdfc0}

(gdb) info args   #查看参数
    s = 0xc2000b6f00
    addr = "0.0.0.0:8000"

(gdb) help info   

(gdb) p addr      #打印变量
    $6 = "0.0.0.0:8000"

(gdb) c           #继续执行,直到下一个断点

(gdb) whatis s        #查看变量类型
    type = struct github.com/hoisie/web.Server *

(gdb) where/bt        #查看堆栈信息,判断函数调用关系

      #0  net.resolveInternetAddr (net="udp4") at /usr/local/go/src/pkg/net/ipsock.go:164
      #1  in net.ResolveUDPAddr (net="udp4") at /usr/local/go/src/pkg/net/udpsock.go:45
      #2  in main.SocketListen (ip="127.0.0.1") at /Users/kenshin/workspace/gor/test.go:13

(gdb) up          #回到上一层调用函数
      #0  in net.ResolveUDPAddr (net="udp4") at /usr/local/go/src/pkg/net/udpsock.go:45
      #1  in main.SocketListen (ip="127.ma0.0.1") at /Users/kenshin/workspace/gor/test.go:13

(gdb) down            #再进入下一层函数
      #0  net.resolveInternetAddr (net="udp4") at /usr/local/go/src/pkg/net/ipsock.go:164
      #1  in net.ResolveUDPAddr (net="udp4") at /usr/local/go/src/pkg/net/udpsock.go:45
      #2  in main.SocketListen (ip="127.0.0.1") at /Users/kenshin/workspace/gor/test.go:13

(gdb) shell           #输入shell,可以进入到shell,输入exit退出shell回到gdb环境
      bash-3.2# exit

通过gdb也可以看到go定义的数据类型底层的实现机制,例如string类型,可以对应到C里面的一个结构体,结构体包含两个属性str和len。 str是一个指向字符数组的指针,len是这个数组的长度。

1
2
3
4
5
6
(gdb) p r   # r string := "process"
$16 = {str = 0x2f0170 "process", len = 7}  
(gdb) p r->  #可以通过`TAB`获得一些提示
len  str
(gdb) p r->str   
$17 = (uint8 *) 0x2f0170 "process"

更多gdb命令参考 :http://golang.org/doc/gdb

Comments