From 9dbfda5857ca5481135c960ead3e9bce153cc8b6 Mon Sep 17 00:00:00 2001
From: Shenghou Ma
When you compile and link your Go programs with the
-Pass the
If you're interested in what the debugging information looks like, run
@@ -128,26 +129,26 @@ the form
In this tutorial we will inspect the binary of the
regexp package's unit tests. To build the binary,
-change to
-Launch GDB, debugging gc
toolchain
-on Linux, Mac OSX or FreeBSD, the resulting binaries contain DWARFv3
-debugging information that recent versions (>7.1) of the GDB debugger can
+on Linux, Mac OS X 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.
'-s'
flag to the linker to omit the debug information.
+Pass the '-s'
flag to the linker to omit the debug information
+(for example, go build -ldflags "-s" prog.go
).
'-s'
flag to the linker to omit the debug information.
(gdb) list
(gdb) list line
(gdb) list file.go:line
@@ -37,7 +38,7 @@ and set breakpoints:
(gdb) disas
(gdb) bt
(gdb) frame n
runtime.g
) that the linker
(src/cmd/ld/dwarf.c) ensures are described in
the DWARF code.
-
pkg.(*MyType).Meth
.
$GOROOT/src/pkg/regexp
and run gotest
.
-This should produce an executable file named 6.out
.
+change to $GOROOT/src/pkg/regexp
and run go test -c
.
+This should produce an executable file named regexp.test
.
Getting Started
6.out
:
+Launch GDB, debugging regexp.test
:
-$ gdb 6.out
+$ gdb regexp.test
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...
+Reading symbols from /home/user/go/src/pkg/regexp/regexp.test...
done.
Loading Go Runtime support.
(gdb)
@@ -164,7 +165,7 @@ pass your
$GOROOT
with the '-d'
flag:
-$ gdb 6.out -d $GOROOT +$ gdb regexp.test -d $GOROOT
@@ -217,14 +218,13 @@ package is known to GDB as 'regexp.Compile'
.
Methods must be qualified with the name of their receiver types. For example,
-the *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.)
+the *Regexp
type’s String
method is known as
+'regexp.(*Regexp).String'
.
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 '&'. +Variables referenced by closures will appear as pointers magically prefixed with '&'.
(gdb) run -Starting program: /home/lvd/g/src/pkg/regexp/6.out +Starting program: /home/user/go/src/pkg/regexp/regexp.test Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148 148 func TestFind(t *testing.T) { @@ -287,16 +287,18 @@ The other goroutine, number 1, is stuck inruntime.gosched
, blocked(gdb) goroutine 1 bt -#0 0x000000000040facb in runtime.gosched () at /home/lvd/g/src/pkg/runtime/proc.c:873 +#0 0x000000000040facb in runtime.gosched () at /home/user/go/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 *, 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 *, 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 + at /home/user/go/src/pkg/runtime/chan.c:342 +#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/pkg/runtime/chan.c:423 +#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)} + 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/pkg/testing/testing.go:201 +#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)} + 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...}) +at /home/user/go/src/pkg/testing/testing.go:168 +#5 0x0000000000400dc1 in main.main () at /home/user/go/src/pkg/regexp/_testmain.go:98 +#6 0x00000000004022e7 in runtime.mainstart () at /home/user/go/src/pkg/runtime/amd64/asm.s:78 +#7 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243 #8 0x0000000000000000 in ?? ()@@ -307,7 +309,7 @@ The stack frame shows we’re currently executing theregexp.TestFind (gdb) info frame Stack level 0, frame at 0x7ffff7f9ff88: - rip = 0x425530 in regexp.TestFind (/home/lvd/g/src/pkg/regexp/find_test.go:148); + rip = 0x425530 in regexp.TestFind (/home/user/go/src/pkg/regexp/find_test.go:148); saved rip 0x430233 called by frame at 0x7ffff7f9ffa8 source language minimal. @@ -346,12 +348,12 @@ $1 = (struct testing.T *) 0xf840688b60 $1 = (struct testing.T *) 0xf840688b60 (gdb) p *t $2 = {errors = "", failed = false, ch = 0xf8406f5690} -(gdb) p *t->ch -$3 = struct hchan<*testing.T> +(gdb) p *t->ch +$3 = struct hchan<*testing.T>
-That struct hchan<*testing.T>
is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
+That struct hchan<*testing.T>
is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
@@ -384,7 +386,7 @@ We can step into the String
function call with "s"
:
(gdb) s -regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/lvd/g/src/pkg/regexp/regexp.go:97 +regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/user/go/src/pkg/regexp/regexp.go:97 97 func (re *Regexp) String() string {@@ -394,14 +396,13 @@ Get a stack trace to see where we are:
(gdb) bt -(gdb) bt #0 regexp.(*Regexp).String (re=0xf84068d070, noname=void) - at /home/lvd/g/src/pkg/regexp/regexp.go:97 + at /home/user/go/src/pkg/regexp/regexp.go:97 #1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60) - at /home/lvd/g/src/pkg/regexp/find_test.go:151 + at /home/user/go/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 + at /home/user/go/src/pkg/testing/testing.go:156 +#3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243 ....@@ -442,7 +443,7 @@ you can look inside the runtime representation to do that (tab completion helps (gdb) p slc $11 = []int = {0, 0} -(gdb) p slc-><TAB> +(gdb) p slc-><TAB> array slc len (gdb) p slc->array $12 = (int *) 0xf84057af00 @@ -463,7 +464,7 @@ $24 = 4
-Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types hash<int,string>*
. Dereferencing will trigger prettyprinting
+Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types hash<int,string>*
. Dereferencing will trigger prettyprinting