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.
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
Attempts to use gdb resulted in a couple issues that proved to be surmountable.
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
gdb Main no longer says there are “no debugging symbols found”.
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:
/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.