Andrew Gerrand | 7cb21a7 | 2012-01-19 11:24:54 +1100 | [diff] [blame] | 1 | <!--{ |
Andrew Gerrand | a22b0f8 | 2012-03-05 15:30:27 +1100 | [diff] [blame] | 2 | "Title": "Debugging Go Code with GDB", |
Andrew Gerrand | 98155bd | 2012-03-27 11:42:01 +1100 | [diff] [blame] | 3 | "Path": "/doc/gdb" |
Andrew Gerrand | 7cb21a7 | 2012-01-19 11:24:54 +1100 | [diff] [blame] | 4 | }--> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 5 | |
| 6 | <p><i> |
Alberto Donizetti | 4601eae | 2017-01-09 19:11:58 +0100 | [diff] [blame] | 7 | This applies to the standard toolchain (the <code>gc</code> Go |
| 8 | compiler and tools). Gccgo has native gdb support. |
Andrew Gerrand | 2a5879d | 2012-03-20 13:50:05 +1100 | [diff] [blame] | 9 | Besides this overview you might want to consult the |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 10 | <a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>. |
| 11 | </i></p> |
| 12 | |
Rob Pike | 2674efb | 2014-04-26 10:18:17 -0600 | [diff] [blame] | 13 | <p> |
| 14 | GDB does not understand Go programs well. |
| 15 | The stack management, threading, and runtime contain aspects that differ |
| 16 | enough from the execution model GDB expects that they can confuse |
| 17 | the debugger, even when the program is compiled with gccgo. |
| 18 | As a consequence, although GDB can be useful in some situations, it is |
| 19 | not a reliable debugger for Go programs, particularly heavily concurrent ones. |
| 20 | Moreover, it is not a priority for the Go project to address these issues, which |
| 21 | are difficult. |
| 22 | In short, the instructions below should be taken only as a guide to how |
| 23 | to use GDB when it works, not as a guarantee of success. |
| 24 | </p> |
| 25 | |
| 26 | <p> |
| 27 | In time, a more Go-centric debugging architecture may be required. |
| 28 | </p> |
| 29 | |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 30 | <h2 id="Introduction">Introduction</h2> |
| 31 | |
| 32 | <p> |
Andrew Gerrand | 2a5879d | 2012-03-20 13:50:05 +1100 | [diff] [blame] | 33 | When you compile and link your Go programs with the <code>gc</code> toolchain |
Hana Kim | 0202aa8 | 2017-09-06 16:17:11 -0400 | [diff] [blame^] | 34 | on Linux, Mac OS X, FreeBSD or NetBSD, the resulting binaries contain DWARFv4 |
| 35 | debugging information that recent versions (>7.5) of the GDB debugger can |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 36 | use to inspect a live process or a core dump. |
| 37 | </p> |
| 38 | |
| 39 | <p> |
Shenghou Ma | c91c564 | 2014-04-16 01:19:26 -0400 | [diff] [blame] | 40 | Pass the <code>'-w'</code> flag to the linker to omit the debug information |
| 41 | (for example, <code>go build -ldflags "-w" prog.go</code>). |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 42 | </p> |
| 43 | |
Shenghou Ma | d9c4cef | 2012-07-03 12:50:03 -0400 | [diff] [blame] | 44 | <p> |
| 45 | The code generated by the <code>gc</code> compiler includes inlining of |
| 46 | function invocations and registerization of variables. These optimizations |
| 47 | can sometimes make debugging with <code>gdb</code> harder. To disable them |
| 48 | when debugging, pass the flags <code>-gcflags "-N -l"</code> to the |
| 49 | <a href="/cmd/go"><code>go</code></a> command used to build the code being |
| 50 | debugged. |
| 51 | </p> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 52 | |
Alberto Donizetti | 4601eae | 2017-01-09 19:11:58 +0100 | [diff] [blame] | 53 | <p> |
| 54 | If you want to use gdb to inspect a core dump, you can trigger a dump |
| 55 | on a program crash, on systems that permit it, by setting |
| 56 | <code>GOTRACEBACK=crash</code> in the environment (see the |
| 57 | <a href="/pkg/runtime/#hdr-Environment_Variables"> runtime package |
| 58 | documentation</a> for more info). |
| 59 | </p> |
| 60 | |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 61 | <h3 id="Common_Operations">Common Operations</h3> |
| 62 | |
| 63 | <ul> |
| 64 | <li> |
Robert Hencke | b0c3429 | 2012-10-07 11:24:14 +1100 | [diff] [blame] | 65 | Show file and line number for code, set breakpoints and disassemble: |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 66 | <pre>(gdb) <b>list</b> |
| 67 | (gdb) <b>list <i>line</i></b> |
| 68 | (gdb) <b>list <i>file.go</i>:<i>line</i></b> |
| 69 | (gdb) <b>break <i>line</i></b> |
| 70 | (gdb) <b>break <i>file.go</i>:<i>line</i></b> |
| 71 | (gdb) <b>disas</b></pre> |
| 72 | </li> |
| 73 | <li> |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 74 | Show backtraces and unwind stack frames: |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 75 | <pre>(gdb) <b>bt</b> |
| 76 | (gdb) <b>frame <i>n</i></b></pre> |
| 77 | </li> |
| 78 | <li> |
| 79 | Show the name, type and location on the stack frame of local variables, |
| 80 | arguments and return values: |
| 81 | <pre>(gdb) <b>info locals</b> |
| 82 | (gdb) <b>info args</b> |
| 83 | (gdb) <b>p variable</b> |
| 84 | (gdb) <b>whatis variable</b></pre> |
| 85 | </li> |
| 86 | <li> |
| 87 | Show the name, type and location of global variables: |
| 88 | <pre>(gdb) <b>info variables <i>regexp</i></b></pre> |
| 89 | </li> |
| 90 | </ul> |
| 91 | |
| 92 | |
| 93 | <h3 id="Go_Extensions">Go Extensions</h3> |
| 94 | |
| 95 | <p> |
| 96 | A recent extension mechanism to GDB allows it to load extension scripts for a |
| 97 | given binary. The tool chain uses this to extend GDB with a handful of |
| 98 | commands to inspect internals of the runtime code (such as goroutines) and to |
| 99 | pretty print the built-in map, slice and channel types. |
| 100 | </p> |
| 101 | |
| 102 | <ul> |
| 103 | <li> |
| 104 | Pretty printing a string, slice, map, channel or interface: |
| 105 | <pre>(gdb) <b>p <i>var</i></b></pre> |
| 106 | </li> |
| 107 | <li> |
| 108 | A $len() and $cap() function for strings, slices and maps: |
| 109 | <pre>(gdb) <b>p $len(<i>var</i>)</b></pre> |
| 110 | </li> |
| 111 | <li> |
| 112 | A function to cast interfaces to their dynamic types: |
| 113 | <pre>(gdb) <b>p $dtype(<i>var</i>)</b> |
| 114 | (gdb) <b>iface <i>var</i></b></pre> |
| 115 | <p class="detail"><b>Known issue:</b> GDB can’t automatically find the dynamic |
| 116 | type of an interface value if its long name differs from its short name |
| 117 | (annoying when printing stacktraces, the pretty printer falls back to printing |
| 118 | the short type name and a pointer).</p> |
| 119 | </li> |
| 120 | <li> |
| 121 | Inspecting goroutines: |
| 122 | <pre>(gdb) <b>info goroutines</b> |
| 123 | (gdb) <b>goroutine <i>n</i> <i>cmd</i></b> |
| 124 | (gdb) <b>help goroutine</b></pre> |
| 125 | For example: |
| 126 | <pre>(gdb) <b>goroutine 12 bt</b></pre> |
| 127 | </li> |
| 128 | </ul> |
| 129 | |
| 130 | <p> |
| 131 | If you'd like to see how this works, or want to extend it, take a look at <a |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 132 | href="/src/runtime/runtime-gdb.py">src/runtime/runtime-gdb.py</a> in |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 133 | the Go source distribution. It depends on some special magic types |
| 134 | (<code>hash<T,U></code>) and variables (<code>runtime.m</code> and |
| 135 | <code>runtime.g</code>) that the linker |
Russ Cox | 6e28bf3 | 2016-01-06 15:26:45 -0500 | [diff] [blame] | 136 | (<a href="/src/cmd/link/internal/ld/dwarf.go">src/cmd/link/internal/ld/dwarf.go</a>) ensures are described in |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 137 | the DWARF code. |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 138 | </p> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 139 | |
| 140 | <p> |
| 141 | If you're interested in what the debugging information looks like, run |
Alberto Donizetti | 4601eae | 2017-01-09 19:11:58 +0100 | [diff] [blame] | 142 | '<code>objdump -W a.out</code>' and browse through the <code>.debug_*</code> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 143 | sections. |
| 144 | </p> |
| 145 | |
| 146 | |
| 147 | <h3 id="Known_Issues">Known Issues</h3> |
| 148 | |
| 149 | <ol> |
| 150 | <li>String pretty printing only triggers for type string, not for types derived |
| 151 | from it.</li> |
| 152 | <li>Type information is missing for the C parts of the runtime library.</li> |
| 153 | <li>GDB does not understand Go’s name qualifications and treats |
| 154 | <code>"fmt.Print"</code> as an unstructured literal with a <code>"."</code> |
| 155 | that needs to be quoted. It objects even more strongly to method names of |
| 156 | the form <code>pkg.(*MyType).Meth</code>. |
| 157 | <li>All global variables are lumped into package <code>"main"</code>.</li> |
| 158 | </ol> |
| 159 | |
| 160 | <h2 id="Tutorial">Tutorial</h2> |
| 161 | |
| 162 | <p> |
| 163 | In this tutorial we will inspect the binary of the |
| 164 | <a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary, |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 165 | change to <code>$GOROOT/src/regexp</code> and run <code>go test -c</code>. |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 166 | This should produce an executable file named <code>regexp.test</code>. |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 167 | </p> |
| 168 | |
| 169 | |
| 170 | <h3 id="Getting_Started">Getting Started</h3> |
| 171 | |
| 172 | <p> |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 173 | Launch GDB, debugging <code>regexp.test</code>: |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 174 | </p> |
| 175 | |
| 176 | <pre> |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 177 | $ <b>gdb regexp.test</b> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 178 | GNU gdb (GDB) 7.2-gg8 |
| 179 | Copyright (C) 2010 Free Software Foundation, Inc. |
| 180 | License GPLv 3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> |
| 181 | Type "show copying" and "show warranty" for licensing/warranty details. |
| 182 | This GDB was configured as "x86_64-linux". |
| 183 | |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 184 | Reading symbols from /home/user/go/src/regexp/regexp.test... |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 185 | done. |
| 186 | Loading Go Runtime support. |
| 187 | (gdb) |
| 188 | </pre> |
| 189 | |
| 190 | <p> |
| 191 | The message <code>"Loading Go Runtime support"</code> means that GDB loaded the |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 192 | extension from <code>$GOROOT/src/runtime/runtime-gdb.py</code>. |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 193 | </p> |
| 194 | |
| 195 | <p> |
| 196 | To help GDB find the Go runtime sources and the accompanying support script, |
| 197 | pass your <code>$GOROOT</code> with the <code>'-d'</code> flag: |
| 198 | </p> |
| 199 | |
| 200 | <pre> |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 201 | $ <b>gdb regexp.test -d $GOROOT</b> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 202 | </pre> |
| 203 | |
| 204 | <p> |
| 205 | If for some reason GDB still can't find that directory or that script, you can load |
| 206 | it by hand by telling gdb (assuming you have the go sources in |
| 207 | <code>~/go/</code>): |
Rob Pike | 7ae41e8 | 2013-02-28 13:32:36 -0800 | [diff] [blame] | 208 | </p> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 209 | |
| 210 | <pre> |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 211 | (gdb) <b>source ~/go/src/runtime/runtime-gdb.py</b> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 212 | Loading Go Runtime support. |
| 213 | </pre> |
| 214 | |
| 215 | <h3 id="Inspecting_the_source">Inspecting the source</h3> |
| 216 | |
| 217 | <p> |
| 218 | Use the <code>"l"</code> or <code>"list"</code> command to inspect source code. |
| 219 | </p> |
| 220 | |
| 221 | <pre> |
| 222 | (gdb) <b>l</b> |
| 223 | </pre> |
| 224 | |
| 225 | <p> |
| 226 | List a specific part of the source parametrizing <code>"list"</code> with a |
| 227 | function name (it must be qualified with its package name). |
| 228 | </p> |
| 229 | |
| 230 | <pre> |
| 231 | (gdb) <b>l main.main</b> |
| 232 | </pre> |
| 233 | |
| 234 | <p> |
| 235 | List a specific file and line number: |
| 236 | </p> |
| 237 | |
| 238 | <pre> |
| 239 | (gdb) <b>l regexp.go:1</b> |
| 240 | (gdb) <i># Hit enter to repeat last command. Here, this lists next 10 lines.</i> |
| 241 | </pre> |
| 242 | |
| 243 | |
| 244 | <h3 id="Naming">Naming</h3> |
| 245 | |
| 246 | <p> |
| 247 | Variable and function names must be qualified with the name of the packages |
| 248 | they belong to. The <code>Compile</code> function from the <code>regexp</code> |
| 249 | package is known to GDB as <code>'regexp.Compile'</code>. |
| 250 | </p> |
| 251 | |
| 252 | <p> |
| 253 | Methods must be qualified with the name of their receiver types. For example, |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 254 | the <code>*Regexp</code> type’s <code>String</code> method is known as |
| 255 | <code>'regexp.(*Regexp).String'</code>. |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 256 | </p> |
| 257 | |
| 258 | <p> |
| 259 | Variables that shadow other variables are magically suffixed with a number in the debug info. |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 260 | Variables referenced by closures will appear as pointers magically prefixed with '&'. |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 261 | </p> |
| 262 | |
| 263 | <h3 id="Setting_breakpoints">Setting breakpoints</h3> |
| 264 | |
| 265 | <p> |
| 266 | Set a breakpoint at the <code>TestFind</code> function: |
| 267 | </p> |
| 268 | |
| 269 | <pre> |
| 270 | (gdb) <b>b 'regexp.TestFind'</b> |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 271 | Breakpoint 1 at 0x424908: file /home/user/go/src/regexp/find_test.go, line 148. |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 272 | </pre> |
| 273 | |
| 274 | <p> |
| 275 | Run the program: |
| 276 | </p> |
| 277 | |
| 278 | <pre> |
| 279 | (gdb) <b>run</b> |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 280 | Starting program: /home/user/go/src/regexp/regexp.test |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 281 | |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 282 | Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/regexp/find_test.go:148 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 283 | 148 func TestFind(t *testing.T) { |
| 284 | </pre> |
| 285 | |
| 286 | <p> |
| 287 | Execution has paused at the breakpoint. |
| 288 | See which goroutines are running, and what they're doing: |
| 289 | </p> |
| 290 | |
| 291 | <pre> |
| 292 | (gdb) <b>info goroutines</b> |
| 293 | 1 waiting runtime.gosched |
| 294 | * 13 running runtime.goexit |
| 295 | </pre> |
| 296 | |
| 297 | <p> |
| 298 | the one marked with the <code>*</code> is the current goroutine. |
| 299 | </p> |
| 300 | |
| 301 | <h3 id="Inspecting_the_stack">Inspecting the stack</h3> |
| 302 | |
| 303 | <p> |
| 304 | Look at the stack trace for where we’ve paused the program: |
| 305 | </p> |
| 306 | |
| 307 | <pre> |
| 308 | (gdb) <b>bt</b> <i># backtrace</i> |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 309 | #0 regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/regexp/find_test.go:148 |
| 310 | #1 0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/testing/testing.go:156 |
| 311 | #2 0x000000000040df64 in runtime.initdone () at /home/user/go/src/runtime/proc.c:242 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 312 | #3 0x000000f8404a89c0 in ?? () |
| 313 | #4 0x0000000000573720 in ?? () |
| 314 | #5 0x0000000000000000 in ?? () |
| 315 | </pre> |
| 316 | |
| 317 | <p> |
| 318 | The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked on a channel receive: |
| 319 | </p> |
| 320 | |
| 321 | <pre> |
| 322 | (gdb) <b>goroutine 1 bt</b> |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 323 | #0 0x000000000040facb in runtime.gosched () at /home/user/go/src/runtime/proc.c:873 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 324 | #1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void) |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 325 | at /home/user/go/src/runtime/chan.c:342 |
| 326 | #2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/runtime/chan.c:423 |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 327 | #3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)} |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 328 | 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/testing/testing.go:201 |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 329 | #4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)} |
| 330 | 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...}) |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 331 | at /home/user/go/src/testing/testing.go:168 |
| 332 | #5 0x0000000000400dc1 in main.main () at /home/user/go/src/regexp/_testmain.go:98 |
| 333 | #6 0x00000000004022e7 in runtime.mainstart () at /home/user/go/src/runtime/amd64/asm.s:78 |
| 334 | #7 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/runtime/proc.c:243 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 335 | #8 0x0000000000000000 in ?? () |
| 336 | </pre> |
| 337 | |
| 338 | <p> |
| 339 | The stack frame shows we’re currently executing the <code>regexp.TestFind</code> function, as expected. |
| 340 | </p> |
| 341 | |
| 342 | <pre> |
| 343 | (gdb) <b>info frame</b> |
| 344 | Stack level 0, frame at 0x7ffff7f9ff88: |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 345 | rip = 0x425530 in regexp.TestFind (/home/user/go/src/regexp/find_test.go:148); |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 346 | saved rip 0x430233 |
| 347 | called by frame at 0x7ffff7f9ffa8 |
| 348 | source language minimal. |
| 349 | Arglist at 0x7ffff7f9ff78, args: t=0xf840688b60 |
| 350 | Locals at 0x7ffff7f9ff78, Previous frame's sp is 0x7ffff7f9ff88 |
| 351 | Saved registers: |
| 352 | rip at 0x7ffff7f9ff80 |
| 353 | </pre> |
| 354 | |
| 355 | <p> |
| 356 | The command <code>info locals</code> lists all variables local to the function and their values, but is a bit |
| 357 | dangerous to use, since it will also try to print uninitialized variables. Uninitialized slices may cause gdb to try |
| 358 | to print arbitrary large arrays. |
| 359 | </p> |
| 360 | |
| 361 | <p> |
| 362 | The function’s arguments: |
| 363 | </p> |
| 364 | |
| 365 | <pre> |
| 366 | (gdb) <b>info args</b> |
| 367 | t = 0xf840688b60 |
| 368 | </pre> |
| 369 | |
| 370 | <p> |
| 371 | When printing the argument, notice that it’s a pointer to a |
| 372 | <code>Regexp</code> value. Note that GDB has incorrectly put the <code>*</code> |
| 373 | on the right-hand side of the type name and made up a 'struct' keyword, in traditional C style. |
| 374 | </p> |
| 375 | |
| 376 | <pre> |
| 377 | (gdb) <b>p re</b> |
| 378 | (gdb) p t |
| 379 | $1 = (struct testing.T *) 0xf840688b60 |
| 380 | (gdb) p t |
| 381 | $1 = (struct testing.T *) 0xf840688b60 |
| 382 | (gdb) p *t |
| 383 | $2 = {errors = "", failed = false, ch = 0xf8406f5690} |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 384 | (gdb) p *t->ch |
| 385 | $3 = struct hchan<*testing.T> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 386 | </pre> |
| 387 | |
| 388 | <p> |
Alberto Donizetti | 4601eae | 2017-01-09 19:11:58 +0100 | [diff] [blame] | 389 | That <code>struct hchan<*testing.T></code> is the |
| 390 | runtime-internal representation of a channel. It is currently empty, |
| 391 | or gdb would have pretty-printed its contents. |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 392 | </p> |
| 393 | |
| 394 | <p> |
| 395 | Stepping forward: |
| 396 | </p> |
| 397 | |
| 398 | <pre> |
| 399 | (gdb) <b>n</b> <i># execute next line</i> |
| 400 | 149 for _, test := range findTests { |
| 401 | (gdb) <i># enter is repeat</i> |
| 402 | 150 re := MustCompile(test.pat) |
| 403 | (gdb) <b>p test.pat</b> |
| 404 | $4 = "" |
| 405 | (gdb) <b>p re</b> |
| 406 | $5 = (struct regexp.Regexp *) 0xf84068d070 |
| 407 | (gdb) <b>p *re</b> |
| 408 | $6 = {expr = "", prog = 0xf840688b80, prefix = "", prefixBytes = []uint8, prefixComplete = true, |
| 409 | prefixRune = 0, cond = 0 '\000', numSubexp = 0, longest = false, mu = {state = 0, sema = 0}, |
| 410 | machine = []*regexp.machine} |
| 411 | (gdb) <b>p *re->prog</b> |
| 412 | $7 = {Inst = []regexp/syntax.Inst = {{Op = 5 '\005', Out = 0, Arg = 0, Rune = []int}, {Op = |
| 413 | 6 '\006', Out = 2, Arg = 0, Rune = []int}, {Op = 4 '\004', Out = 0, Arg = 0, Rune = []int}}, |
| 414 | Start = 1, NumCap = 2} |
| 415 | </pre> |
| 416 | |
| 417 | |
| 418 | <p> |
| 419 | We can step into the <code>String</code>function call with <code>"s"</code>: |
| 420 | </p> |
| 421 | |
| 422 | <pre> |
| 423 | (gdb) <b>s</b> |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 424 | regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/user/go/src/regexp/regexp.go:97 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 425 | 97 func (re *Regexp) String() string { |
| 426 | </pre> |
| 427 | |
| 428 | <p> |
| 429 | Get a stack trace to see where we are: |
| 430 | </p> |
| 431 | |
| 432 | <pre> |
| 433 | (gdb) <b>bt</b> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 434 | #0 regexp.(*Regexp).String (re=0xf84068d070, noname=void) |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 435 | at /home/user/go/src/regexp/regexp.go:97 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 436 | #1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60) |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 437 | at /home/user/go/src/regexp/find_test.go:151 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 438 | #2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8) |
Russ Cox | 220a6de | 2014-09-08 00:06:45 -0400 | [diff] [blame] | 439 | at /home/user/go/src/testing/testing.go:156 |
| 440 | #3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/runtime/proc.c:243 |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 441 | .... |
| 442 | </pre> |
| 443 | |
| 444 | <p> |
| 445 | Look at the source code: |
| 446 | </p> |
| 447 | |
| 448 | <pre> |
| 449 | (gdb) <b>l</b> |
| 450 | 92 mu sync.Mutex |
| 451 | 93 machine []*machine |
| 452 | 94 } |
| 453 | 95 |
| 454 | 96 // String returns the source text used to compile the regular expression. |
| 455 | 97 func (re *Regexp) String() string { |
| 456 | 98 return re.expr |
| 457 | 99 } |
| 458 | 100 |
| 459 | 101 // Compile parses a regular expression and returns, if successful, |
| 460 | </pre> |
| 461 | |
| 462 | <h3 id="Pretty_Printing">Pretty Printing</h3> |
| 463 | |
| 464 | <p> |
| 465 | GDB's pretty printing mechanism is triggered by regexp matches on type names. An example for slices: |
| 466 | </p> |
| 467 | |
| 468 | <pre> |
| 469 | (gdb) <b>p utf</b> |
| 470 | $22 = []uint8 = {0 '\000', 0 '\000', 0 '\000', 0 '\000'} |
| 471 | </pre> |
| 472 | |
| 473 | <p> |
| 474 | Since slices, arrays and strings are not C pointers, GDB can't interpret the subscripting operation for you, but |
| 475 | you can look inside the runtime representation to do that (tab completion helps here): |
| 476 | </p> |
| 477 | <pre> |
| 478 | |
| 479 | (gdb) <b>p slc</b> |
| 480 | $11 = []int = {0, 0} |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 481 | (gdb) <b>p slc-></b><i><TAB></i> |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 482 | array slc len |
| 483 | (gdb) <b>p slc->array</b> |
| 484 | $12 = (int *) 0xf84057af00 |
| 485 | (gdb) <b>p slc->array[1]</b> |
| 486 | $13 = 0</pre> |
| 487 | |
| 488 | |
| 489 | |
| 490 | <p> |
| 491 | The extension functions $len and $cap work on strings, arrays and slices: |
| 492 | </p> |
| 493 | |
| 494 | <pre> |
| 495 | (gdb) <b>p $len(utf)</b> |
| 496 | $23 = 4 |
| 497 | (gdb) <b>p $cap(utf)</b> |
| 498 | $24 = 4 |
| 499 | </pre> |
| 500 | |
| 501 | <p> |
Shenghou Ma | 9dbfda5 | 2012-03-21 00:42:53 +0800 | [diff] [blame] | 502 | Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types <code>hash<int,string>*</code>. Dereferencing will trigger prettyprinting |
Luuk van Dijk | 3e26862 | 2011-10-05 10:49:23 -0700 | [diff] [blame] | 503 | </p> |
| 504 | |
| 505 | <p> |
| 506 | 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 <code>$dtype</code> decodes the dynamic type for you (examples are taken from a breakpoint at <code>regexp.go</code> line 293.) |
| 507 | </p> |
| 508 | |
| 509 | <pre> |
| 510 | (gdb) <b>p i</b> |
| 511 | $4 = {str = "cbb"} |
| 512 | (gdb) <b>whatis i</b> |
| 513 | type = regexp.input |
| 514 | (gdb) <b>p $dtype(i)</b> |
| 515 | $26 = (struct regexp.inputBytes *) 0xf8400b4930 |
| 516 | (gdb) <b>iface i</b> |
| 517 | regexp.input: struct regexp.inputBytes * |
| 518 | </pre> |