blob: cd16a6cbab70f41bfbe37b8ca410f814882d00d0 [file] [log] [blame]
Luuk van Dijk9a71bb02010-12-03 19:19:33 +01001# Copyright 2010 The Go Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file.
4
Robert Hencke3fbd4782011-05-30 18:02:59 +10005"""GDB Pretty printers and convenience functions for Go's runtime structures.
Luuk van Dijk9a71bb02010-12-03 19:19:33 +01006
7This script is loaded by GDB when it finds a .debug_gdb_scripts
Luuk van Dijkfb270612012-02-29 16:42:25 +01008section in the compiled binary. The [68]l linkers emit this with a
Luuk van Dijk9a71bb02010-12-03 19:19:33 +01009path to this file based on the path to the runtime package.
10"""
11
Luuk van Dijk7a4ce232010-12-15 12:00:43 +010012# Known issues:
13# - pretty printing only works for the 'native' strings. E.g. 'type
14# foo string' will make foo a plain struct in the eyes of gdb,
15# circumventing the pretty print triggering.
Luuk van Dijkdb22e232011-02-20 18:53:23 +010016
Luuk van Dijk7a4ce232010-12-15 12:00:43 +010017
Shane Hansenf12a1672014-02-24 10:13:27 -050018from __future__ import print_function
19import re
20import sys
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010021
Shane Hansenf12a1672014-02-24 10:13:27 -050022print("Loading Go Runtime support.", file=sys.stderr)
23#http://python3porting.com/differences.html
24if sys.version > '3':
25 xrange = range
Luuk van Dijk7a4ce232010-12-15 12:00:43 +010026# allow to manually reload while developing
27goobjfile = gdb.current_objfile() or gdb.objfiles()[0]
28goobjfile.pretty_printers = []
29
Hana Kimef175732018-01-16 15:21:34 -050030# G state (runtime2.go)
31
32def read_runtime_const(varname, default):
33 try:
34 return int(gdb.parse_and_eval(varname))
35 except Exception:
36 return int(default)
37
38
39G_IDLE = read_runtime_const("'runtime._Gidle'", 0)
40G_RUNNABLE = read_runtime_const("'runtime._Grunnable'", 1)
41G_RUNNING = read_runtime_const("'runtime._Grunning'", 2)
42G_SYSCALL = read_runtime_const("'runtime._Gsyscall'", 3)
43G_WAITING = read_runtime_const("'runtime._Gwaiting'", 4)
44G_MORIBUND_UNUSED = read_runtime_const("'runtime._Gmoribund_unused'", 5)
45G_DEAD = read_runtime_const("'runtime._Gdead'", 6)
46G_ENQUEUE_UNUSED = read_runtime_const("'runtime._Genqueue_unused'", 7)
47G_COPYSTACK = read_runtime_const("'runtime._Gcopystack'", 8)
48G_SCAN = read_runtime_const("'runtime._Gscan'", 0x1000)
49G_SCANRUNNABLE = G_SCAN+G_RUNNABLE
50G_SCANRUNNING = G_SCAN+G_RUNNING
51G_SCANSYSCALL = G_SCAN+G_SYSCALL
52G_SCANWAITING = G_SCAN+G_WAITING
53
54sts = {
55 G_IDLE: 'idle',
56 G_RUNNABLE: 'runnable',
57 G_RUNNING: 'running',
58 G_SYSCALL: 'syscall',
59 G_WAITING: 'waiting',
60 G_MORIBUND_UNUSED: 'moribund',
61 G_DEAD: 'dead',
62 G_ENQUEUE_UNUSED: 'enqueue',
63 G_COPYSTACK: 'copystack',
64 G_SCAN: 'scan',
65 G_SCANRUNNABLE: 'runnable+s',
66 G_SCANRUNNING: 'running+s',
67 G_SCANSYSCALL: 'syscall+s',
68 G_SCANWAITING: 'waiting+s',
69}
70
71
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010072#
Austin Clements54568682015-02-16 21:56:10 -050073# Value wrappers
74#
75
76class SliceValue:
77 "Wrapper for slice values."
78
79 def __init__(self, val):
80 self.val = val
81
82 @property
83 def len(self):
84 return int(self.val['len'])
85
86 @property
87 def cap(self):
88 return int(self.val['cap'])
89
90 def __getitem__(self, i):
91 if i < 0 or i >= self.len:
92 raise IndexError(i)
93 ptr = self.val["array"]
94 return (ptr + i).dereference()
95
96
97#
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010098# Pretty Printers
99#
100
Shane Hansenf12a1672014-02-24 10:13:27 -0500101
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100102class StringTypePrinter:
103 "Pretty print Go strings."
104
Lee Packhamc45751e2015-03-30 17:36:49 +0100105 pattern = re.compile(r'^struct string( \*)?$')
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100106
107 def __init__(self, val):
108 self.val = val
109
110 def display_hint(self):
111 return 'string'
112
113 def to_string(self):
Luuk van Dijkdb22e232011-02-20 18:53:23 +0100114 l = int(self.val['len'])
115 return self.val['str'].string("utf-8", "ignore", l)
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100116
117
118class SliceTypePrinter:
119 "Pretty print slices."
120
121 pattern = re.compile(r'^struct \[\]')
122
123 def __init__(self, val):
124 self.val = val
125
126 def display_hint(self):
127 return 'array'
128
129 def to_string(self):
130 return str(self.val.type)[6:] # skip 'struct '
131
132 def children(self):
Austin Clements98651d62015-02-16 22:04:24 -0500133 sval = SliceValue(self.val)
134 if sval.len > sval.cap:
Luuk van Dijkfb270612012-02-29 16:42:25 +0100135 return
Austin Clements98651d62015-02-16 22:04:24 -0500136 for idx, item in enumerate(sval):
137 yield ('[{0}]'.format(idx), item)
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100138
139
140class MapTypePrinter:
141 """Pretty print map[K]V types.
142
143 Map-typed go variables are really pointers. dereference them in gdb
144 to inspect their contents with this pretty printer.
145 """
146
Shane Hansenf12a1672014-02-24 10:13:27 -0500147 pattern = re.compile(r'^map\[.*\].*$')
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100148
149 def __init__(self, val):
150 self.val = val
151
152 def display_hint(self):
153 return 'map'
154
155 def to_string(self):
156 return str(self.val.type)
157
158 def children(self):
Jan Kratochvil1c82e232015-02-21 18:18:33 +0100159 B = self.val['B']
Keith Randallfb3ed162013-03-29 11:04:07 -0700160 buckets = self.val['buckets']
161 oldbuckets = self.val['oldbuckets']
162 flags = self.val['flags']
163 inttype = self.val['hash0'].type
164 cnt = 0
Shane Hansenf12a1672014-02-24 10:13:27 -0500165 for bucket in xrange(2 ** int(B)):
Keith Randallfb3ed162013-03-29 11:04:07 -0700166 bp = buckets + bucket
167 if oldbuckets:
168 oldbucket = bucket & (2 ** (B - 1) - 1)
169 oldbp = oldbuckets + oldbucket
170 oldb = oldbp.dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500171 if (oldb['overflow'].cast(inttype) & 1) == 0: # old bucket not evacuated yet
172 if bucket >= 2 ** (B - 1):
173 continue # already did old bucket
Keith Randallfb3ed162013-03-29 11:04:07 -0700174 bp = oldbp
175 while bp:
176 b = bp.dereference()
177 for i in xrange(8):
178 if b['tophash'][i] != 0:
179 k = b['keys'][i]
180 v = b['values'][i]
181 if flags & 1:
182 k = k.dereference()
183 if flags & 2:
184 v = v.dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500185 yield str(cnt), k
186 yield str(cnt + 1), v
Keith Randallfb3ed162013-03-29 11:04:07 -0700187 cnt += 2
188 bp = b['overflow']
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100189
Shane Hansenf12a1672014-02-24 10:13:27 -0500190
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100191class ChanTypePrinter:
192 """Pretty print chan[T] types.
193
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100194 Chan-typed go variables are really pointers. dereference them in gdb
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100195 to inspect their contents with this pretty printer.
196 """
197
198 pattern = re.compile(r'^struct hchan<.*>$')
199
200 def __init__(self, val):
201 self.val = val
202
203 def display_hint(self):
204 return 'array'
205
206 def to_string(self):
207 return str(self.val.type)
208
209 def children(self):
Luuk van Dijkfb270612012-02-29 16:42:25 +0100210 # see chan.c chanbuf(). et is the type stolen from hchan<T>::recvq->first->elem
Luuk van Dijk8a4ef5d2011-09-29 12:07:38 -0700211 et = [x.type for x in self.val['recvq']['first'].type.target().fields() if x.name == 'elem'][0]
Luuk van Dijkfb270612012-02-29 16:42:25 +0100212 ptr = (self.val.address + 1).cast(et.pointer())
213 for i in range(self.val["qcount"]):
Luuk van Dijkdd93df32011-04-14 15:32:20 +0200214 j = (self.val["recvx"] + i) % self.val["dataqsiz"]
Shane Hansenf12a1672014-02-24 10:13:27 -0500215 yield ('[{0}]'.format(i), (ptr + j).dereference())
Luuk van Dijkdd93df32011-04-14 15:32:20 +0200216
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100217
218#
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100219# Register all the *Printer classes above.
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100220#
221
222def makematcher(klass):
223 def matcher(val):
224 try:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100225 if klass.pattern.match(str(val.type)):
226 return klass(val)
Shane Hansenf12a1672014-02-24 10:13:27 -0500227 except Exception:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100228 pass
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100229 return matcher
230
Shane Hansenf12a1672014-02-24 10:13:27 -0500231goobjfile.pretty_printers.extend([makematcher(var) for var in vars().values() if hasattr(var, 'pattern')])
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100232
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100233#
234# For reference, this is what we're trying to do:
Russ Cox11209822012-11-13 13:06:29 -0500235# eface: p *(*(struct 'runtime.rtype'*)'main.e'->type_->data)->string
236# iface: p *(*(struct 'runtime.rtype'*)'main.s'->tab->Type->data)->string
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100237#
238# interface types can't be recognized by their name, instead we check
239# if they have the expected fields. Unfortunately the mapping of
240# fields to python attributes in gdb.py isn't complete: you can't test
241# for presence other than by trapping.
242
243
244def is_iface(val):
245 try:
Shane Hansenf12a1672014-02-24 10:13:27 -0500246 return str(val['tab'].type) == "struct runtime.itab *" and str(val['data'].type) == "void *"
247 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100248 pass
249
Shane Hansenf12a1672014-02-24 10:13:27 -0500250
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100251def is_eface(val):
252 try:
Shane Hansenf12a1672014-02-24 10:13:27 -0500253 return str(val['_type'].type) == "struct runtime._type *" and str(val['data'].type) == "void *"
254 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100255 pass
256
Shane Hansenf12a1672014-02-24 10:13:27 -0500257
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100258def lookup_type(name):
259 try:
260 return gdb.lookup_type(name)
Shane Hansenf12a1672014-02-24 10:13:27 -0500261 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100262 pass
263 try:
264 return gdb.lookup_type('struct ' + name)
Shane Hansenf12a1672014-02-24 10:13:27 -0500265 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100266 pass
267 try:
268 return gdb.lookup_type('struct ' + name[1:]).pointer()
Shane Hansenf12a1672014-02-24 10:13:27 -0500269 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100270 pass
271
Shane Hansenf12a1672014-02-24 10:13:27 -0500272
Luuk van Dijkfb270612012-02-29 16:42:25 +0100273def iface_commontype(obj):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100274 if is_iface(obj):
Luuk van Dijk7400be82011-01-31 12:27:28 +0100275 go_type_ptr = obj['tab']['_type']
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100276 elif is_eface(obj):
Luuk van Dijk7400be82011-01-31 12:27:28 +0100277 go_type_ptr = obj['_type']
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100278 else:
279 return
Shane Hansenf12a1672014-02-24 10:13:27 -0500280
Jan Kratochvil02d80b92015-02-21 17:35:01 +0100281 return go_type_ptr.cast(gdb.lookup_type("struct reflect.rtype").pointer()).dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500282
Luuk van Dijkfb270612012-02-29 16:42:25 +0100283
284def iface_dtype(obj):
285 "Decode type of the data field of an eface or iface struct."
Russ Cox11209822012-11-13 13:06:29 -0500286 # known issue: dtype_name decoded from runtime.rtype is "nested.Foo"
Luuk van Dijkfb270612012-02-29 16:42:25 +0100287 # but the dwarf table lists it as "full/path/to/nested.Foo"
288
289 dynamic_go_type = iface_commontype(obj)
290 if dynamic_go_type is None:
291 return
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100292 dtype_name = dynamic_go_type['string'].dereference()['str'].string()
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200293
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100294 dynamic_gdb_type = lookup_type(dtype_name)
Luuk van Dijkfb270612012-02-29 16:42:25 +0100295 if dynamic_gdb_type is None:
296 return
Shane Hansenf12a1672014-02-24 10:13:27 -0500297
Luuk van Dijkfb270612012-02-29 16:42:25 +0100298 type_size = int(dynamic_go_type['size'])
299 uintptr_size = int(dynamic_go_type['size'].type.sizeof) # size is itself an uintptr
300 if type_size > uintptr_size:
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200301 dynamic_gdb_type = dynamic_gdb_type.pointer()
302
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100303 return dynamic_gdb_type
304
Shane Hansenf12a1672014-02-24 10:13:27 -0500305
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200306def iface_dtype_name(obj):
307 "Decode type name of the data field of an eface or iface struct."
308
Luuk van Dijkfb270612012-02-29 16:42:25 +0100309 dynamic_go_type = iface_commontype(obj)
310 if dynamic_go_type is None:
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200311 return
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200312 return dynamic_go_type['string'].dereference()['str'].string()
313
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100314
315class IfacePrinter:
316 """Pretty print interface values
317
318 Casts the data field to the appropriate dynamic type."""
319
320 def __init__(self, val):
321 self.val = val
322
323 def display_hint(self):
324 return 'string'
325
326 def to_string(self):
Luuk van Dijk43512e62011-03-28 17:34:22 +0200327 if self.val['data'] == 0:
328 return 0x0
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100329 try:
330 dtype = iface_dtype(self.val)
Shane Hansenf12a1672014-02-24 10:13:27 -0500331 except Exception:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100332 return "<bad dynamic type>"
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200333
Luuk van Dijkfb270612012-02-29 16:42:25 +0100334 if dtype is None: # trouble looking up, print something reasonable
Shane Hansenf12a1672014-02-24 10:13:27 -0500335 return "({0}){0}".format(iface_dtype_name(self.val), self.val['data'])
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200336
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100337 try:
338 return self.val['data'].cast(dtype).dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500339 except Exception:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100340 pass
341 return self.val['data'].cast(dtype)
342
343
344def ifacematcher(val):
345 if is_iface(val) or is_eface(val):
346 return IfacePrinter(val)
347
348goobjfile.pretty_printers.append(ifacematcher)
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100349
350#
351# Convenience Functions
352#
353
Shane Hansenf12a1672014-02-24 10:13:27 -0500354
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100355class GoLenFunc(gdb.Function):
356 "Length of strings, slices, maps or channels"
357
Shane Hansenf12a1672014-02-24 10:13:27 -0500358 how = ((StringTypePrinter, 'len'), (SliceTypePrinter, 'len'), (MapTypePrinter, 'count'), (ChanTypePrinter, 'qcount'))
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100359
360 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500361 gdb.Function.__init__(self, "len")
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100362
363 def invoke(self, obj):
364 typename = str(obj.type)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100365 for klass, fld in self.how:
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100366 if klass.pattern.match(typename):
367 return obj[fld]
368
Shane Hansenf12a1672014-02-24 10:13:27 -0500369
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100370class GoCapFunc(gdb.Function):
371 "Capacity of slices or channels"
372
Shane Hansenf12a1672014-02-24 10:13:27 -0500373 how = ((SliceTypePrinter, 'cap'), (ChanTypePrinter, 'dataqsiz'))
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100374
375 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500376 gdb.Function.__init__(self, "cap")
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100377
378 def invoke(self, obj):
379 typename = str(obj.type)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100380 for klass, fld in self.how:
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100381 if klass.pattern.match(typename):
382 return obj[fld]
383
Shane Hansenf12a1672014-02-24 10:13:27 -0500384
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100385class DTypeFunc(gdb.Function):
386 """Cast Interface values to their dynamic type.
387
388 For non-interface types this behaves as the identity operation.
389 """
390
391 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500392 gdb.Function.__init__(self, "dtype")
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100393
394 def invoke(self, obj):
395 try:
396 return obj['data'].cast(iface_dtype(obj))
Shane Hansenf12a1672014-02-24 10:13:27 -0500397 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100398 pass
399 return obj
400
401#
402# Commands
403#
404
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100405def linked_list(ptr, linkfield):
406 while ptr:
407 yield ptr
408 ptr = ptr[linkfield]
409
410
411class GoroutinesCmd(gdb.Command):
412 "List all goroutines."
413
414 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500415 gdb.Command.__init__(self, "info goroutines", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100416
Shane Hansenf12a1672014-02-24 10:13:27 -0500417 def invoke(self, _arg, _from_tty):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100418 # args = gdb.string_to_argv(arg)
419 vp = gdb.lookup_type('void').pointer()
Austin Clements54568682015-02-16 21:56:10 -0500420 for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
Hana Kimef175732018-01-16 15:21:34 -0500421 if ptr['atomicstatus'] == G_DEAD:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100422 continue
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100423 s = ' '
Luuk van Dijk43512e62011-03-28 17:34:22 +0200424 if ptr['m']:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100425 s = '*'
Luuk van Dijkfb270612012-02-29 16:42:25 +0100426 pc = ptr['sched']['pc'].cast(vp)
Shane Hansenf12a1672014-02-24 10:13:27 -0500427 # python2 will not cast pc (type void*) to an int cleanly
428 # instead python2 and python3 work with the hex string representation
429 # of the void pointer which we can parse back into an int.
430 # int(pc) will not work.
431 try:
432 #python3 / newer versions of gdb
433 pc = int(pc)
434 except gdb.error:
Austin Clements54568682015-02-16 21:56:10 -0500435 # str(pc) can return things like
436 # "0x429d6c <runtime.gopark+284>", so
437 # chop at first space.
438 pc = int(str(pc).split(None, 1)[0], 16)
Shane Hansenf12a1672014-02-24 10:13:27 -0500439 blk = gdb.block_for_pc(pc)
Hana Kimef175732018-01-16 15:21:34 -0500440 status = int(ptr['atomicstatus'])
441 st = sts.get(status, "unknown(%d)" % status)
442 print(s, ptr['goid'], "{0:8s}".format(st), blk.function)
Shane Hansenf12a1672014-02-24 10:13:27 -0500443
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100444
445def find_goroutine(goid):
Shane Hansenf12a1672014-02-24 10:13:27 -0500446 """
447 find_goroutine attempts to find the goroutine identified by goid.
Shenghou Maca6be912014-05-20 14:42:07 -0400448 It returns a touple of gdv.Value's representing the stack pointer
Shane Hansenf12a1672014-02-24 10:13:27 -0500449 and program counter pointer for the goroutine.
450
451 @param int goid
452
453 @return tuple (gdb.Value, gdb.Value)
454 """
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100455 vp = gdb.lookup_type('void').pointer()
Austin Clements54568682015-02-16 21:56:10 -0500456 for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
Hana Kimef175732018-01-16 15:21:34 -0500457 if ptr['atomicstatus'] == G_DEAD:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100458 continue
459 if ptr['goid'] == goid:
Austin Clements24659712017-06-07 10:30:49 -0400460 break
461 else:
462 return None, None
463 # Get the goroutine's saved state.
464 pc, sp = ptr['sched']['pc'], ptr['sched']['sp']
Hana Kimdc3bef32018-01-16 15:31:12 -0500465 status = ptr['atomicstatus']&~G_SCAN
466 # Goroutine is not running nor in syscall, so use the info in goroutine
467 if status != G_RUNNING and status != G_SYSCALL:
Austin Clements24659712017-06-07 10:30:49 -0400468 return pc.cast(vp), sp.cast(vp)
Hana Kimdc3bef32018-01-16 15:31:12 -0500469
Austin Clements24659712017-06-07 10:30:49 -0400470 # If the goroutine is in a syscall, use syscallpc/sp.
471 pc, sp = ptr['syscallpc'], ptr['syscallsp']
472 if sp != 0:
473 return pc.cast(vp), sp.cast(vp)
474 # Otherwise, the goroutine is running, so it doesn't have
475 # saved scheduler state. Find G's OS thread.
476 m = ptr['m']
477 if m == 0:
478 return None, None
479 for thr in gdb.selected_inferior().threads():
480 if thr.ptid[1] == m['procid']:
481 break
Austin Clementsa7d7d7a2017-06-08 12:05:31 -0400482 else:
Austin Clements24659712017-06-07 10:30:49 -0400483 return None, None
484 # Get scheduler state from the G's OS thread state.
485 curthr = gdb.selected_thread()
486 try:
487 thr.switch()
488 pc = gdb.parse_and_eval('$pc')
489 sp = gdb.parse_and_eval('$sp')
490 finally:
491 curthr.switch()
492 return pc.cast(vp), sp.cast(vp)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100493
494
495class GoroutineCmd(gdb.Command):
496 """Execute gdb command in the context of goroutine <goid>.
497
498 Switch PC and SP to the ones in the goroutine's G structure,
499 execute an arbitrary gdb command, and restore PC and SP.
500
501 Usage: (gdb) goroutine <goid> <gdbcmd>
502
503 Note that it is ill-defined to modify state in the context of a goroutine.
504 Restrict yourself to inspecting values.
505 """
506
507 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500508 gdb.Command.__init__(self, "goroutine", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100509
Shane Hansenf12a1672014-02-24 10:13:27 -0500510 def invoke(self, arg, _from_tty):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100511 goid, cmd = arg.split(None, 1)
Christian Himpelca8aac62012-11-19 10:22:47 -0800512 goid = gdb.parse_and_eval(goid)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100513 pc, sp = find_goroutine(int(goid))
514 if not pc:
Shane Hansenf12a1672014-02-24 10:13:27 -0500515 print("No such goroutine: ", goid)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100516 return
Shane Hansenf12a1672014-02-24 10:13:27 -0500517 try:
518 #python3 / newer versions of gdb
519 pc = int(pc)
520 except gdb.error:
Derek Buitenhuis53840ad2015-04-10 15:13:04 -0400521 pc = int(str(pc).split(None, 1)[0], 16)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100522 save_frame = gdb.selected_frame()
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100523 gdb.parse_and_eval('$save_sp = $sp')
Cherry Zhangcbc26862016-06-08 22:22:35 -0400524 gdb.parse_and_eval('$save_pc = $pc')
Shane Hansenf12a1672014-02-24 10:13:27 -0500525 gdb.parse_and_eval('$sp = {0}'.format(str(sp)))
Cherry Zhangcbc26862016-06-08 22:22:35 -0400526 gdb.parse_and_eval('$pc = {0}'.format(str(pc)))
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100527 try:
528 gdb.execute(cmd)
Luuk van Dijkfb270612012-02-29 16:42:25 +0100529 finally:
Luuk van Dijkfb270612012-02-29 16:42:25 +0100530 gdb.parse_and_eval('$sp = $save_sp')
Cherry Zhangcbc26862016-06-08 22:22:35 -0400531 gdb.parse_and_eval('$pc = $save_pc')
Luuk van Dijkfb270612012-02-29 16:42:25 +0100532 save_frame.select()
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100533
534
535class GoIfaceCmd(gdb.Command):
536 "Print Static and dynamic interface types"
537
538 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500539 gdb.Command.__init__(self, "iface", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100540
Shane Hansenf12a1672014-02-24 10:13:27 -0500541 def invoke(self, arg, _from_tty):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100542 for obj in gdb.string_to_argv(arg):
543 try:
544 #TODO fix quoting for qualified variable names
Shane Hansenf12a1672014-02-24 10:13:27 -0500545 obj = gdb.parse_and_eval(str(obj))
546 except Exception as e:
547 print("Can't parse ", obj, ": ", e)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100548 continue
549
Luuk van Dijkfb270612012-02-29 16:42:25 +0100550 if obj['data'] == 0:
551 dtype = "nil"
552 else:
553 dtype = iface_dtype(obj)
Shane Hansenf12a1672014-02-24 10:13:27 -0500554
Luuk van Dijkfb270612012-02-29 16:42:25 +0100555 if dtype is None:
Shane Hansenf12a1672014-02-24 10:13:27 -0500556 print("Not an interface: ", obj.type)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100557 continue
558
Shane Hansenf12a1672014-02-24 10:13:27 -0500559 print("{0}: {1}".format(obj.type, dtype))
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100560
561# TODO: print interface's methods and dynamic type's func pointers thereof.
Shane Hansenf12a1672014-02-24 10:13:27 -0500562#rsc: "to find the number of entries in the itab's Fn field look at
563# itab.inter->numMethods
564# i am sure i have the names wrong but look at the interface type
565# and its method count"
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100566# so Itype will start with a commontype which has kind = interface
567
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100568#
Robert Hencke3fbd4782011-05-30 18:02:59 +1000569# Register all convenience functions and CLI commands
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100570#
Alexis Imperial-Legrand927b7ac2013-09-10 13:00:08 -0400571GoLenFunc()
572GoCapFunc()
573DTypeFunc()
574GoroutinesCmd()
575GoroutineCmd()
576GoIfaceCmd()