GO可以说是近年来最流行的新兴语言之一。 通常人们一听到分布式数据和大数据就会想到GO。 本文主要是编译go的源码,然后搭建gdb的调试环境。
源代码是Google官方的实现的1.10.2版本, 不适用于其他版本和gccgo等其他实现,
运行环境是CentOS Linux release 7.5.1804.
编译golang源码
go的源码是用go编写的,编译时也需要一个可运行的go。
首先gdb 源码编译,我们从官网下载源代码和补码文件。
go1.10.2.src.tar.gz
go1.10.2.linux-amd64.tar.gz
注意两个压缩包解压后的文件夹名称都是go,所以不要解压在同一个目录下。 go环境的安装可以参考我之前的一篇文章——Centos7VScode golang开发环境搭建,这里不再赘述。
我的go环境安装解压路径(就是上面的go二进制文件的解压路径):
/home/james/opt/go
上面的go源码的解压路径:
/home/james/workspace/go_src
为了方便我把解压之后的文件夹重命名为go_src。
编译go之前需要设置环境变量:
GOROOT_BOOTSTRAP是go二进制补码文件夹所在目录,
GO_GCFLAGS是编译go时使用的参数。
export GOROOT_BOOTSTRAP=~/opt/go
export GO_GCFLAGS="-N -l"
这里的-N参数表示严格禁止优化gdb 源码编译,-l参数表示严格禁止内联。 Go在编译目标程序时,会嵌入运行时(runtime)的二补码。
严格禁止优化和内联可以使运行时的函数看起来更容易调试。
一切都规划好后,就可以进入go源码文件夹(/home/james/workspace/go_src)并执行all.bash编译:
等待几分钟,编译结果在/home/james/workspace/go_src/bin下,注意你自己的目录可能和我的不一样。 :
调试golang源代码
下面我们使用gdb来调试,以下面的源码(hello.go)为例:
package main
import "fmt"
func main() {
var c int = 0
a,b := 1,2
c = a + b
fmt.Printf("c : %dn",c);
fmt.Printf("Hello Wroldn")
}
使用以下命令编译源码,这里的-l参数含义和之前一样,如果需要可以添加-N参数:
/home/james/workspace/go_src/bin/go build -gcflags "-l" hello.go
编译完成后,使用gdb运行:
gdb ./hello
go上面函数符号名的命名规则就是包名。 函数名,比如main函数的符号名是main.main,运行时newobject的符号名是runtime.newobject。
首先在下一个断点后运行到main函数:
可以看到main函数已经成功进入,但是有源码提示。
取出来,根据文件名和行号设置断点:
可以看到,在我使用的环境下,gdb可以正常设置断点,单步执行go代码,但是复制的变量的输出值可能是错误的,虽然没有开启优化。
总结
目前gdb的调试环境简单搭建,待多研究后补充。