Debugging Go 1.4.2 code in GDB on OS X
- go-lang
- tips
There are lots of guides and answers when it comes to debugging Go with gdb, but none of them worked for my environment. Here’s what worked.
My Environment
I have Go installed via homebrew brew install go
and have set my GOPATH in ~/.bash_profile
, so this may be specific to
any or all of my environment. Go says my environment is:
Attempts to use delve resulted in the message “Could not launch program: could not acquire mach task 5”
which is likely due to my code not being signed the way OS X wants it to be. Running any dlv
command leaves bash in a
mode where it doesn’t echo input, which doesn’t inspire much confidence, so I’m loath to spend more time trying to get
delve working.
Attempts to use gdb resulted in a couple issues that proved to be surmountable.
Build
When building with go build Main.go
and running via gdb Main
, gdb promptly states “no debugging symbols found”. That’s
not going to be very useful, so we’ll build with debugging symbols:
go build -gcflags "-N -l" Main.go
Alas, loading the resulting executable in gdb still prints “no debugging symbols found”. It turns out we need two additional flags:
-work
will tell go build
to keep the working directory with .o files. Note that you’ll probably need to clean these
up once in a while, since go build
is no longer removing them after building.
-a
will rebuild any packages that have already been built (e.g. without debugging flags). This seems to be necessary
even after the first rebuild with debugging flags.
Now we can build with all the debugging symbols gdb needs,
go build -a -work -gcflags "-N -l" Main.go
and gdb Main
no longer says there are “no debugging symbols found”.
Run
Unfortunately, the r
(run) command in gdb doesn’t yield much success:
(gdb) r Starting program: /Users/jordan/src/go/GoTest1/Main Unable to find Mach task port for process-id 95573: (os/kern) failure (0x5). (please check gdb is codesigned - see taskgated(8))
This can be mitigated in one of two ways:
1
Run as sudo
2
Code-sign gdb, per this SO answer
sudo gdb Main
gets us there quickly enough, at which point you can set breakpoints, but that’s about it.
Loading gdb support for the Go runtime doesn’t work so well:
There are some different approaches to fixing this, but the one that worked for me was based on this patch:
Edit /usr/local/opt/go/libexec/src/runtime/runtime-gdb.py
and comment out (or remove) line 205:
#_rctp_type = gdb.lookup_type("struct runtime._type").pointer()
then change line 216 to:
return go_type_ptr.cast(gdb.lookup_type("struct reflect.rtype").pointer()).dereference()
Now we can load the Go runtime support:
(gdb) source /usr/local/opt/go/libexec/src/runtime/runtime-gdb.py Loading Go Runtime support. (gdb)
and finally start doing some debugging… in as much as the very limited debugging capacity of Go’s gdb support allows.