Changeset View
Changeset View
Standalone View
Standalone View
debuggers/lldb/formatters/helpers.py
Show All 15 Lines | |||||
16 | # GNU General Public License for more details. | 16 | # GNU General Public License for more details. | ||
17 | # | 17 | # | ||
18 | # You should have received a copy of the GNU General Public License | 18 | # You should have received a copy of the GNU General Public License | ||
19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | # | 20 | # | ||
21 | 21 | | |||
22 | # BEGIN: Utilities for wrapping differences of Python 2.x and Python 3 | 22 | # BEGIN: Utilities for wrapping differences of Python 2.x and Python 3 | ||
23 | # Inspired by http://pythonhosted.org/six/ | 23 | # Inspired by http://pythonhosted.org/six/ | ||
24 | 24 | from __future__ import print_function | |||
25 | import sys | 25 | import sys | ||
26 | import lldb | 26 | import lldb | ||
27 | # Useful for very coarse version differentiation. | 27 | # Useful for very coarse version differentiation. | ||
28 | PY2 = sys.version_info[0] == 2 | 28 | PY2 = sys.version_info[0] == 2 | ||
29 | PY3 = sys.version_info[0] == 3 | 29 | PY3 = sys.version_info[0] == 3 | ||
30 | 30 | | |||
31 | # create Python 2.x & 3.x compatible iterator base | 31 | # create Python 2.x & 3.x compatible iterator base | ||
32 | if PY3: | 32 | if PY3: | ||
33 | Iterator = object | 33 | Iterator = object | ||
34 | else: | 34 | else: | ||
35 | class Iterator(object): | 35 | class Iterator(object): | ||
36 | 36 | | |||
37 | def next(self): | 37 | def next(self): | ||
38 | return type(self).__next__(self) | 38 | return type(self).__next__(self) | ||
39 | if PY3: | 39 | if PY3: | ||
40 | unichr = chr | 40 | unichr = chr | ||
41 | unicode = str | ||||
41 | else: | 42 | else: | ||
42 | unichr = unichr | 43 | unichr = unichr | ||
43 | # END | 44 | # END | ||
44 | 45 | | |||
45 | 46 | | |||
47 | def canonicalized_type_name(name): | ||||
48 | """Canonicalize the type name for FindFirstType usage. | ||||
49 | + 1 space between template arguments (after comma) | ||||
50 | + no space before pointer * | ||||
51 | otherwise FindFirstType returns None | ||||
52 | """ | ||||
53 | return name.replace(' ', '').replace(',', ', ') | ||||
54 | | ||||
55 | | ||||
46 | def quote(string, quote='"'): | 56 | def quote(string, quote='"'): | ||
47 | """Quote a string so it's suitable to be used in quote""" | 57 | """Quote a string so it's suitable to be used in quote""" | ||
48 | if isinstance(string, unicode): | 58 | if isinstance(string, unicode): | ||
49 | ls = [] | 59 | ls = [] | ||
50 | for uch in string: | 60 | for uch in string: | ||
51 | code = ord(uch) | 61 | code = ord(uch) | ||
52 | if code > 255: | 62 | if code > 255: | ||
53 | ls += '\\u{:04x}'.format(code) | 63 | ls += '\\u{:04x}'.format(code) | ||
54 | elif code >= 127: | 64 | elif code >= 127: | ||
55 | ls += '\\x{:02x}'.format(code) | 65 | ls += '\\x{:02x}'.format(code) | ||
56 | elif uch == quote or uch == '\\': | 66 | elif uch == quote or uch == '\\': | ||
57 | ls += '\\' + chr(code) | 67 | ls += '\\' + chr(code) | ||
58 | elif code == 0: | 68 | elif code == 0: | ||
59 | ls += '\\x00' | 69 | ls += '\\x00' | ||
60 | else: | 70 | else: | ||
61 | ls += chr(code) | 71 | ls += chr(code) | ||
62 | return quote + ''.join(ls) + quote | 72 | return quote + ''.join(ls) + quote | ||
63 | else: | 73 | else: | ||
64 | return '{q}{s}{q}'.format(s=string.replace('\\', '\\\\').replace(quote, '\\' + quote), | 74 | return '{q}{s}{q}'.format(s=string.replace('\\', '\\\\').replace(quote, '\\' + quote), | ||
65 | q=quote) | 75 | q=quote) | ||
66 | 76 | | |||
67 | 77 | | |||
68 | def unquote(string, quote='"'): | 78 | def unquote(data, quote='"'): | ||
69 | """Unquote a string""" | 79 | """Unquote a string""" | ||
70 | if string.startswith(quote) and string.endswith(quote): | 80 | if data.startswith(quote) and data.endswith(quote): | ||
71 | string = string.lstrip(quote).rstrip(quote) | 81 | data = data[1:-1] | ||
72 | ls = [] | 82 | ls = [] | ||
73 | esc = False | 83 | esc = False | ||
74 | for idx in range(0, len(string)): | 84 | for ch in data: | ||
75 | ch = string[idx] | 85 | if esc: | ||
76 | if ch == '\\': | | |||
77 | if esc: | | |||
78 | ls.append(ch) | | |||
79 | esc = not esc | | |||
80 | else: | | |||
81 | ls.append(ch) | 86 | ls.append(ch) | ||
82 | string = ''.join(ls) | 87 | esc = False | ||
83 | return string | 88 | else: | ||
89 | if ch == '\\': | ||||
90 | esc = True | ||||
91 | else: | ||||
92 | ls.append(ch) | ||||
93 | if esc: | ||||
94 | print('WARNING: unpaired escape') | ||||
95 | data = ''.join(ls) | ||||
96 | return data | ||||
84 | 97 | | |||
85 | 98 | | |||
86 | def invoke(val, method, args=''): | 99 | def invoke(val, method, args=''): | ||
87 | """Try to invoke a method on val, args are passed in as an expression string""" | 100 | """Try to invoke a method on val, args are passed in as an expression string""" | ||
88 | # first try to get a valid frame | 101 | # first try to get a valid frame | ||
89 | frame = None | 102 | frame = None | ||
90 | for f in [val.frame, lldb.frame, val.process.selected_thread.GetFrameAtIndex(0)]: | 103 | for f in [val.frame, lldb.frame, val.process.selected_thread.GetFrameAtIndex(0)]: | ||
91 | if f.IsValid(): | 104 | if f.IsValid(): | ||
92 | frame = f | 105 | frame = f | ||
93 | break | 106 | break | ||
94 | if frame is None: | 107 | if frame is None: | ||
95 | return lldb.SBValue() | 108 | return lldb.SBValue() | ||
96 | 109 | | |||
97 | # second try to get a pointer to val | 110 | # second try to get a pointer to val | ||
98 | if val.GetType().IsPointerType(): | 111 | if val.GetType().IsPointerType(): | ||
99 | ptype = val.GetType() | 112 | ptype = val.GetType() | ||
100 | addr = val.GetValueAsUnsigned(0) | 113 | addr = val.GetValueAsUnsigned(0) | ||
101 | else: | 114 | else: | ||
102 | ptype = val.GetType().GetPointerType() | 115 | ptype = val.GetType().GetPointerType() | ||
103 | addr = val.AddressOf().GetValueAsUnsigned(0) | 116 | addr = val.AddressOf().GetValueAsUnsigned(0) | ||
104 | 117 | | |||
105 | # third, build expression | 118 | # third, build expression | ||
106 | expr = 'reinterpret_cast<const {}>({})->{}({})'.format(ptype.GetName(), addr, method, args) | 119 | expr = 'reinterpret_cast<const {}>({})->{}({})'.format(ptype.GetName(), addr, method, args) | ||
107 | res = frame.EvaluateExpression(expr) | 120 | res = frame.EvaluateExpression(expr) | ||
108 | #if not res.IsValid(): | 121 | # if not res.IsValid(): | ||
109 | #print 'Expr {} on value {} failed'.format(expr, val.GetName()) | 122 | # print 'Expr {} on value {} failed'.format(expr, val.GetName()) | ||
110 | return res | 123 | return res | ||
111 | 124 | | |||
112 | 125 | | |||
113 | def rename(name, val): | 126 | def rename(name, val): | ||
114 | """Rename a SBValue""" | 127 | """Rename a SBValue""" | ||
115 | return val.CreateValueFromData(name, val.GetData(), val.GetType()) | 128 | return val.CreateValueFromData(name, val.GetData(), val.GetType()) | ||
116 | 129 | | |||
117 | 130 | | |||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Line(s) | 199 | def get_child_at_index(self, idx): | |||
204 | if isinstance(child, lldb.SBValue): | 217 | if isinstance(child, lldb.SBValue): | ||
205 | return child | 218 | return child | ||
206 | else: | 219 | else: | ||
207 | # we don't cache (const char[]) SBValue, ceate it on the fly | 220 | # we don't cache (const char[]) SBValue, ceate it on the fly | ||
208 | # LLDB tends to reuse a static data space for c-string literal type expressions, | 221 | # LLDB tends to reuse a static data space for c-string literal type expressions, | ||
209 | # it might be overwriten by others if we cache them. | 222 | # it might be overwriten by others if we cache them. | ||
210 | # child is a (name, expr) tuple in this case | 223 | # child is a (name, expr) tuple in this case | ||
211 | if len(child) != 2: | 224 | if len(child) != 2: | ||
212 | print 'error, const char[] value should be a tuple with two elements, it is', child | 225 | print('error, const char[] value should be a tuple with two elements, it is', child) | ||
213 | return self.valobj.CreateValueFromExpression(*child) | 226 | return self.valobj.CreateValueFromExpression(*child) | ||
214 | 227 | | |||
215 | @staticmethod | 228 | @staticmethod | ||
216 | def _getName(var): | 229 | def _getName(var): | ||
217 | if isinstance(var, lldb.SBValue): | 230 | if isinstance(var, lldb.SBValue): | ||
218 | return var.GetName() | 231 | return var.GetName() | ||
219 | else: | 232 | else: | ||
220 | return var[0] | 233 | return var[0] | ||
▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines |