From 3e26862c1a0c83503d08696b2ceef131755626b3 Mon Sep 17 00:00:00 2001
From: Luuk van Dijk
+This applies to the 6g toolchain. Gccgo has native gdb support. Besides this
+overview you might want to consult the
+GDB manual.
+
+When you compile and link your Go programs with the 6g/6l or 8g/8l toolchains
+on Linux, Mac OSX or FreeBSD, the resulting binaries contain DWARFv3
+debugging information that recent versions (>7.1) of the GDB debugger can
+use to inspect a live process or a core dump.
+
+Pass the
+A recent extension mechanism to GDB allows it to load extension scripts for a
+given binary. The tool chain uses this to extend GDB with a handful of
+commands to inspect internals of the runtime code (such as goroutines) and to
+pretty print the built-in map, slice and channel types.
+ Known issue: GDB canât automatically find the dynamic
+type of an interface value if its long name differs from its short name
+(annoying when printing stacktraces, the pretty printer falls back to printing
+the short type name and a pointer).
+If you'd like to see how this works, or want to extend it, take a look at src/pkg/runtime/runtime-gdb.py in
+the Go source distribution. It depends on some special magic types
+(
+In this tutorial we will inspect the binary of the
+regexp package's unit tests. To build the binary,
+change to
+Launch GDB, debugging
+The message
+To help GDB find the Go runtime sources and the accompanying support script,
+pass your
+If for some reason GDB still can't find that directory or that script, you can load
+it by hand by telling gdb (assuming you have the go sources in
+
+
+
+Use the
+List a specific part of the source parametrizing
+List a specific file and line number:
+
+Variable and function names must be qualified with the name of the packages
+they belong to. The
+Methods must be qualified with the name of their receiver types. For example,
+the
+Variables that shadow other variables are magically suffixed with a number in the debug info.
+Variables referenced by closures will appear as pointers magically prefixed with '&'.
+
+Set a breakpoint at the
+Run the program:
+
+Execution has paused at the breakpoint.
+See which goroutines are running, and what they're doing:
+
+the one marked with the
+Look at the stack trace for where weâve paused the program:
+
+The other goroutine, number 1, is stuck in
+The stack frame shows weâre currently executing the
+The command
+The functionâs arguments:
+
+When printing the argument, notice that itâs a pointer to a
+
+That
+Stepping forward:
+
+We can step into the
+Get a stack trace to see where we are:
+
+Look at the source code:
+
+GDB's pretty printing mechanism is triggered by regexp matches on type names. An example for slices:
+
+Since slices, arrays and strings are not C pointers, GDB can't interpret the subscripting operation for you, but
+you can look inside the runtime representation to do that (tab completion helps here):
+
+The extension functions $len and $cap work on strings, arrays and slices:
+
+Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types
+Interfaces are represented in the runtime as a pointer to a type descriptor and a pointer to a value. The Go GDB runtime extension decodes this and automatically triggers pretty printing for the runtime type. The extension function Introduction
+
+'-s'
flag to the linker to omit the debug information.
+Common Operations
+
+
+
+
+
+(gdb) list
+(gdb) list line
+(gdb) list file.go:line
+(gdb) break line
+(gdb) break file.go:line
+(gdb) disas
+(gdb) bt
+(gdb) frame n
+(gdb) info locals
+(gdb) info args
+(gdb) p variable
+(gdb) whatis variable
+(gdb) info variables regexp
+Go Extensions
+
+
+
+
+(gdb) p var
+(gdb) p $len(var)
+(gdb) p $dtype(var)
+(gdb) iface var
+(gdb) info goroutines
+(gdb) goroutine n cmd
+(gdb) help goroutine
+For example:
+(gdb) goroutine 12 bt
+hash<T,U>
) and variables (runtime.m
and
+runtime.g
) that the linker
+(src/cmd/ld/dwarf.c) ensures are described in
+the DWARF code.
+
+If you're interested in what the debugging information looks like, run
+'objdump -W 6.out
' and browse through the .debug_*
+sections.
+Known Issues
+
+
+
+
+"fmt.Print"
as an unstructured literal with a "."
+that needs to be quoted. It objects even more strongly to method names of
+the form pkg.(*MyType).Meth
.
+"main"
.Tutorial
+
+$GOROOT/src/pkg/regexp
and run gotest
.
+This should produce an executable file named 6.out
.
+Getting Started
+
+6.out
:
+
+$ gdb 6.out
+GNU gdb (GDB) 7.2-gg8
+Copyright (C) 2010 Free Software Foundation, Inc.
+License GPLv 3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+Type "show copying" and "show warranty" for licensing/warranty details.
+This GDB was configured as "x86_64-linux".
+
+Reading symbols from /home/user/go/src/pkg/regexp/6.out...
+done.
+Loading Go Runtime support.
+(gdb)
+
+
+"Loading Go Runtime support"
means that GDB loaded the
+extension from $GOROOT/src/pkg/runtime/runtime-gdb.py
.
+$GOROOT
with the '-d'
flag:
+
+$ gdb 6.out -d $GOROOT
+
+
+~/go/
):
+
+(gdb) source ~/go/src/pkg/runtime/runtime-gdb.py
+Loading Go Runtime support.
+
+
+Inspecting the source
+
+"l"
or "list"
command to inspect source code.
+
+(gdb) l
+
+
+"list"
with a
+function name (it must be qualified with its package name).
+
+(gdb) l main.main
+
+
+
+(gdb) l regexp.go:1
+(gdb) # Hit enter to repeat last command. Here, this lists next 10 lines.
+
+
+
+Naming
+
+Compile
function from the regexp
+package is known to GDB as 'regexp.Compile'
.
+*Regexp
typeâs doParse
method is known as
+'regexp.*Regexp.doParse'
. (Note that the second dot is a "middot,"
+an artifact of Goâs internal representation of methods.)
+Setting breakpoints
+
+TestFind
function:
+
+(gdb) b 'regexp.TestFind'
+Breakpoint 1 at 0x424908: file /home/user/go/src/pkg/regexp/find_test.go, line 148.
+
+
+
+(gdb) run
+Starting program: /home/lvd/g/src/pkg/regexp/6.out
+
+Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+148 func TestFind(t *testing.T) {
+
+
+
+(gdb) info goroutines
+ 1 waiting runtime.gosched
+* 13 running runtime.goexit
+
+
+*
is the current goroutine.
+Inspecting the stack
+
+
+(gdb) bt # backtrace
+#0 regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+#1 0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/pkg/testing/testing.go:156
+#2 0x000000000040df64 in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:242
+#3 0x000000f8404a89c0 in ?? ()
+#4 0x0000000000573720 in ?? ()
+#5 0x0000000000000000 in ?? ()
+
+
+runtime.gosched
, blocked on a channel receive:
+
+(gdb) goroutine 1 bt
+#0 0x000000000040facb in runtime.gosched () at /home/lvd/g/src/pkg/runtime/proc.c:873
+#1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)
+ at /home/lvd/g/src/pkg/runtime/chan.c:342
+#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/lvd/g/src/pkg/runtime/chan.c:423
+#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, os.Error *)} 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/lvd/g/src/pkg/testing/testing.go:201
+#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, os.Error *)} 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
+ at /home/lvd/g/src/pkg/testing/testing.go:168
+#5 0x0000000000400dc1 in main.main () at /home/lvd/g/src/pkg/regexp/_testmain.go:98
+#6 0x00000000004022e7 in runtime.mainstart () at /home/lvd/g/src/pkg/runtime/amd64/asm.s:78
+#7 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
+#8 0x0000000000000000 in ?? ()
+
+
+regexp.TestFind
function, as expected.
+
+(gdb) info frame
+Stack level 0, frame at 0x7ffff7f9ff88:
+ rip = 0x425530 in regexp.TestFind (/home/lvd/g/src/pkg/regexp/find_test.go:148);
+ saved rip 0x430233
+ called by frame at 0x7ffff7f9ffa8
+ source language minimal.
+ Arglist at 0x7ffff7f9ff78, args: t=0xf840688b60
+ Locals at 0x7ffff7f9ff78, Previous frame's sp is 0x7ffff7f9ff88
+ Saved registers:
+ rip at 0x7ffff7f9ff80
+
+
+info locals
lists all variables local to the function and their values, but is a bit
+dangerous to use, since it will also try to print uninitialized variables. Uninitialized slices may cause gdb to try
+to print arbitrary large arrays.
+
+(gdb) info args
+t = 0xf840688b60
+
+
+Regexp
value. Note that GDB has incorrectly put the *
+on the right-hand side of the type name and made up a 'struct' keyword, in traditional C style.
+
+(gdb) p re
+(gdb) p t
+$1 = (struct testing.T *) 0xf840688b60
+(gdb) p t
+$1 = (struct testing.T *) 0xf840688b60
+(gdb) p *t
+$2 = {errors = "", failed = false, ch = 0xf8406f5690}
+(gdb) p *t->ch
+$3 = struct hchan<*testing.T>
+
+
+struct hchan<*testing.T>
is the runtime-internal represntation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
+
+(gdb) n # execute next line
+149 for _, test := range findTests {
+(gdb) # enter is repeat
+150 re := MustCompile(test.pat)
+(gdb) p test.pat
+$4 = ""
+(gdb) p re
+$5 = (struct regexp.Regexp *) 0xf84068d070
+(gdb) p *re
+$6 = {expr = "", prog = 0xf840688b80, prefix = "", prefixBytes = []uint8, prefixComplete = true,
+ prefixRune = 0, cond = 0 '\000', numSubexp = 0, longest = false, mu = {state = 0, sema = 0},
+ machine = []*regexp.machine}
+(gdb) p *re->prog
+$7 = {Inst = []regexp/syntax.Inst = {{Op = 5 '\005', Out = 0, Arg = 0, Rune = []int}, {Op =
+ 6 '\006', Out = 2, Arg = 0, Rune = []int}, {Op = 4 '\004', Out = 0, Arg = 0, Rune = []int}},
+ Start = 1, NumCap = 2}
+
+
+
+String
function call with "s"
:
+
+(gdb) s
+regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/lvd/g/src/pkg/regexp/regexp.go:97
+97 func (re *Regexp) String() string {
+
+
+
+(gdb) bt
+(gdb) bt
+#0 regexp.(*Regexp).String (re=0xf84068d070, noname=void)
+ at /home/lvd/g/src/pkg/regexp/regexp.go:97
+#1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60)
+ at /home/lvd/g/src/pkg/regexp/find_test.go:151
+#2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)
+ at /home/lvd/g/src/pkg/testing/testing.go:156
+#3 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
+....
+
+
+
+(gdb) l
+92 mu sync.Mutex
+93 machine []*machine
+94 }
+95
+96 // String returns the source text used to compile the regular expression.
+97 func (re *Regexp) String() string {
+98 return re.expr
+99 }
+100
+101 // Compile parses a regular expression and returns, if successful,
+
+
+Pretty Printing
+
+
+(gdb) p utf
+$22 = []uint8 = {0 '\000', 0 '\000', 0 '\000', 0 '\000'}
+
+
+
+
+(gdb) p slc
+$11 = []int = {0, 0}
+(gdb) p slc-><TAB>
+array slc len
+(gdb) p slc->array
+$12 = (int *) 0xf84057af00
+(gdb) p slc->array[1]
+$13 = 0
+
+
+
+
+(gdb) p $len(utf)
+$23 = 4
+(gdb) p $cap(utf)
+$24 = 4
+
+
+hash<int,string>*
. Dereferencing will trigger prettyprinting
+$dtype
decodes the dynamic type for you (examples are taken from a breakpoint at regexp.go
line 293.)
+
+(gdb) p i
+$4 = {str = "cbb"}
+(gdb) whatis i
+type = regexp.input
+(gdb) p $dtype(i)
+$26 = (struct regexp.inputBytes *) 0xf8400b4930
+(gdb) iface i
+regexp.input: struct regexp.inputBytes *
+
diff --git a/doc/docs.html b/doc/docs.html
index e25a538149..c42116a30c 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -188,6 +188,11 @@ one goroutine can be guaranteed to observe values produced by writes to the
same variable in a different goroutine.
+Using GDB to debug Go programs. +
+