|
| 1 | +# vi: ft=python |
| 2 | +set print static-members off |
| 3 | +set print object |
| 4 | +set unwindonsignal on |
| 5 | +set unwind-on-terminating-exception on |
| 6 | +set python print-stack full |
| 7 | + |
| 8 | +if $_isvoid($bpnum) |
| 9 | + break ErrorReporter::emit_message |
| 10 | + disable |
| 11 | + break Util::P4CExceptionBase::P4CExceptionBase<> |
| 12 | + break Util::P4CExceptionBase::traceCreation |
| 13 | + break BaseCompileContext::getDefaultErrorDiagnosticAction |
| 14 | +end |
| 15 | + |
| 16 | +define pn |
| 17 | + if $argc == 2 |
| 18 | + call ::dbprint($arg0 $arg1) |
| 19 | + else |
| 20 | + call ::dbprint($arg0) |
| 21 | + end |
| 22 | +end |
| 23 | +document pn |
| 24 | + print a IR::Node pointer |
| 25 | +end |
| 26 | +define d |
| 27 | + if $argc == 2 |
| 28 | + call ::dump($arg0 $arg1) |
| 29 | + else |
| 30 | + call ::dump($arg0) |
| 31 | + end |
| 32 | +end |
| 33 | +document d |
| 34 | + dump IR::Node tree or Visitor::Context |
| 35 | +end |
| 36 | +define dnt |
| 37 | + if $argc == 2 |
| 38 | + call ::dump_notype($arg0 $arg1) |
| 39 | + else |
| 40 | + call ::dump_notype($arg0) |
| 41 | + end |
| 42 | +end |
| 43 | +document dnt |
| 44 | + dump IR::Node tree, skipping 'type' fields |
| 45 | +end |
| 46 | +define dsrc |
| 47 | + if $argc == 2 |
| 48 | + call ::dump_src($arg0 $arg1) |
| 49 | + else |
| 50 | + call ::dump_src($arg0) |
| 51 | + end |
| 52 | +end |
| 53 | +document dsrc |
| 54 | + dump IR::Node tree, skipping 'type' fields, and printing source info |
| 55 | +end |
| 56 | + |
| 57 | +python |
| 58 | +import sys |
| 59 | +import re |
| 60 | + |
| 61 | +def template_split(s): |
| 62 | + parts = [] |
| 63 | + bracket_level = 0 |
| 64 | + current = [] |
| 65 | + for c in (s): |
| 66 | + if c == "," and bracket_level == 1: |
| 67 | + parts.append("".join(current)) |
| 68 | + current = [] |
| 69 | + else: |
| 70 | + if c == '>': |
| 71 | + bracket_level -= 1 |
| 72 | + if bracket_level > 0: |
| 73 | + current.append(c) |
| 74 | + if c == '<': |
| 75 | + bracket_level += 1 |
| 76 | + parts.append("".join(current)) |
| 77 | + return parts |
| 78 | + |
| 79 | +TYPE_CACHE = {} |
| 80 | + |
| 81 | +def lookup_type(typename): |
| 82 | + """Return a gdb.Type object represents given `typename`. |
| 83 | + For example, x.cast(ty('Buffer'))""" |
| 84 | + if typename in TYPE_CACHE: |
| 85 | + return TYPE_CACHE[typename] |
| 86 | + |
| 87 | + m0 = re.match(r"^(.*\S)\s*const$", typename) |
| 88 | + m1 = re.match(r"^(.*\S)\s*[*|&]$", typename) |
| 89 | + if m0 is not None: |
| 90 | + tp = lookup_type(m0.group(1)) |
| 91 | + elif m1 is None: |
| 92 | + tp = gdb.lookup_type(typename) |
| 93 | + else: |
| 94 | + if m1.group(0).endswith('*'): |
| 95 | + tp = lookup_type(m1.group(1)).pointer() |
| 96 | + else: |
| 97 | + tp = lookup_type(m1.group(1)).reference() |
| 98 | + TYPE_CACHE[typename] = tp |
| 99 | + return tp |
| 100 | + |
| 101 | +class ordered_map_Printer: |
| 102 | + "Print an ordered_map<>" |
| 103 | + def __init__(self, val): |
| 104 | + self.val = val |
| 105 | + self.args = template_split(val.type.tag) |
| 106 | + self.eltype = gdb.lookup_type('std::pair<' + self.args[0] + ' const,' + self.args[1] + '>') |
| 107 | + def to_string(self): |
| 108 | + return "ordered_map<..>" |
| 109 | + class _iter: |
| 110 | + def __init__(self, eltype, it, e): |
| 111 | + self.eltype = eltype |
| 112 | + self.it = it |
| 113 | + self.e = e |
| 114 | + def __iter__(self): |
| 115 | + return self |
| 116 | + def __next__(self): |
| 117 | + if self.it == self.e: |
| 118 | + raise StopIteration |
| 119 | + el = (self.it + 1).cast(self.eltype.pointer()).dereference() |
| 120 | + self.it = self.it.dereference()['_M_next'] |
| 121 | + return ("[" + str(el['first']) + "]", el['second']); |
| 122 | + def next(self): return self.__next__() |
| 123 | + def children(self): |
| 124 | + return self._iter(self.eltype, self.val['data']['_M_impl']['_M_node']['_M_next'], |
| 125 | + self.val['data']['_M_impl']['_M_node'].address) |
| 126 | + |
| 127 | +class ordered_set_Printer: |
| 128 | + "Print an ordered_set<>" |
| 129 | + def __init__(self, val): |
| 130 | + self.val = val |
| 131 | + self.args = template_split(val.type.tag) |
| 132 | + self.eltypestr = self.args[0] |
| 133 | + self.eltype = lookup_type(self.args[0]) |
| 134 | + self.isptr = True if re.match(r"^.*[*]$", self.args[0]) else False |
| 135 | + def to_string(self): |
| 136 | + return "ordered_set<..>" |
| 137 | + class _iter: |
| 138 | + def __init__(self, eltype, eltypestr, isptr, it, e): |
| 139 | + self.eltype = eltype |
| 140 | + self.eltypestr = eltypestr |
| 141 | + self.isptr = isptr |
| 142 | + self.it = it |
| 143 | + self.e = e |
| 144 | + self.idx = 0 |
| 145 | + def __iter__(self): |
| 146 | + return self |
| 147 | + def __next__(self): |
| 148 | + if self.it == self.e: |
| 149 | + raise StopIteration |
| 150 | + el = (self.it + 1).cast(self.eltype.pointer()).dereference() |
| 151 | + self.it = self.it.dereference()['_M_next'] |
| 152 | + idx = self.idx |
| 153 | + self.idx = idx + 1 |
| 154 | + if self.isptr: |
| 155 | + return ("[%d]" % idx, "(" + self.eltypestr + ")" + str(el)) |
| 156 | + return ("[%d]" % idx, el); |
| 157 | + def next(self): return self.__next__() |
| 158 | + def children(self): |
| 159 | + return self._iter(self.eltype, self.eltypestr, self.isptr, |
| 160 | + self.val['data']['_M_impl']['_M_node']['_M_next'], |
| 161 | + self.val['data']['_M_impl']['_M_node'].address) |
| 162 | + |
| 163 | +class cstringPrinter(object): |
| 164 | + "Print a cstring" |
| 165 | + def __init__(self, val): |
| 166 | + self.val = val |
| 167 | + def to_string(self): |
| 168 | + if self.val['str']: |
| 169 | + return str(self.val['str']) |
| 170 | + else: |
| 171 | + return "nullptr" |
| 172 | + |
| 173 | +class SourceInfoPrinter(object): |
| 174 | + "Print a Util::SourceInfo" |
| 175 | + def __init__(self, val): |
| 176 | + self.val = val |
| 177 | + def to_string(self): |
| 178 | + return (str(self.val['start']['lineNumber']) + ':' + |
| 179 | + str(self.val['start']['columnNumber']) + '-' + |
| 180 | + str(self.val['end']['lineNumber']) + ':' + |
| 181 | + str(self.val['end']['columnNumber'])) |
| 182 | + |
| 183 | +class bitvecPrinter(object): |
| 184 | + "Print a bitvec" |
| 185 | + def __init__(self, val): |
| 186 | + self.val = val |
| 187 | + def to_string(self): |
| 188 | + data = self.val['data'] |
| 189 | + rv = "" |
| 190 | + size = self.val['size'] |
| 191 | + ptr = self.val['ptr'] |
| 192 | + unitsize = ptr.type.target().sizeof * 8 |
| 193 | + while size > 1: |
| 194 | + data = ptr.dereference() |
| 195 | + i = 0 |
| 196 | + while i < unitsize: |
| 197 | + if (rv.__len__() % 120 == 119): rv += ':' |
| 198 | + elif (rv.__len__() % 30 == 29): rv += ' ' |
| 199 | + elif (rv.__len__() % 6 == 5): rv += '_' |
| 200 | + if (data & 1) == 0: |
| 201 | + rv += "0" |
| 202 | + else: |
| 203 | + rv += "1" |
| 204 | + data >>= 1 |
| 205 | + i += 1 |
| 206 | + ptr += 1 |
| 207 | + size -= 1 |
| 208 | + data = ptr.dereference() |
| 209 | + while rv == "" or data > 0: |
| 210 | + if (rv.__len__() % 120 == 119): rv += ':' |
| 211 | + elif (rv.__len__() % 30 == 29): rv += ' ' |
| 212 | + elif (rv.__len__() % 6 == 5): rv += '_' |
| 213 | + if (data & 1) == 0: |
| 214 | + rv += "0" |
| 215 | + else: |
| 216 | + rv += "1" |
| 217 | + data >>= 1 |
| 218 | + return rv |
| 219 | + |
| 220 | +def vec_begin(vec): |
| 221 | + return vec['_M_impl']['_M_start'] |
| 222 | +def vec_end(vec): |
| 223 | + return vec['_M_impl']['_M_finish'] |
| 224 | +def vec_size(vec): |
| 225 | + return int(vec_end(vec) - vec_begin(vec)) |
| 226 | +def vec_at(vec, i): |
| 227 | + return (vec_begin(vec) + i).dereference() |
| 228 | + |
| 229 | +class safe_vector_Printer: |
| 230 | + "Print a safe_vector<>" |
| 231 | + def __init__(self, val): |
| 232 | + self.val = val |
| 233 | + def to_string(self): |
| 234 | + return "" if vec_size(self.val) > 0 else "[]" |
| 235 | + class _iter: |
| 236 | + def __init__(self, val): |
| 237 | + self.val = val |
| 238 | + self.size = vec_size(val) |
| 239 | + self.idx = 0 |
| 240 | + def __iter__(self): |
| 241 | + return self |
| 242 | + def __next__(self): |
| 243 | + if self.idx >= self.size: |
| 244 | + raise StopIteration |
| 245 | + idx = self.idx |
| 246 | + self.idx = idx + 1 |
| 247 | + return ("[%d]" % idx, vec_at(self.val, idx)); |
| 248 | + def next(self): return self.__next__() |
| 249 | + def children(self): |
| 250 | + return self._iter(self.val) |
| 251 | + |
| 252 | +def bvec_size(vec): |
| 253 | + sz = int(vec_end(vec)['_M_p'] - vec_begin(vec)['_M_p']) |
| 254 | + sz = sz * vec_begin(vec)['_M_p'].type.target().sizeof * 8 |
| 255 | + sz = sz + int(vec_end(vec)['_M_offset'] - vec_begin(vec)['_M_offset']) |
| 256 | + return sz |
| 257 | + |
| 258 | +class safe_vector_bool_Printer: |
| 259 | + "Print a safe_vector<bool>" |
| 260 | + def __init__(self, val): |
| 261 | + self.val = val |
| 262 | + def to_string(self): |
| 263 | + return "" if bvec_size(self.val) > 0 else "[]" |
| 264 | + class _iter: |
| 265 | + def __init__(self, val): |
| 266 | + self.val = val |
| 267 | + self.end = vec_end(val) |
| 268 | + self.ptr = vec_begin(val)['_M_p'] |
| 269 | + self.offset = vec_begin(val)['_M_offset'] |
| 270 | + self.idx = 0 |
| 271 | + def __iter__(self): |
| 272 | + return self |
| 273 | + def __next__(self): |
| 274 | + if self.ptr == self.end['_M_p'] and self.offset >= self.end['_M_offset']: |
| 275 | + raise StopIteration |
| 276 | + ptr = self.ptr |
| 277 | + offset = self.offset |
| 278 | + idx = self.idx |
| 279 | + self.offset = offset + 1 |
| 280 | + self.idx = idx + 1 |
| 281 | + if self.offset == self.ptr.type.target().sizeof * 8: |
| 282 | + self.offset = 0 |
| 283 | + self.ptr = self.ptr + 1 |
| 284 | + return ("[%d]" % idx, (self.ptr.dereference() >> self.offset) & 1); |
| 285 | + def next(self): return self.__next__() |
| 286 | + def children(self): |
| 287 | + return self._iter(self.val) |
| 288 | + |
| 289 | +def find_pp(val): |
| 290 | + if str(val.type.tag).startswith('ordered_map<'): |
| 291 | + return ordered_map_Printer(val) |
| 292 | + if str(val.type.tag).startswith('ordered_set<'): |
| 293 | + return ordered_set_Printer(val) |
| 294 | + if str(val.type.tag).startswith('safe_vector<bool'): |
| 295 | + return safe_vector_bool_Printer(val) |
| 296 | + if str(val.type.tag).startswith('safe_vector<'): |
| 297 | + return safe_vector_Printer(val) |
| 298 | + if val.type.tag == 'bitvec': |
| 299 | + return bitvecPrinter(val) |
| 300 | + if val.type.tag == 'cstring': |
| 301 | + return cstringPrinter(val) |
| 302 | + if val.type.tag == 'Util::SourceInfo': |
| 303 | + return SourceInfoPrinter(val) |
| 304 | + return None |
| 305 | + |
| 306 | +try: |
| 307 | + while gdb.pretty_printers[-1].__name__ == "find_pp": |
| 308 | + gdb.pretty_printers = gdb.pretty_printers[:-1] |
| 309 | +except: |
| 310 | + pass |
| 311 | + |
| 312 | +gdb.pretty_printers.append(find_pp) |
| 313 | +end |
0 commit comments