| # Debugging Go code (a status report) | |
| 2 Nov 2010 | |
| Tags: debug, gdb | |
| Summary: What works and what doesn't when debugging Go programs with GDB. | |
| OldURL: /debugging-go-code-status-report | |
| Luuk van Dijk | |
| ## | |
| When it comes to debugging, nothing beats a few strategic print statements | |
| to inspect variables or a well-placed panic to obtain a stack trace. | |
| However, sometimes you’re missing either the patience or the source code, | |
| and in those cases a good debugger can be invaluable. | |
| That's why over the past few releases we have been improving the support | |
| in Go’s gc linker (6l, | |
| 8l) for GDB, the GNU debugger. | |
| In the latest release (2010-11-02), the 6l and 8l linkers emit DWARF3 debugging | |
| information when writing ELF (Linux, | |
| FreeBSD) or Mach-O (Mac OS X) binaries. | |
| The DWARF code is rich enough to let you do the following: | |
| - load a Go program in GDB version 7.x, | |
| - list all Go, C, and assembly source files by line (parts of the Go runtime are written in C and assembly), | |
| - set breakpoints by line and step through the code, | |
| - print stack traces and inspect stack frames, and | |
| - find the addresses and print the contents of most variables. | |
| There are still some inconveniences: | |
| - The emitted DWARF code is unreadable by the GDB version 6.x that ships with Mac OS X. | |
| We would gladly accept patches to make the DWARF output compatible with | |
| the standard OS X GDB, | |
| but until that’s fixed you’ll need to download, | |
| build, and install GDB 7.x to use it under OS X. | |
| The source can be found at [http://sourceware.org/gdb/download/](http://sourceware.org/gdb/download/). | |
| Due to the particulars of OS X you’ll need to install the binary on a | |
| local file system with `chgrp procmod` and `chmod g+s`. | |
| - Names are qualified with a package name and, | |
| as GDB doesn't understand Go packages, you must reference each item by its full name. | |
| For example, the variable named `v` in package `main` must be referred to | |
| as `'main.v'`, in single quotes. | |
| A consequence of this is that tab completion of variable and function names does not work. | |
| - Lexical scoping information is somewhat obfuscated. | |
| If there are multiple variables of the same name, | |
| the nth instance will have a suffix of the form ‘#n’. | |
| We plan to fix this, but it will require some changes to the data exchanged | |
| between the compiler and linker. | |
| - Slice and string variables are represented as their underlying structure | |
| in the runtime library. | |
| They will look something like `{data = 0x2aaaaab3e320, len = 1, cap = 1}.` For slices, | |
| you must dereference the data pointer to inspect the elements. | |
| Some things don't work yet: | |
| - Channel, function, interface, and map variables cannot be inspected. | |
| - Only Go variables are annotated with type information; the runtime's C variables are not. | |
| - Windows and ARM binaries do not contain DWARF debugging information and, as such, cannot be inspected with GDB. | |
| Over the coming months we intend to address these issues, | |
| either by changing the compiler and linker or by using the Python extensions to GDB. | |
| In the meantime, we hope that Go programmers will benefit from having better | |
| access to this well-known debugging tool. | |
| P.S. The DWARF information can also be read by tools other than GDB. | |
| For example, on Linux you can use it with the sysprof system-wide profiler. |