blob: 9f2ba9f934878f1717d68e6eb7a594c5a2fc25d1 [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
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010030#
Austin Clements54568682015-02-16 21:56:10 -050031# Value wrappers
32#
33
34class SliceValue:
35 "Wrapper for slice values."
36
37 def __init__(self, val):
38 self.val = val
39
40 @property
41 def len(self):
42 return int(self.val['len'])
43
44 @property
45 def cap(self):
46 return int(self.val['cap'])
47
48 def __getitem__(self, i):
49 if i < 0 or i >= self.len:
50 raise IndexError(i)
51 ptr = self.val["array"]
52 return (ptr + i).dereference()
53
54
55#
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010056# Pretty Printers
57#
58
Shane Hansenf12a1672014-02-24 10:13:27 -050059
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010060class StringTypePrinter:
61 "Pretty print Go strings."
62
63 pattern = re.compile(r'^struct string$')
64
65 def __init__(self, val):
66 self.val = val
67
68 def display_hint(self):
69 return 'string'
70
71 def to_string(self):
Luuk van Dijkdb22e232011-02-20 18:53:23 +010072 l = int(self.val['len'])
73 return self.val['str'].string("utf-8", "ignore", l)
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010074
75
76class SliceTypePrinter:
77 "Pretty print slices."
78
79 pattern = re.compile(r'^struct \[\]')
80
81 def __init__(self, val):
82 self.val = val
83
84 def display_hint(self):
85 return 'array'
86
87 def to_string(self):
88 return str(self.val.type)[6:] # skip 'struct '
89
90 def children(self):
Austin Clements98651d62015-02-16 22:04:24 -050091 sval = SliceValue(self.val)
92 if sval.len > sval.cap:
Luuk van Dijkfb270612012-02-29 16:42:25 +010093 return
Austin Clements98651d62015-02-16 22:04:24 -050094 for idx, item in enumerate(sval):
95 yield ('[{0}]'.format(idx), item)
Luuk van Dijk9a71bb02010-12-03 19:19:33 +010096
97
98class MapTypePrinter:
99 """Pretty print map[K]V types.
100
101 Map-typed go variables are really pointers. dereference them in gdb
102 to inspect their contents with this pretty printer.
103 """
104
Shane Hansenf12a1672014-02-24 10:13:27 -0500105 pattern = re.compile(r'^map\[.*\].*$')
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 'map'
112
113 def to_string(self):
114 return str(self.val.type)
115
116 def children(self):
Jan Kratochvil1c82e232015-02-21 18:18:33 +0100117 B = self.val['B']
Keith Randallfb3ed162013-03-29 11:04:07 -0700118 buckets = self.val['buckets']
119 oldbuckets = self.val['oldbuckets']
120 flags = self.val['flags']
121 inttype = self.val['hash0'].type
122 cnt = 0
Shane Hansenf12a1672014-02-24 10:13:27 -0500123 for bucket in xrange(2 ** int(B)):
Keith Randallfb3ed162013-03-29 11:04:07 -0700124 bp = buckets + bucket
125 if oldbuckets:
126 oldbucket = bucket & (2 ** (B - 1) - 1)
127 oldbp = oldbuckets + oldbucket
128 oldb = oldbp.dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500129 if (oldb['overflow'].cast(inttype) & 1) == 0: # old bucket not evacuated yet
130 if bucket >= 2 ** (B - 1):
131 continue # already did old bucket
Keith Randallfb3ed162013-03-29 11:04:07 -0700132 bp = oldbp
133 while bp:
134 b = bp.dereference()
135 for i in xrange(8):
136 if b['tophash'][i] != 0:
137 k = b['keys'][i]
138 v = b['values'][i]
139 if flags & 1:
140 k = k.dereference()
141 if flags & 2:
142 v = v.dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500143 yield str(cnt), k
144 yield str(cnt + 1), v
Keith Randallfb3ed162013-03-29 11:04:07 -0700145 cnt += 2
146 bp = b['overflow']
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100147
Shane Hansenf12a1672014-02-24 10:13:27 -0500148
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100149class ChanTypePrinter:
150 """Pretty print chan[T] types.
151
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100152 Chan-typed go variables are really pointers. dereference them in gdb
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100153 to inspect their contents with this pretty printer.
154 """
155
156 pattern = re.compile(r'^struct hchan<.*>$')
157
158 def __init__(self, val):
159 self.val = val
160
161 def display_hint(self):
162 return 'array'
163
164 def to_string(self):
165 return str(self.val.type)
166
167 def children(self):
Luuk van Dijkfb270612012-02-29 16:42:25 +0100168 # see chan.c chanbuf(). et is the type stolen from hchan<T>::recvq->first->elem
Luuk van Dijk8a4ef5d2011-09-29 12:07:38 -0700169 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 +0100170 ptr = (self.val.address + 1).cast(et.pointer())
171 for i in range(self.val["qcount"]):
Luuk van Dijkdd93df32011-04-14 15:32:20 +0200172 j = (self.val["recvx"] + i) % self.val["dataqsiz"]
Shane Hansenf12a1672014-02-24 10:13:27 -0500173 yield ('[{0}]'.format(i), (ptr + j).dereference())
Luuk van Dijkdd93df32011-04-14 15:32:20 +0200174
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100175
176#
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100177# Register all the *Printer classes above.
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100178#
179
180def makematcher(klass):
181 def matcher(val):
182 try:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100183 if klass.pattern.match(str(val.type)):
184 return klass(val)
Shane Hansenf12a1672014-02-24 10:13:27 -0500185 except Exception:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100186 pass
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100187 return matcher
188
Shane Hansenf12a1672014-02-24 10:13:27 -0500189goobjfile.pretty_printers.extend([makematcher(var) for var in vars().values() if hasattr(var, 'pattern')])
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100190
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100191#
192# For reference, this is what we're trying to do:
Russ Cox11209822012-11-13 13:06:29 -0500193# eface: p *(*(struct 'runtime.rtype'*)'main.e'->type_->data)->string
194# iface: p *(*(struct 'runtime.rtype'*)'main.s'->tab->Type->data)->string
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100195#
196# interface types can't be recognized by their name, instead we check
197# if they have the expected fields. Unfortunately the mapping of
198# fields to python attributes in gdb.py isn't complete: you can't test
199# for presence other than by trapping.
200
201
202def is_iface(val):
203 try:
Shane Hansenf12a1672014-02-24 10:13:27 -0500204 return str(val['tab'].type) == "struct runtime.itab *" and str(val['data'].type) == "void *"
205 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100206 pass
207
Shane Hansenf12a1672014-02-24 10:13:27 -0500208
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100209def is_eface(val):
210 try:
Shane Hansenf12a1672014-02-24 10:13:27 -0500211 return str(val['_type'].type) == "struct runtime._type *" and str(val['data'].type) == "void *"
212 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100213 pass
214
Shane Hansenf12a1672014-02-24 10:13:27 -0500215
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100216def lookup_type(name):
217 try:
218 return gdb.lookup_type(name)
Shane Hansenf12a1672014-02-24 10:13:27 -0500219 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100220 pass
221 try:
222 return gdb.lookup_type('struct ' + name)
Shane Hansenf12a1672014-02-24 10:13:27 -0500223 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100224 pass
225 try:
226 return gdb.lookup_type('struct ' + name[1:]).pointer()
Shane Hansenf12a1672014-02-24 10:13:27 -0500227 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100228 pass
229
Shane Hansenf12a1672014-02-24 10:13:27 -0500230
Luuk van Dijkfb270612012-02-29 16:42:25 +0100231def iface_commontype(obj):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100232 if is_iface(obj):
Luuk van Dijk7400be82011-01-31 12:27:28 +0100233 go_type_ptr = obj['tab']['_type']
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100234 elif is_eface(obj):
Luuk van Dijk7400be82011-01-31 12:27:28 +0100235 go_type_ptr = obj['_type']
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100236 else:
237 return
Shane Hansenf12a1672014-02-24 10:13:27 -0500238
Jan Kratochvil02d80b92015-02-21 17:35:01 +0100239 return go_type_ptr.cast(gdb.lookup_type("struct reflect.rtype").pointer()).dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500240
Luuk van Dijkfb270612012-02-29 16:42:25 +0100241
242def iface_dtype(obj):
243 "Decode type of the data field of an eface or iface struct."
Russ Cox11209822012-11-13 13:06:29 -0500244 # known issue: dtype_name decoded from runtime.rtype is "nested.Foo"
Luuk van Dijkfb270612012-02-29 16:42:25 +0100245 # but the dwarf table lists it as "full/path/to/nested.Foo"
246
247 dynamic_go_type = iface_commontype(obj)
248 if dynamic_go_type is None:
249 return
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100250 dtype_name = dynamic_go_type['string'].dereference()['str'].string()
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200251
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100252 dynamic_gdb_type = lookup_type(dtype_name)
Luuk van Dijkfb270612012-02-29 16:42:25 +0100253 if dynamic_gdb_type is None:
254 return
Shane Hansenf12a1672014-02-24 10:13:27 -0500255
Luuk van Dijkfb270612012-02-29 16:42:25 +0100256 type_size = int(dynamic_go_type['size'])
257 uintptr_size = int(dynamic_go_type['size'].type.sizeof) # size is itself an uintptr
258 if type_size > uintptr_size:
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200259 dynamic_gdb_type = dynamic_gdb_type.pointer()
260
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100261 return dynamic_gdb_type
262
Shane Hansenf12a1672014-02-24 10:13:27 -0500263
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200264def iface_dtype_name(obj):
265 "Decode type name of the data field of an eface or iface struct."
266
Luuk van Dijkfb270612012-02-29 16:42:25 +0100267 dynamic_go_type = iface_commontype(obj)
268 if dynamic_go_type is None:
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200269 return
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200270 return dynamic_go_type['string'].dereference()['str'].string()
271
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100272
273class IfacePrinter:
274 """Pretty print interface values
275
276 Casts the data field to the appropriate dynamic type."""
277
278 def __init__(self, val):
279 self.val = val
280
281 def display_hint(self):
282 return 'string'
283
284 def to_string(self):
Luuk van Dijk43512e62011-03-28 17:34:22 +0200285 if self.val['data'] == 0:
286 return 0x0
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100287 try:
288 dtype = iface_dtype(self.val)
Shane Hansenf12a1672014-02-24 10:13:27 -0500289 except Exception:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100290 return "<bad dynamic type>"
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200291
Luuk van Dijkfb270612012-02-29 16:42:25 +0100292 if dtype is None: # trouble looking up, print something reasonable
Shane Hansenf12a1672014-02-24 10:13:27 -0500293 return "({0}){0}".format(iface_dtype_name(self.val), self.val['data'])
Luuk van Dijk46ed89b2011-09-23 10:28:02 +0200294
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100295 try:
296 return self.val['data'].cast(dtype).dereference()
Shane Hansenf12a1672014-02-24 10:13:27 -0500297 except Exception:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100298 pass
299 return self.val['data'].cast(dtype)
300
301
302def ifacematcher(val):
303 if is_iface(val) or is_eface(val):
304 return IfacePrinter(val)
305
306goobjfile.pretty_printers.append(ifacematcher)
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100307
308#
309# Convenience Functions
310#
311
Shane Hansenf12a1672014-02-24 10:13:27 -0500312
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100313class GoLenFunc(gdb.Function):
314 "Length of strings, slices, maps or channels"
315
Shane Hansenf12a1672014-02-24 10:13:27 -0500316 how = ((StringTypePrinter, 'len'), (SliceTypePrinter, 'len'), (MapTypePrinter, 'count'), (ChanTypePrinter, 'qcount'))
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100317
318 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500319 gdb.Function.__init__(self, "len")
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100320
321 def invoke(self, obj):
322 typename = str(obj.type)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100323 for klass, fld in self.how:
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100324 if klass.pattern.match(typename):
325 return obj[fld]
326
Shane Hansenf12a1672014-02-24 10:13:27 -0500327
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100328class GoCapFunc(gdb.Function):
329 "Capacity of slices or channels"
330
Shane Hansenf12a1672014-02-24 10:13:27 -0500331 how = ((SliceTypePrinter, 'cap'), (ChanTypePrinter, 'dataqsiz'))
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100332
333 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500334 gdb.Function.__init__(self, "cap")
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100335
336 def invoke(self, obj):
337 typename = str(obj.type)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100338 for klass, fld in self.how:
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100339 if klass.pattern.match(typename):
340 return obj[fld]
341
Shane Hansenf12a1672014-02-24 10:13:27 -0500342
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100343class DTypeFunc(gdb.Function):
344 """Cast Interface values to their dynamic type.
345
346 For non-interface types this behaves as the identity operation.
347 """
348
349 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500350 gdb.Function.__init__(self, "dtype")
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100351
352 def invoke(self, obj):
353 try:
354 return obj['data'].cast(iface_dtype(obj))
Shane Hansenf12a1672014-02-24 10:13:27 -0500355 except gdb.error:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100356 pass
357 return obj
358
359#
360# Commands
361#
362
Luuk van Dijkfb270612012-02-29 16:42:25 +0100363sts = ('idle', 'runnable', 'running', 'syscall', 'waiting', 'moribund', 'dead', 'recovery')
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100364
Shane Hansenf12a1672014-02-24 10:13:27 -0500365
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100366def linked_list(ptr, linkfield):
367 while ptr:
368 yield ptr
369 ptr = ptr[linkfield]
370
371
372class GoroutinesCmd(gdb.Command):
373 "List all goroutines."
374
375 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500376 gdb.Command.__init__(self, "info goroutines", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100377
Shane Hansenf12a1672014-02-24 10:13:27 -0500378 def invoke(self, _arg, _from_tty):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100379 # args = gdb.string_to_argv(arg)
380 vp = gdb.lookup_type('void').pointer()
Austin Clements54568682015-02-16 21:56:10 -0500381 for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
382 if ptr['atomicstatus'] == 6: # 'gdead'
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100383 continue
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100384 s = ' '
Luuk van Dijk43512e62011-03-28 17:34:22 +0200385 if ptr['m']:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100386 s = '*'
Luuk van Dijkfb270612012-02-29 16:42:25 +0100387 pc = ptr['sched']['pc'].cast(vp)
Shane Hansenf12a1672014-02-24 10:13:27 -0500388 # python2 will not cast pc (type void*) to an int cleanly
389 # instead python2 and python3 work with the hex string representation
390 # of the void pointer which we can parse back into an int.
391 # int(pc) will not work.
392 try:
393 #python3 / newer versions of gdb
394 pc = int(pc)
395 except gdb.error:
Austin Clements54568682015-02-16 21:56:10 -0500396 # str(pc) can return things like
397 # "0x429d6c <runtime.gopark+284>", so
398 # chop at first space.
399 pc = int(str(pc).split(None, 1)[0], 16)
Shane Hansenf12a1672014-02-24 10:13:27 -0500400 blk = gdb.block_for_pc(pc)
Austin Clements54568682015-02-16 21:56:10 -0500401 print(s, ptr['goid'], "{0:8s}".format(sts[int(ptr['atomicstatus'])]), blk.function)
Shane Hansenf12a1672014-02-24 10:13:27 -0500402
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100403
404def find_goroutine(goid):
Shane Hansenf12a1672014-02-24 10:13:27 -0500405 """
406 find_goroutine attempts to find the goroutine identified by goid.
Shenghou Maca6be912014-05-20 14:42:07 -0400407 It returns a touple of gdv.Value's representing the stack pointer
Shane Hansenf12a1672014-02-24 10:13:27 -0500408 and program counter pointer for the goroutine.
409
410 @param int goid
411
412 @return tuple (gdb.Value, gdb.Value)
413 """
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100414 vp = gdb.lookup_type('void').pointer()
Austin Clements54568682015-02-16 21:56:10 -0500415 for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
416 if ptr['atomicstatus'] == 6: # 'gdead'
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100417 continue
418 if ptr['goid'] == goid:
Shane Hansenf12a1672014-02-24 10:13:27 -0500419 return (ptr['sched'][x].cast(vp) for x in ('pc', 'sp'))
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100420 return None, None
421
422
423class GoroutineCmd(gdb.Command):
424 """Execute gdb command in the context of goroutine <goid>.
425
426 Switch PC and SP to the ones in the goroutine's G structure,
427 execute an arbitrary gdb command, and restore PC and SP.
428
429 Usage: (gdb) goroutine <goid> <gdbcmd>
430
431 Note that it is ill-defined to modify state in the context of a goroutine.
432 Restrict yourself to inspecting values.
433 """
434
435 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500436 gdb.Command.__init__(self, "goroutine", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100437
Shane Hansenf12a1672014-02-24 10:13:27 -0500438 def invoke(self, arg, _from_tty):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100439 goid, cmd = arg.split(None, 1)
Christian Himpelca8aac62012-11-19 10:22:47 -0800440 goid = gdb.parse_and_eval(goid)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100441 pc, sp = find_goroutine(int(goid))
442 if not pc:
Shane Hansenf12a1672014-02-24 10:13:27 -0500443 print("No such goroutine: ", goid)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100444 return
Shane Hansenf12a1672014-02-24 10:13:27 -0500445 try:
446 #python3 / newer versions of gdb
447 pc = int(pc)
448 except gdb.error:
449 pc = int(str(pc), 16)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100450 save_frame = gdb.selected_frame()
451 gdb.parse_and_eval('$save_pc = $pc')
452 gdb.parse_and_eval('$save_sp = $sp')
Shane Hansenf12a1672014-02-24 10:13:27 -0500453 gdb.parse_and_eval('$pc = {0}'.format(str(pc)))
454 gdb.parse_and_eval('$sp = {0}'.format(str(sp)))
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100455 try:
456 gdb.execute(cmd)
Luuk van Dijkfb270612012-02-29 16:42:25 +0100457 finally:
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100458 gdb.parse_and_eval('$pc = $save_pc')
Luuk van Dijkfb270612012-02-29 16:42:25 +0100459 gdb.parse_and_eval('$sp = $save_sp')
460 save_frame.select()
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100461
462
463class GoIfaceCmd(gdb.Command):
464 "Print Static and dynamic interface types"
465
466 def __init__(self):
Shane Hansenf12a1672014-02-24 10:13:27 -0500467 gdb.Command.__init__(self, "iface", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100468
Shane Hansenf12a1672014-02-24 10:13:27 -0500469 def invoke(self, arg, _from_tty):
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100470 for obj in gdb.string_to_argv(arg):
471 try:
472 #TODO fix quoting for qualified variable names
Shane Hansenf12a1672014-02-24 10:13:27 -0500473 obj = gdb.parse_and_eval(str(obj))
474 except Exception as e:
475 print("Can't parse ", obj, ": ", e)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100476 continue
477
Luuk van Dijkfb270612012-02-29 16:42:25 +0100478 if obj['data'] == 0:
479 dtype = "nil"
480 else:
481 dtype = iface_dtype(obj)
Shane Hansenf12a1672014-02-24 10:13:27 -0500482
Luuk van Dijkfb270612012-02-29 16:42:25 +0100483 if dtype is None:
Shane Hansenf12a1672014-02-24 10:13:27 -0500484 print("Not an interface: ", obj.type)
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100485 continue
486
Shane Hansenf12a1672014-02-24 10:13:27 -0500487 print("{0}: {1}".format(obj.type, dtype))
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100488
489# TODO: print interface's methods and dynamic type's func pointers thereof.
Shane Hansenf12a1672014-02-24 10:13:27 -0500490#rsc: "to find the number of entries in the itab's Fn field look at
491# itab.inter->numMethods
492# i am sure i have the names wrong but look at the interface type
493# and its method count"
Luuk van Dijk7a4ce232010-12-15 12:00:43 +0100494# so Itype will start with a commontype which has kind = interface
495
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100496#
Robert Hencke3fbd4782011-05-30 18:02:59 +1000497# Register all convenience functions and CLI commands
Luuk van Dijk9a71bb02010-12-03 19:19:33 +0100498#
Alexis Imperial-Legrand927b7ac2013-09-10 13:00:08 -0400499GoLenFunc()
500GoCapFunc()
501DTypeFunc()
502GoroutinesCmd()
503GoroutineCmd()
504GoIfaceCmd()