Skip to content

Commit 58223e5

Browse files
committed
Bundled pretty-printer for GDB: init
1 parent e017c2a commit 58223e5

File tree

6 files changed

+512
-191
lines changed

6 files changed

+512
-191
lines changed

Diff for: prettyPrinters/gdb_lookup.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import gdb
2+
3+
from gdb_providers import *
4+
from rust_types import *
5+
6+
7+
def register_printers(objfile):
8+
"""Registers Rust pretty printers for the given objfile"""
9+
objfile.pretty_printers.append(lookup)
10+
11+
12+
def classify_rust_type(type):
13+
type_class = type.code
14+
if type_class == gdb.TYPE_CODE_STRUCT:
15+
return classify_struct(type.tag, type.fields())
16+
if type_class == gdb.TYPE_CODE_UNION:
17+
return classify_union(type.fields())
18+
19+
return RustType.OTHER
20+
21+
22+
def lookup(valobj):
23+
"""Returns the provider for the given value"""
24+
rust_type = classify_rust_type(valobj.type)
25+
26+
if rust_type == RustType.STRUCT:
27+
return StructProvider(valobj)
28+
if rust_type == RustType.STRUCT_VARIANT:
29+
return StructProvider(valobj, is_variant=True)
30+
if rust_type == RustType.TUPLE:
31+
return TupleProvider(valobj)
32+
if rust_type == RustType.TUPLE_VARIANT:
33+
return TupleProvider(valobj, is_variant=True)
34+
35+
if rust_type == RustType.STD_STRING:
36+
return StdStringProvider(valobj)
37+
if rust_type == RustType.STD_STR:
38+
return StdStrProvider(valobj)
39+
40+
if rust_type == RustType.STD_VEC:
41+
return StdVecProvider(valobj)
42+
if rust_type == RustType.STD_VEC_DEQUE:
43+
return StdVecDequeProvider(valobj)
44+
if rust_type == RustType.STD_BTREE_SET:
45+
return StdBTreeSetProvider(valobj)
46+
if rust_type == RustType.STD_BTREE_MAP:
47+
return StdBTreeMapProvider(valobj)
48+
49+
if rust_type == RustType.STD_RC:
50+
return StdRcProvider(valobj)
51+
if rust_type == RustType.STD_ARC:
52+
return StdRcProvider(valobj, is_atomic=True)
53+
54+
if rust_type == RustType.STD_CELL:
55+
return StdCellProvider(valobj)
56+
if rust_type == RustType.STD_REF:
57+
return StdRefProvider(valobj)
58+
if rust_type == RustType.STD_REF_MUT:
59+
return StdRefProvider(valobj)
60+
if rust_type == RustType.STD_REF_CELL:
61+
return StdRefCellProvider(valobj)
62+
63+
return None

Diff for: prettyPrinters/gdb_providers.py

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
from gdb import lookup_type
2+
from sys import version_info
3+
4+
if version_info[0] >= 3:
5+
xrange = range
6+
7+
ZERO_FIELD = "__0"
8+
9+
class StructProvider:
10+
def __init__(self, valobj, is_variant=False):
11+
self.valobj = valobj
12+
self.is_variant = is_variant
13+
fields = self.valobj.type.fields()
14+
self.fields = fields[1:] if is_variant else fields
15+
16+
def children(self):
17+
for i, field in enumerate(self.fields):
18+
yield ((field.name, self.valobj[field.name]))
19+
20+
21+
class TupleProvider:
22+
def __init__(self, valobj, is_variant=False):
23+
self.valobj = valobj
24+
self.is_variant = is_variant
25+
fields = self.valobj.type.fields()
26+
self.fields = fields[1:] if is_variant else fields
27+
28+
def children(self):
29+
for i, field in enumerate(self.fields):
30+
yield ((str(i), self.valobj[field.name]))
31+
32+
@staticmethod
33+
def display_hint():
34+
return "array"
35+
36+
37+
class StdStringProvider:
38+
def __init__(self, valobj):
39+
self.valobj = valobj
40+
vec = valobj["vec"]
41+
self.length = int(vec["len"])
42+
self.data_ptr = vec["buf"]["ptr"]["pointer"][ZERO_FIELD]
43+
44+
def to_string(self):
45+
return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
46+
47+
@staticmethod
48+
def display_hint():
49+
return "string"
50+
51+
52+
class StdStrProvider:
53+
def __init__(self, valobj):
54+
self.valobj = valobj
55+
self.length = int(valobj["length"])
56+
self.data_ptr = valobj["data_ptr"]
57+
58+
def to_string(self):
59+
return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
60+
61+
@staticmethod
62+
def display_hint():
63+
return "string"
64+
65+
66+
class StdVecProvider:
67+
def __init__(self, valobj):
68+
self.valobj = valobj
69+
self.length = int(valobj["len"])
70+
self.data_ptr = valobj["buf"]["ptr"]["pointer"][ZERO_FIELD]
71+
72+
def to_string(self):
73+
return "len=" + str(self.length)
74+
75+
def children(self):
76+
for index in xrange(0, self.length):
77+
yield ("[{}]".format(index), (self.data_ptr + index).dereference())
78+
79+
@staticmethod
80+
def display_hint():
81+
return "array"
82+
83+
84+
class StdVecDequeProvider:
85+
def __init__(self, valobj):
86+
self.valobj = valobj
87+
self.head = int(valobj["head"])
88+
self.tail = int(valobj["tail"])
89+
self.cap = int(valobj["buf"]["cap"])
90+
self.data_ptr = valobj["buf"]["ptr"]["pointer"][ZERO_FIELD]
91+
self.size = self.head - self.tail if self.head >= self.tail else self.cap + self.head - self.tail
92+
93+
def to_string(self):
94+
return "len=" + str(self.size)
95+
96+
def children(self):
97+
for index in xrange(0, self.size):
98+
yield ("[{}]".format(index), (self.data_ptr + ((self.tail + index) % self.cap)).dereference())
99+
100+
@staticmethod
101+
def display_hint():
102+
return "array"
103+
104+
105+
class StdRcProvider:
106+
def __init__(self, valobj, is_atomic=False):
107+
self.valobj = valobj
108+
self.ptr = valobj["ptr"]["pointer"][ZERO_FIELD]
109+
self.value = self.ptr["data" if is_atomic else "value"]
110+
self.strong = self.ptr["strong"]["v" if is_atomic else "value"]["value"]
111+
self.weak = self.ptr["weak"]["v" if is_atomic else "value"]["value"]
112+
113+
def to_string(self):
114+
return "strong={}, weak={}".format(int(self.strong), int(self.weak))
115+
116+
def children(self):
117+
yield ("value", self.value)
118+
yield ("strong", self.strong)
119+
yield ("weak", self.weak)
120+
121+
122+
class StdCellProvider:
123+
def __init__(self, valobj):
124+
self.value = valobj["value"]["value"]
125+
126+
def children(self):
127+
yield ("value", self.value)
128+
129+
130+
class StdRefProvider:
131+
def __init__(self, valobj):
132+
self.value = valobj["value"].dereference()
133+
self.borrow = valobj["borrow"]["borrow"]["value"]["value"]
134+
135+
def to_string(self):
136+
borrow = int(self.borrow)
137+
return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
138+
139+
def children(self):
140+
yield ("*value", self.value)
141+
yield ("borrow", self.borrow)
142+
143+
144+
class StdRefCellProvider:
145+
def __init__(self, valobj):
146+
self.value = valobj["value"]["value"]
147+
self.borrow = valobj["borrow"]["value"]["value"]
148+
149+
def to_string(self):
150+
borrow = int(self.borrow)
151+
return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
152+
153+
def children(self):
154+
yield ("value", self.value)
155+
yield ("borrow", self.borrow)
156+
157+
158+
# Yield each key (and optionally value) from a BoxedNode.
159+
def children_of_node(boxed_node, height, want_values):
160+
def cast_to_internal(node):
161+
internal_type_name = str(node.type.target()).replace('LeafNode', 'InternalNode')
162+
internal_type = lookup_type(internal_type_name)
163+
return node.cast(internal_type.pointer())
164+
165+
ptr = boxed_node['ptr']['pointer']
166+
node = ptr[ZERO_FIELD]
167+
node = cast_to_internal(node) if height > 0 else node
168+
leaf = node['data'] if height > 0 else node.dereference()
169+
keys = leaf['keys']['value']['value']
170+
values = leaf['vals']['value']['value']
171+
length = int(leaf['len'])
172+
173+
for i in xrange(0, length + 1):
174+
if height > 0:
175+
for child in children_of_node(node['edges'][i], height - 1, want_values):
176+
yield child
177+
if i < length:
178+
if want_values:
179+
yield (keys[i], values[i])
180+
else:
181+
yield keys[i]
182+
183+
184+
class StdBTreeSetProvider:
185+
def __init__(self, valobj):
186+
self.valobj = valobj
187+
188+
def to_string(self):
189+
return "len=".format(self.valobj["map"]["length"])
190+
191+
def children(self):
192+
root = self.valobj["map"]["root"]
193+
node_ptr = root["node"]
194+
i = 0
195+
for child in children_of_node(node_ptr, root["height"], want_values=False):
196+
yield ("[{}]".format(i), child)
197+
i = i + 1
198+
199+
@staticmethod
200+
def display_hint():
201+
return "array"
202+
203+
204+
class StdBTreeMapProvider:
205+
def __init__(self, valobj):
206+
self.valobj = valobj
207+
208+
def to_string(self):
209+
return "len=".format(self.valobj["length"])
210+
211+
def children(self):
212+
root = self.valobj["root"]
213+
node_ptr = root["node"]
214+
i = 0
215+
for child in children_of_node(node_ptr, root["height"], want_values=True):
216+
yield ("key{}".format(i), child[0])
217+
yield ("val{}".format(i), child[1])
218+
i = i + 1
219+
220+
@staticmethod
221+
def display_hint():
222+
return "map"

Diff for: prettyPrinters/lldb_lookup.py

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import lldb
2+
3+
from lldb_providers import *
4+
from rust_types import *
5+
6+
7+
def classify_rust_type(type):
8+
type_class = type.GetTypeClass()
9+
if type_class == lldb.eTypeClassStruct:
10+
return classify_struct(type.name, type.fields)
11+
if type_class == lldb.eTypeClassUnion:
12+
return classify_union(type.fields)
13+
14+
return RustType.OTHER
15+
16+
17+
def summary_lookup(valobj, dict):
18+
# type: (SBValue, dict) -> str
19+
"""Returns the summary provider for the given value"""
20+
rust_type = classify_rust_type(valobj.GetType())
21+
22+
if rust_type == RustType.STD_STRING:
23+
return StdStringSummaryProvider(valobj, dict)
24+
if rust_type == RustType.STD_OS_STRING:
25+
return StdOsStringSummaryProvider(valobj, dict)
26+
if rust_type == RustType.STD_STR:
27+
return StdStrSummaryProvider(valobj, dict)
28+
29+
if rust_type == RustType.STD_VEC:
30+
return SizeSummaryProvider(valobj, dict)
31+
if rust_type == RustType.STD_VEC_DEQUE:
32+
return SizeSummaryProvider(valobj, dict)
33+
34+
if rust_type == RustType.STD_RC:
35+
return StdRcSummaryProvider(valobj, dict)
36+
if rust_type == RustType.STD_ARC:
37+
return StdRcSummaryProvider(valobj, dict)
38+
39+
if rust_type == RustType.STD_REF:
40+
return StdRefSummaryProvider(valobj, dict)
41+
if rust_type == RustType.STD_REF_MUT:
42+
return StdRefSummaryProvider(valobj, dict)
43+
if rust_type == RustType.STD_REF_CELL:
44+
return StdRefSummaryProvider(valobj, dict)
45+
46+
return ""
47+
48+
49+
def synthetic_lookup(valobj, dict):
50+
# type: (SBValue, dict) -> object
51+
"""Returns the synthetic provider for the given value"""
52+
rust_type = classify_rust_type(valobj.GetType())
53+
54+
if rust_type == RustType.STRUCT:
55+
return StructSyntheticProvider(valobj, dict)
56+
if rust_type == RustType.STRUCT_VARIANT:
57+
return StructSyntheticProvider(valobj, dict, is_variant=True)
58+
if rust_type == RustType.TUPLE:
59+
return TupleSyntheticProvider(valobj, dict)
60+
if rust_type == RustType.TUPLE_VARIANT:
61+
return TupleSyntheticProvider(valobj, dict, is_variant=True)
62+
if rust_type == RustType.EMPTY:
63+
return EmptySyntheticProvider(valobj, dict)
64+
if rust_type == RustType.REGULAR_ENUM:
65+
discriminant = valobj.GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned()
66+
return synthetic_lookup(valobj.GetChildAtIndex(discriminant), dict)
67+
if rust_type == RustType.SINGLETON_ENUM:
68+
return synthetic_lookup(valobj.GetChildAtIndex(0), dict)
69+
70+
if rust_type == RustType.STD_VEC:
71+
return StdVecSyntheticProvider(valobj, dict)
72+
if rust_type == RustType.STD_VEC_DEQUE:
73+
return StdVecDequeSyntheticProvider(valobj, dict)
74+
75+
if rust_type == RustType.STD_RC:
76+
return StdRcSyntheticProvider(valobj, dict)
77+
if rust_type == RustType.STD_ARC:
78+
return StdRcSyntheticProvider(valobj, dict, is_atomic=True)
79+
80+
if rust_type == RustType.STD_CELL:
81+
return StdCellSyntheticProvider(valobj, dict)
82+
if rust_type == RustType.STD_REF:
83+
return StdRefSyntheticProvider(valobj, dict)
84+
if rust_type == RustType.STD_REF_MUT:
85+
return StdRefSyntheticProvider(valobj, dict)
86+
if rust_type == RustType.STD_REF_CELL:
87+
return StdRefSyntheticProvider(valobj, dict, is_cell=True)
88+
89+
return DefaultSynthteticProvider(valobj, dict)

0 commit comments

Comments
 (0)