1、加载go语言的gdb调试支持文件
gdb里键入:source go/src/runtime/runtime-gdb.py
加载成功后gdb显示:Loading Go Runtime support.
或者设置为自动加载,有两种方法:
1、放入 /etc/gdbinit.d/ 目录下。
2、在 ~./gdbinit 文件中添加,如:
# 保存历史命令
set history filename ~/.gdb_history
set history save on
# 加载go支持
source ~/go1.18/src/runtime/runtime-gdb.py
如果程序涉及cgo,采用gccgo编译更方便gdb调试,gccgo的编译方式:
export PATH=${gccgo版本的go执行体目录}:$PATH
#share
#go build -compiler gccgo -v -o myexe main.go myxx.go
#static
go build -compiler gccgo -gccgoflags -static-libgo -v -o myexe main.go myxx.go
2、编译go程序时打开调试符号和禁止内联
go build -gcflags "-N -l" xx.go
When compiling Go programs, the following points require particular attention:
- Using
-ldflags "-s"
will prevent the standard debugging information from being printed- Using
-gcflags "-N -l"
will prevent Go from performing some of its automated optimizations -optimizations of aggregate variables, functions, etc. These optimizations can make it very difficult for GDB to do its job, so it’s best to disable them at compile time using these flags.
查看载入的二进制文件:info files
查看载入的源码文件:info sources
查看载入的函数列表:info functions
查看载入的动态库列表:info sharedlibrary
对于go test单测,可以编译为bin再调试:
CGO_ENABLED=1 CGO_CXXFLAGS=-g CGO_CFLAGS=-g go test -c xxx_test.go `ls *go | grep -v main.go | grep -v xxx_test.go` -o test
./test -test.v -test.timeout=20m -test.run Testxxx
gdb -p `pidof test`
3、为golang新增的命令和函数
新增的命令会出现在 help info 里。
新增的函数会出现在 help function 里。
比如使用新增的cap函数:
p $cap(slicea)
4、查看协程和线程
info goroutines
info threads
在某个协程上执行gdb命令,比如查看2号协程的栈帧:
goroutine 2 bt
切换当前线程:
thread {线程号}
5、查看变量
slice:
len:p $len(slicea)
cap:p $cap(slicea)
array:p slicea.array[0]
搜索变量包名:
info variables varname
全局变量:
p pkgname.varname
p 'path1/path2/pkgname.varname'
也可以通过bin文件查看:
nm -D bin_file
局部变量:
info local
p var
动态环境变量:
p 'syscall.envs'
p 'syscall.envs'.array[0]
静态环境变量:
show env
6、go用户程序入口断点
b main.main
7、其他常用断点
lock:
b runtime.futex
channel:
b runtime.chansend
b runtime.chanrecv
调度:
b runtime.schedule
b runtime.save
b runtime.newm
b runtime.newproc
b runtime.osyield
b runtime.pidleput
b runtime.stopm
系统调用:
b syscall.read
b syscall.write
b syscall.Syscall
b syscall.Syscall6
b syscall.RawSyscall
b syscall.RawSyscall6
b runtime.entersyscall
b runtime.exitsyscall
b runtime.Gosched
显示可打断点的文件:
info sources
显示可打断点的函数:
info functions
8、查看运行时
p 'runtime.ncpu'
p 'runtime.gomaxprocs'
p 'runtime.allp'
p 'runtime.allp'.__count
p (*('runtime.allp'.__values[0])).status
p 'runtime.allm'.park
p 'runtime.allgs'
p 'runtime.allgs'.__count
p (*('runtime.allgs'.__values[0])).goid
p (*('runtime.allgs'.__values[0])).atomicstatus
p (*('runtime.allgs'.__values[0])).waitreason
p (*('runtime.allgs'.__values[0])).lockedm
p *'runtime.g'
p 'runtime.g'.atomicstatus
p 'runtime.g'.waitreason
p 'runtime.g'.lockedm
p *'runtime.g'.m
p 'runtime.g'.m.park
p 'runtime.g'.m.blocked
p 'runtime.g'.m.locks
p 'runtime.g'.m.spinning
p 'runtime.g'.m.procid
p 'runtime.g'.m.incgo
p 'runtime.g'.m.ncgocall
p 'runtime.g'.m.ncgo
p 'runtime.g'.m.lockedg
遇到的问题:
1、gdb显示Dwarf Error:
Dwarf Error: wrong version in compilation unit header (is 0, should be 2, 3, or 4)
Python Exception <class 'gdb.error'> Attempt to extract a component of a value that is not a (null).
解决办法:升级gdb到8,如el7升级到gdb8,按如下操作:
yum安装:
yum -y install centos-release-scl
yum-config-manager --enable rhel-server-rhscl-7-rpms
yum -y install devtoolset-7
scl enable devtoolset-7 bash
rpm安装:
rpm包下载地址:https://centos.pkgs.org/7/centos-sclo-rh-x86_64/devtoolset-7-gdb-8.0.1-36.el7.x86_64.rpm.html
yum provides semanage
yum install policycoreutils-python-2.5-34.el7.x86_64
rpm -i scl-utils-20130529-19.el7.x86_64.rpm
rpm -i devtoolset-7-runtime-7.1-4.el7.x86_64.rpm
rpm -i devtoolset-7-gdb-8.0.1-36.el7.x86_64.rpm
mv /bin/gdb /bin/gdb.old
ln -s /opt/rh/devtoolset-7/root/usr/bin/gdb /bin/gdb
--end--