Commit fb270611 authored by Luuk van Dijk's avatar Luuk van Dijk

pkg/runtime: 2 sanity checks in the runtime-gdb.py prettyprinters.

Don't try to print obviously corrupt slices or interfaces.
Doesn't actually solve 3047 or 2818, but seems a good idea anyway.

R=rsc, bsiegert
CC=golang-dev
https://golang.org/cl/5708061
parent ecdd9f23
...@@ -58,6 +58,8 @@ class SliceTypePrinter: ...@@ -58,6 +58,8 @@ class SliceTypePrinter:
return str(self.val.type)[6:] # skip 'struct ' return str(self.val.type)[6:] # skip 'struct '
def children(self): def children(self):
if self.val["len"] > self.val["cap"]:
return
ptr = self.val["array"] ptr = self.val["array"]
for idx in range(self.val["len"]): for idx in range(self.val["len"]):
yield ('[%d]' % idx, (ptr + idx).dereference()) yield ('[%d]' % idx, (ptr + idx).dereference())
...@@ -184,12 +186,10 @@ def lookup_type(name): ...@@ -184,12 +186,10 @@ def lookup_type(name):
except: except:
pass pass
_rctp_type = gdb.lookup_type("struct runtime.commonType").pointer()
_rtp_type = gdb.lookup_type("struct runtime._type").pointer()
def iface_dtype(obj): def iface_commontype(obj):
"Decode type of the data field of an eface or iface struct."
# known issue: dtype_name decoded from runtime.commonType is "nested.Foo"
# but the dwarf table lists it as "full/path/to/nested.Foo"
if is_iface(obj): if is_iface(obj):
go_type_ptr = obj['tab']['_type'] go_type_ptr = obj['tab']['_type']
elif is_eface(obj): elif is_eface(obj):
...@@ -197,12 +197,28 @@ def iface_dtype(obj): ...@@ -197,12 +197,28 @@ def iface_dtype(obj):
else: else:
return return
ct = gdb.lookup_type("struct runtime.commonType").pointer() # sanity check: reflection type description ends in a loop.
dynamic_go_type = go_type_ptr['ptr'].cast(ct).dereference() tt = go_type_ptr['_type'].cast(_rtp_type).dereference()['_type']
if tt != tt.cast(_rtp_type).dereference()['_type']:
return
return go_type_ptr['ptr'].cast(_rctp_type).dereference()
def iface_dtype(obj):
"Decode type of the data field of an eface or iface struct."
# known issue: dtype_name decoded from runtime.commonType is "nested.Foo"
# but the dwarf table lists it as "full/path/to/nested.Foo"
dynamic_go_type = iface_commontype(obj)
if dynamic_go_type is None:
return
dtype_name = dynamic_go_type['string'].dereference()['str'].string() dtype_name = dynamic_go_type['string'].dereference()['str'].string()
dynamic_gdb_type = lookup_type(dtype_name) dynamic_gdb_type = lookup_type(dtype_name)
if dynamic_gdb_type: if dynamic_gdb_type is None:
return
type_size = int(dynamic_go_type['size']) type_size = int(dynamic_go_type['size'])
uintptr_size = int(dynamic_go_type['size'].type.sizeof) # size is itself an uintptr uintptr_size = int(dynamic_go_type['size'].type.sizeof) # size is itself an uintptr
if type_size > uintptr_size: if type_size > uintptr_size:
...@@ -213,15 +229,9 @@ def iface_dtype(obj): ...@@ -213,15 +229,9 @@ def iface_dtype(obj):
def iface_dtype_name(obj): def iface_dtype_name(obj):
"Decode type name of the data field of an eface or iface struct." "Decode type name of the data field of an eface or iface struct."
if is_iface(obj): dynamic_go_type = iface_commontype(obj)
go_type_ptr = obj['tab']['_type'] if dynamic_go_type is None:
elif is_eface(obj):
go_type_ptr = obj['_type']
else:
return return
ct = gdb.lookup_type("struct runtime.commonType").pointer()
dynamic_go_type = go_type_ptr['ptr'].cast(ct).dereference()
return dynamic_go_type['string'].dereference()['str'].string() return dynamic_go_type['string'].dereference()['str'].string()
...@@ -244,7 +254,7 @@ class IfacePrinter: ...@@ -244,7 +254,7 @@ class IfacePrinter:
except: except:
return "<bad dynamic type>" return "<bad dynamic type>"
if not dtype: # trouble looking up, print something reasonable if dtype is None: # trouble looking up, print something reasonable
return "(%s)%s" % (iface_dtype_name(self.val), self.val['data']) return "(%s)%s" % (iface_dtype_name(self.val), self.val['data'])
try: try:
...@@ -267,7 +277,7 @@ goobjfile.pretty_printers.append(ifacematcher) ...@@ -267,7 +277,7 @@ goobjfile.pretty_printers.append(ifacematcher)
class GoLenFunc(gdb.Function): class GoLenFunc(gdb.Function):
"Length of strings, slices, maps or channels" "Length of strings, slices, maps or channels"
how = ((StringTypePrinter, 'len' ), how = ((StringTypePrinter, 'len'),
(SliceTypePrinter, 'len'), (SliceTypePrinter, 'len'),
(MapTypePrinter, 'count'), (MapTypePrinter, 'count'),
(ChanTypePrinter, 'qcount')) (ChanTypePrinter, 'qcount'))
...@@ -316,7 +326,7 @@ class DTypeFunc(gdb.Function): ...@@ -316,7 +326,7 @@ class DTypeFunc(gdb.Function):
# Commands # Commands
# #
sts = ( 'idle', 'runnable', 'running', 'syscall', 'waiting', 'moribund', 'dead', 'recovery') sts = ('idle', 'runnable', 'running', 'syscall', 'waiting', 'moribund', 'dead', 'recovery')
def linked_list(ptr, linkfield): def linked_list(ptr, linkfield):
while ptr: while ptr:
...@@ -403,8 +413,12 @@ class GoIfaceCmd(gdb.Command): ...@@ -403,8 +413,12 @@ class GoIfaceCmd(gdb.Command):
print "Can't parse ", obj, ": ", e print "Can't parse ", obj, ": ", e
continue continue
if obj['data'] == 0:
dtype = "nil"
else:
dtype = iface_dtype(obj) dtype = iface_dtype(obj)
if not dtype:
if dtype is None:
print "Not an interface: ", obj.type print "Not an interface: ", obj.type
continue continue
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment