使用Golang代码调试器gdb, 了解interface的存储结构

Golang语言的接口实现是隐式声明,目标类只要实现接口定义的所有方法,就被视为实现了接口。接口使用了一个名为itab的结构存储运行期所需的相关类型信息。现在利用gdb调试器来查看结构存储的具体内容。

调试器gdb

gdb7.x版本支持golang语言,首先下载gdb并安装就可以进行调试。下面介绍下mac下如何安装gdb并授权。

安装gdb

brew install gdb
Alt text

mac上安装完成dgb后,dgb默认是没有读取其它进程的权限,需要安装授权证书赋予权限。

打开Keychain Access,创建新证书。没有截取图片的按默认选择下一步。
Alt text

Alt text

Alt text

创建证书后,Get info中修改授权
Alt text

授权gdb,好了现在可以使用gdb调试我们的golang代码了。

1
2
3
sudo killall taskgated
codesign -fs gdb-cert /usr/local/bin/gdb
launchctl load /System/Library/LaunchDaemons/com.apple.taskgated.plist

Golang接口的存储结构

1
2
3
4
5
6
7
8
9
10
type iface struct {
tab *itab //类型信息
data unsafe.Pointer //实际对象指针
}

type itab struct {
inter *interfacetype //接口类型
_type *_type //实际对象类型
fun [1]uintptr //实际对象方法地址
}

接口示例

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
package main

type Ner interface {
a()
b(int)
c(string) string
}

type N int

func (N) a() {
}

func (*N) b(int) {
}

func (*N) c(string) string {
return ""
}

func main() {
var n N
var ner Ner = &n

ner.a()
}

编译

编译Go程序的时候需要注意以下几点

  1. 传递参数-ldflags “-s”,忽略debug的打印信息
  2. 传递-gcflags “-N -l” 参数,这样可以忽略Go内部做的一些优化,聚合变量和函数等优化,这样对于GDB调试来说非常困难,所以在编译的时候加入这两个参数避免这些优化。

编译示例代码go build -gcflags "-N -l" -ldflags "-s" main.go,目录下生成main可执行文件

gdb调试

1
gdb main

Alt text

Alt text

如图,gdb打印出了接口的结构。你也去试试吧。

关于gdb

引入官方gdb说明

GDB does not understand Go programs well. The stack management, threading, and runtime contain aspects that differ enough from the execution model GDB expects that they can confuse the debugger, even when the program is compiled with gccgo. As a consequence, although GDB can be useful in some situations, it is not a reliable debugger for Go programs, particularly heavily concurrent ones. Moreover, it is not a priority for the Go project to address these issues, which are difficult. In short, the instructions below should be taken only as a guide to how to use GDB when it works, not as a guarantee of success.
In time, a more Go-centric debugging architecture may be required.

golang官网说gdb能解决大部情况的调试,在对大并发的情况有可能达不到期望。下一篇文章将介绍delve调试器