Although “GDB does not understand Go programs well.” (from Debugging Go Code with GDB), sometimes gdb
is still a useful tool for debugging Golang
program. In this post, I will show some small tips.
(1)
My OS is Ubuntu 14.04
. Launching gdb
, it prompts following things:
......
warning: File "/usr/local/go/src/runtime/runtime-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
add-auto-load-safe-path /usr/local/go/src/runtime/runtime-gdb.py
line to your configuration file "/home/nan/.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/home/nan/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
......
So I add “add-auto-load-safe-path /usr/local/go/src/runtime/runtime-gdb.py
” in my .gdbinit
file. My preferred .gdbinit
file is like this:
$ cat ${HOME}/.gdbinit
add-auto-load-safe-path /usr/local/go/src/runtime/runtime-gdb.py
set confirm off
set print pretty on
(2)
If you want to set breakpoint on the start of main
function, you should use “b main.main
“:
......
(gdb) b main.main
Breakpoint 1 at 0x4021e0: file /home/nan/kubernetes/_output/local/go/src/k8s.io/kubernetes/cmd/kubectl/kubectl.go, line 26.
(gdb) r
Starting program: /home/nan/kubernetes/_output/local/go/bin/kubectl
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff77f6700 (LWP 957)]
[New Thread 0x7ffff6fb5700 (LWP 958)]
[New Thread 0x7ffff5fb3700 (LWP 960)]
[New Thread 0x7ffff67b4700 (LWP 959)]
Breakpoint 1, main.main () at /home/nan/kubernetes/_output/local/go/src/k8s.io/kubernetes/cmd/kubectl/kubectl.go:26
26 func main() {
......
Not “b main
“, except you want to read mysterious assembly code:
......
(gdb) b main
Breakpoint 1 at 0x45e830: file /usr/local/go/src/runtime/rt0_linux_amd64.s, line 63.
(gdb) r
Starting program: /home/nan/kubernetes/_output/local/go/bin/kubectl
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main () at /usr/local/go/src/runtime/rt0_linux_amd64.s:63
63 MOVQ $runtime·rt0_go(SB), AX
(gdb)
......
(3)
If you don’t know the symbol name of a function, you can use readelf
tool. E.g.:
$ readelf -s -W /home/nan/kubernetes/_output/local/go/bin/kubectl | grep NewCmdConfig
......
14350: 0000000000766da0 3168 FUNC LOCAL DEFAULT 14 k8s.io/kubernetes/pkg/kubectl/cmd/config.NewCmdConfig
......
14404: 00000000007745d0 48 FUNC LOCAL DEFAULT 14 k8s.io/kubernetes/pkg/kubectl/cmd/config.NewCmdConfig.func1
The config.NewCmdConfig.func1
is the function which is defined in NewCmdConfig
function:
func NewCmdConfig(pathOptions *PathOptions, out io.Writer) *cobra.Command {
......
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
......
}
Then you can set breakpoint for wanted function:
......
(gdb) b k8s.io/kubernetes/pkg/kubectl/cmd/config.NewCmdConfig
Breakpoint 1 at 0x766da0: file /home/nan/kubernetes/_output/local/go/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go, line 63.
(gdb) r
Starting program: /home/nan/kubernetes/_output/local/go/bin/kubectl
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff77f6700 (LWP 1416)]
[New Thread 0x7ffff6fb5700 (LWP 1417)]
[New Thread 0x7ffff67b4700 (LWP 1418)]
[New Thread 0x7ffff5fb3700 (LWP 1419)]
Breakpoint 1, k8s.io/kubernetes/pkg/kubectl/cmd/config.NewCmdConfig (pathOptions=0xc820178b90, out=..., ~r2=0x1)
at /home/nan/kubernetes/_output/local/go/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go:63
63 func NewCmdConfig(pathOptions *PathOptions, out io.Writer) *cobra.Command {
(gdb)
......