mirror of
https://github.com/golang/go
synced 2024-11-24 23:07:56 -07:00
doc/debugging_with_gdb: format & content update
R=adg, lvd CC=golang-dev https://golang.org/cl/5845065
This commit is contained in:
parent
8521811cde
commit
9dbfda5857
@ -13,13 +13,14 @@ Besides this overview you might want to consult the
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
When you compile and link your Go programs with the <code>gc</code> toolchain
|
When you compile and link your Go programs with the <code>gc</code> toolchain
|
||||||
on Linux, Mac OSX or FreeBSD, the resulting binaries contain DWARFv3
|
on Linux, Mac OS X or FreeBSD, the resulting binaries contain DWARFv3
|
||||||
debugging information that recent versions (>7.1) of the GDB debugger can
|
debugging information that recent versions (>7.1) of the GDB debugger can
|
||||||
use to inspect a live process or a core dump.
|
use to inspect a live process or a core dump.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Pass the <code>'-s'</code> flag to the linker to omit the debug information.
|
Pass the <code>'-s'</code> flag to the linker to omit the debug information
|
||||||
|
(for example, <code>go build -ldflags "-s" prog.go</code>).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ Pass the <code>'-s'</code> flag to the linker to omit the debug information.
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
Show file and line number for code
|
Show file and line number for code
|
||||||
and set breakpoints:
|
, set breakpoints and disassemble:
|
||||||
<pre>(gdb) <b>list</b>
|
<pre>(gdb) <b>list</b>
|
||||||
(gdb) <b>list <i>line</i></b>
|
(gdb) <b>list <i>line</i></b>
|
||||||
(gdb) <b>list <i>file.go</i>:<i>line</i></b>
|
(gdb) <b>list <i>file.go</i>:<i>line</i></b>
|
||||||
@ -37,7 +38,7 @@ and set breakpoints:
|
|||||||
(gdb) <b>disas</b></pre>
|
(gdb) <b>disas</b></pre>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Unwind stack frames:
|
Show backtraces and unwind stack frames:
|
||||||
<pre>(gdb) <b>bt</b>
|
<pre>(gdb) <b>bt</b>
|
||||||
(gdb) <b>frame <i>n</i></b></pre>
|
(gdb) <b>frame <i>n</i></b></pre>
|
||||||
</li>
|
</li>
|
||||||
@ -101,7 +102,7 @@ the Go source distribution. It depends on some special magic types
|
|||||||
<code>runtime.g</code>) that the linker
|
<code>runtime.g</code>) that the linker
|
||||||
(<a href="/src/cmd/ld/dwarf.c">src/cmd/ld/dwarf.c</a>) ensures are described in
|
(<a href="/src/cmd/ld/dwarf.c">src/cmd/ld/dwarf.c</a>) ensures are described in
|
||||||
the DWARF code.
|
the DWARF code.
|
||||||
</ines
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If you're interested in what the debugging information looks like, run
|
If you're interested in what the debugging information looks like, run
|
||||||
@ -128,26 +129,26 @@ the form <code>pkg.(*MyType).Meth</code>.
|
|||||||
<p>
|
<p>
|
||||||
In this tutorial we will inspect the binary of the
|
In this tutorial we will inspect the binary of the
|
||||||
<a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary,
|
<a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary,
|
||||||
change to <code>$GOROOT/src/pkg/regexp</code> and run <code>gotest</code>.
|
change to <code>$GOROOT/src/pkg/regexp</code> and run <code>go test -c</code>.
|
||||||
This should produce an executable file named <code>6.out</code>.
|
This should produce an executable file named <code>regexp.test</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Getting_Started">Getting Started</h3>
|
<h3 id="Getting_Started">Getting Started</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Launch GDB, debugging <code>6.out</code>:
|
Launch GDB, debugging <code>regexp.test</code>:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
$ <b>gdb 6.out</b>
|
$ <b>gdb regexp.test</b>
|
||||||
GNU gdb (GDB) 7.2-gg8
|
GNU gdb (GDB) 7.2-gg8
|
||||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
License GPLv 3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
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.
|
Type "show copying" and "show warranty" for licensing/warranty details.
|
||||||
This GDB was configured as "x86_64-linux".
|
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.
|
done.
|
||||||
Loading Go Runtime support.
|
Loading Go Runtime support.
|
||||||
(gdb)
|
(gdb)
|
||||||
@ -164,7 +165,7 @@ pass your <code>$GOROOT</code> with the <code>'-d'</code> flag:
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
$ <b>gdb 6.out -d $GOROOT</b>
|
$ <b>gdb regexp.test -d $GOROOT</b>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -217,14 +218,13 @@ package is known to GDB as <code>'regexp.Compile'</code>.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Methods must be qualified with the name of their receiver types. For example,
|
Methods must be qualified with the name of their receiver types. For example,
|
||||||
the <code>*Regexp</code> type’s <code>doParse</code> method is known as
|
the <code>*Regexp</code> type’s <code>String</code> method is known as
|
||||||
<code>'regexp.*Regexp.doParse'</code>. (Note that the second dot is a "middot,"
|
<code>'regexp.(*Regexp).String'</code>.
|
||||||
an artifact of Go’s internal representation of methods.)
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Variables that shadow other variables are magically suffixed with a number in the debug info.
|
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 '&'.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="Setting_breakpoints">Setting breakpoints</h3>
|
<h3 id="Setting_breakpoints">Setting breakpoints</h3>
|
||||||
@ -244,7 +244,7 @@ Run the program:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(gdb) <b>run</b>
|
(gdb) <b>run</b>
|
||||||
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
|
Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
|
||||||
148 func TestFind(t *testing.T) {
|
148 func TestFind(t *testing.T) {
|
||||||
@ -287,16 +287,18 @@ The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(gdb) <b>goroutine 1 bt</b>
|
(gdb) <b>goroutine 1 bt</b>
|
||||||
#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)
|
#1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)
|
||||||
at /home/lvd/g/src/pkg/runtime/chan.c:342
|
at /home/user/go/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
|
#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/lvd/g/src/pkg/testing/testing.go:201
|
#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)}
|
||||||
#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)} 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
|
0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/pkg/testing/testing.go:201
|
||||||
at /home/lvd/g/src/pkg/testing/testing.go:168
|
#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)}
|
||||||
#5 0x0000000000400dc1 in main.main () at /home/lvd/g/src/pkg/regexp/_testmain.go:98
|
0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
|
||||||
#6 0x00000000004022e7 in runtime.mainstart () at /home/lvd/g/src/pkg/runtime/amd64/asm.s:78
|
at /home/user/go/src/pkg/testing/testing.go:168
|
||||||
#7 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
|
#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 ?? ()
|
#8 0x0000000000000000 in ?? ()
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -307,7 +309,7 @@ The stack frame shows we’re currently executing the <code>regexp.TestFind</cod
|
|||||||
<pre>
|
<pre>
|
||||||
(gdb) <b>info frame</b>
|
(gdb) <b>info frame</b>
|
||||||
Stack level 0, frame at 0x7ffff7f9ff88:
|
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
|
saved rip 0x430233
|
||||||
called by frame at 0x7ffff7f9ffa8
|
called by frame at 0x7ffff7f9ffa8
|
||||||
source language minimal.
|
source language minimal.
|
||||||
@ -346,12 +348,12 @@ $1 = (struct testing.T *) 0xf840688b60
|
|||||||
$1 = (struct testing.T *) 0xf840688b60
|
$1 = (struct testing.T *) 0xf840688b60
|
||||||
(gdb) p *t
|
(gdb) p *t
|
||||||
$2 = {errors = "", failed = false, ch = 0xf8406f5690}
|
$2 = {errors = "", failed = false, ch = 0xf8406f5690}
|
||||||
(gdb) p *t->ch
|
(gdb) p *t->ch
|
||||||
$3 = struct hchan<*testing.T>
|
$3 = struct hchan<*testing.T>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
That <code>struct hchan<*testing.T></code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
|
That <code>struct hchan<*testing.T></code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -384,7 +386,7 @@ We can step into the <code>String</code>function call with <code>"s"</code>:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(gdb) <b>s</b>
|
(gdb) <b>s</b>
|
||||||
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 {
|
97 func (re *Regexp) String() string {
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -394,14 +396,13 @@ Get a stack trace to see where we are:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(gdb) <b>bt</b>
|
(gdb) <b>bt</b>
|
||||||
(gdb) bt
|
|
||||||
#0 regexp.(*Regexp).String (re=0xf84068d070, noname=void)
|
#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)
|
#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)
|
#2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)
|
||||||
at /home/lvd/g/src/pkg/testing/testing.go:156
|
at /home/user/go/src/pkg/testing/testing.go:156
|
||||||
#3 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
|
#3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243
|
||||||
....
|
....
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -442,7 +443,7 @@ you can look inside the runtime representation to do that (tab completion helps
|
|||||||
|
|
||||||
(gdb) <b>p slc</b>
|
(gdb) <b>p slc</b>
|
||||||
$11 = []int = {0, 0}
|
$11 = []int = {0, 0}
|
||||||
(gdb) <b>p slc-></b><i><TAB></i>
|
(gdb) <b>p slc-></b><i><TAB></i>
|
||||||
array slc len
|
array slc len
|
||||||
(gdb) <b>p slc->array</b>
|
(gdb) <b>p slc->array</b>
|
||||||
$12 = (int *) 0xf84057af00
|
$12 = (int *) 0xf84057af00
|
||||||
@ -463,7 +464,7 @@ $24 = 4
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types <code>hash<int,string>*</code>. Dereferencing will trigger prettyprinting
|
Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types <code>hash<int,string>*</code>. Dereferencing will trigger prettyprinting
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
Loading…
Reference in New Issue
Block a user