-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwatch.py
120 lines (92 loc) · 2.89 KB
/
watch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""
Common interface for watchable variables:
var v,
v.name : var name eg "var1.foo.bar"
v.expr : var expr eg "bar"
v.type = var type eg "int", "struct {...}*", ...
v.value = string
v.numchild = int
v.in_scope = in_scope
v.children = None
"""
class AbstractVar(object):
type = property(lambda self: self._type())
value = property(lambda self: self._value())
name = property(lambda self: self._name())
expr = property(lambda self: self._expr())
children = property(lambda self: self._children())
numchild = property(lambda self: self._numchild())
in_scope = property(lambda self: self._in_scope())
path_expr = property(lambda self: self._path_expr())
def __init__(self, gdbsess, var):
self.gdbsess = gdbsess
self.var = var
def _children(self):
return dict( (k, self.wrap(v)) for k, v in self.var.children.iteritems() )
def __getitem__(self, idx):
return self.children[str(idx)]
def _type(self):
return self.var.type
def _name(self):
return self.var.name
def _expr(self):
return self.var.expr
def _value(self):
return self.var.value
def _numchild(self):
return self.var.numchild
def _in_scope(self):
return self.var.in_scope
@classmethod
def _wrap(cls, sess, var):
return AbstractVar(sess, var)
def wrap(self, var):
return self._wrap(self.gdbsess, var)
def _path_expr(self):
if self.var.path_expr is None:
self.var.path_expr = self.gdbsess.var_path_expr(self.var.name, sync = True)
return self.var.path_expr
def register_watch(self, expr, depends = ()):
e = expr % tuple(v.path_expr for v in depends)
v = self.gdbsess.var_create(e, sync = True)
self.gdbsess.add_var_watcher(v, self, toplevel = False)
return self.wrap(v)
def onUpdate(self, var, upd):
pass
def __str__(self):
return "(%s) %s: %s" % (type(self).__name__, self.expr, self.value)
def __repr__(self):
return self.__str__()
class FilteredWatch(AbstractVar):
@classmethod
def _wrap(cls, sess, var):
if var.type is not None:
if var.type.startswith('std::basic_string<') and var.type[-1] == '>':
return StdStringWatch(sess, var)
elif var.type.startswith('std::vector<') and var.type[-1] == '>':
return StdVectorWatch(sess, var)
return FilteredWatch(sess, var)
class StdVectorWatch(FilteredWatch):
def __init__(self, gdbsess, var):
FilteredWatch.__init__(self, gdbsess, var)
self.arrlen = self.register_watch(
"(%s)._M_impl._M_finish - (%s)._M_impl._M_start",
(self.var, self.var))
self.array = self.register_watch(
"(%s)._M_impl._M_start[0]@(%s)",
(self.var, self.arrlen))
def _children(self):
return self.array.children
class StdStringWatch(FilteredWatch):
def __init__(self, gdbsess, var):
FilteredWatch.__init__(self, gdbsess, var)
self.chars = self.register_watch(
"(%s)._M_dataplus._M_p",
(self.var,)
)
def _value(self):
return self.chars.value
def _numchild(self):
return 0
def _children(self):
return {}