150
|
1 from __future__ import print_function
|
221
|
2 import struct
|
150
|
3 import sys
|
|
4
|
|
5 import gdb.printing
|
|
6 import gdb.types
|
|
7
|
252
|
8
|
150
|
9 class Iterator:
|
252
|
10 def __iter__(self):
|
|
11 return self
|
|
12
|
|
13 if sys.version_info.major == 2:
|
150
|
14
|
252
|
15 def next(self):
|
|
16 return self.__next__()
|
150
|
17
|
252
|
18 def children(self):
|
|
19 return self
|
|
20
|
150
|
21
|
|
22 class SmallStringPrinter:
|
252
|
23 """Print an llvm::SmallString object."""
|
150
|
24
|
252
|
25 def __init__(self, val):
|
|
26 self.val = val
|
150
|
27
|
252
|
28 def to_string(self):
|
|
29 data = self.val["BeginX"].cast(gdb.lookup_type("char").pointer())
|
|
30 length = self.val["Size"]
|
|
31 return data.lazy_string(length=length)
|
236
|
32
|
252
|
33 def display_hint(self):
|
|
34 return "string"
|
|
35
|
150
|
36
|
|
37 class StringRefPrinter:
|
252
|
38 """Print an llvm::StringRef object."""
|
150
|
39
|
252
|
40 def __init__(self, val):
|
|
41 self.val = val
|
150
|
42
|
252
|
43 def to_string(self):
|
|
44 data = self.val["Data"]
|
|
45 length = self.val["Length"]
|
|
46 return data.lazy_string(length=length)
|
236
|
47
|
252
|
48 def display_hint(self):
|
|
49 return "string"
|
|
50
|
150
|
51
|
|
52 class SmallVectorPrinter(Iterator):
|
252
|
53 """Print an llvm::SmallVector object."""
|
150
|
54
|
252
|
55 def __init__(self, val):
|
|
56 self.val = val
|
|
57 t = val.type.template_argument(0).pointer()
|
|
58 self.begin = val["BeginX"].cast(t)
|
|
59 self.size = val["Size"]
|
|
60 self.i = 0
|
150
|
61
|
252
|
62 def __next__(self):
|
|
63 if self.i == self.size:
|
|
64 raise StopIteration
|
|
65 ret = "[{}]".format(self.i), (self.begin + self.i).dereference()
|
|
66 self.i += 1
|
|
67 return ret
|
150
|
68
|
252
|
69 def to_string(self):
|
|
70 return "llvm::SmallVector of Size {}, Capacity {}".format(
|
|
71 self.size, self.val["Capacity"]
|
|
72 )
|
150
|
73
|
252
|
74 def display_hint(self):
|
|
75 return "array"
|
|
76
|
150
|
77
|
|
78 class ArrayRefPrinter:
|
252
|
79 """Print an llvm::ArrayRef object."""
|
150
|
80
|
252
|
81 class _iterator:
|
|
82 def __init__(self, begin, end):
|
|
83 self.cur = begin
|
|
84 self.end = end
|
|
85 self.count = 0
|
150
|
86
|
252
|
87 def __iter__(self):
|
|
88 return self
|
150
|
89
|
252
|
90 def __next__(self):
|
|
91 if self.cur == self.end:
|
|
92 raise StopIteration
|
|
93 count = self.count
|
|
94 self.count = self.count + 1
|
|
95 cur = self.cur
|
|
96 self.cur = self.cur + 1
|
|
97 return "[%d]" % count, cur.dereference()
|
150
|
98
|
252
|
99 if sys.version_info.major == 2:
|
|
100 next = __next__
|
150
|
101
|
252
|
102 def __init__(self, val):
|
|
103 self.val = val
|
|
104
|
|
105 def children(self):
|
|
106 data = self.val["Data"]
|
|
107 return self._iterator(data, data + self.val["Length"])
|
150
|
108
|
252
|
109 def to_string(self):
|
|
110 return "llvm::ArrayRef of length %d" % (self.val["Length"])
|
150
|
111
|
252
|
112 def display_hint(self):
|
|
113 return "array"
|
150
|
114
|
|
115
|
|
116 class ExpectedPrinter(Iterator):
|
252
|
117 """Print an llvm::Expected object."""
|
150
|
118
|
252
|
119 def __init__(self, val):
|
|
120 self.val = val
|
150
|
121
|
252
|
122 def __next__(self):
|
|
123 val = self.val
|
|
124 if val is None:
|
|
125 raise StopIteration
|
|
126 self.val = None
|
|
127 if val["HasError"]:
|
|
128 return (
|
|
129 "error",
|
|
130 val["ErrorStorage"]
|
|
131 .address.cast(gdb.lookup_type("llvm::ErrorInfoBase").pointer())
|
|
132 .dereference(),
|
|
133 )
|
|
134 return (
|
|
135 "value",
|
|
136 val["TStorage"]
|
|
137 .address.cast(val.type.template_argument(0).pointer())
|
|
138 .dereference(),
|
|
139 )
|
150
|
140
|
252
|
141 def to_string(self):
|
|
142 return "llvm::Expected{}".format(" is error" if self.val["HasError"] else "")
|
|
143
|
150
|
144
|
|
145 class OptionalPrinter(Iterator):
|
252
|
146 """Print an llvm::Optional object."""
|
150
|
147
|
252
|
148 def __init__(self, val):
|
|
149 self.val = val
|
150
|
150
|
252
|
151 def __next__(self):
|
|
152 val = self.val
|
|
153 if val is None:
|
|
154 raise StopIteration
|
|
155 self.val = None
|
|
156 if not val["Storage"]["hasVal"]:
|
|
157 raise StopIteration
|
|
158 return ("value", val["Storage"]["val"])
|
150
|
159
|
252
|
160 def to_string(self):
|
|
161 return "llvm::Optional{}".format(
|
|
162 "" if self.val["Storage"]["hasVal"] else " is not initialized"
|
|
163 )
|
|
164
|
150
|
165
|
|
166 class DenseMapPrinter:
|
252
|
167 "Print a DenseMap"
|
150
|
168
|
252
|
169 class _iterator:
|
|
170 def __init__(self, key_info_t, begin, end):
|
|
171 self.key_info_t = key_info_t
|
|
172 self.cur = begin
|
|
173 self.end = end
|
|
174 self.advancePastEmptyBuckets()
|
|
175 self.first = True
|
150
|
176
|
252
|
177 def __iter__(self):
|
|
178 return self
|
150
|
179
|
252
|
180 def advancePastEmptyBuckets(self):
|
|
181 # disabled until the comments below can be addressed
|
|
182 # keeping as notes/posterity/hints for future contributors
|
|
183 return
|
|
184 n = self.key_info_t.name
|
|
185 is_equal = gdb.parse_and_eval(n + "::isEqual")
|
|
186 empty = gdb.parse_and_eval(n + "::getEmptyKey()")
|
|
187 tombstone = gdb.parse_and_eval(n + "::getTombstoneKey()")
|
|
188 # the following is invalid, GDB fails with:
|
|
189 # Python Exception <class 'gdb.error'> Attempt to take address of value
|
|
190 # not located in memory.
|
|
191 # because isEqual took parameter (for the unsigned long key I was testing)
|
|
192 # by const ref, and GDB
|
|
193 # It's also not entirely general - we should be accessing the "getFirst()"
|
|
194 # member function, not the 'first' member variable, but I've yet to figure
|
|
195 # out how to find/call member functions (especially (const) overloaded
|
|
196 # ones) on a gdb.Value.
|
|
197 while self.cur != self.end and (
|
|
198 is_equal(self.cur.dereference()["first"], empty)
|
|
199 or is_equal(self.cur.dereference()["first"], tombstone)
|
|
200 ):
|
|
201 self.cur = self.cur + 1
|
150
|
202
|
252
|
203 def __next__(self):
|
|
204 if self.cur == self.end:
|
|
205 raise StopIteration
|
|
206 cur = self.cur
|
|
207 v = cur.dereference()["first" if self.first else "second"]
|
|
208 if not self.first:
|
|
209 self.cur = self.cur + 1
|
|
210 self.advancePastEmptyBuckets()
|
|
211 self.first = True
|
|
212 else:
|
|
213 self.first = False
|
|
214 return "x", v
|
|
215
|
|
216 if sys.version_info.major == 2:
|
|
217 next = __next__
|
150
|
218
|
252
|
219 def __init__(self, val):
|
|
220 self.val = val
|
150
|
221
|
252
|
222 def children(self):
|
|
223 t = self.val.type.template_argument(3).pointer()
|
|
224 begin = self.val["Buckets"].cast(t)
|
|
225 end = (begin + self.val["NumBuckets"]).cast(t)
|
|
226 return self._iterator(self.val.type.template_argument(2), begin, end)
|
150
|
227
|
252
|
228 def to_string(self):
|
|
229 return "llvm::DenseMap with %d elements" % (self.val["NumEntries"])
|
150
|
230
|
252
|
231 def display_hint(self):
|
|
232 return "map"
|
|
233
|
150
|
234
|
221
|
235 class StringMapPrinter:
|
252
|
236 "Print a StringMap"
|
221
|
237
|
252
|
238 def __init__(self, val):
|
|
239 self.val = val
|
221
|
240
|
252
|
241 def children(self):
|
|
242 it = self.val["TheTable"]
|
|
243 end = it + self.val["NumBuckets"]
|
|
244 value_ty = self.val.type.template_argument(0)
|
|
245 entry_base_ty = gdb.lookup_type("llvm::StringMapEntryBase")
|
|
246 tombstone = gdb.parse_and_eval("llvm::StringMapImpl::TombstoneIntVal")
|
221
|
247
|
252
|
248 while it != end:
|
|
249 it_deref = it.dereference()
|
|
250 if it_deref == 0 or it_deref == tombstone:
|
|
251 it = it + 1
|
|
252 continue
|
|
253
|
|
254 entry_ptr = it_deref.cast(entry_base_ty.pointer())
|
|
255 entry = entry_ptr.dereference()
|
221
|
256
|
252
|
257 str_len = entry["keyLength"]
|
|
258 value_ptr = (entry_ptr + 1).cast(value_ty.pointer())
|
|
259 str_data = (entry_ptr + 1).cast(gdb.lookup_type("uintptr_t")) + max(
|
|
260 value_ty.sizeof, entry_base_ty.alignof
|
|
261 )
|
|
262 str_data = str_data.cast(gdb.lookup_type("char").const().pointer())
|
|
263 string_ref = gdb.Value(
|
|
264 struct.pack("PN", int(str_data), int(str_len)),
|
|
265 gdb.lookup_type("llvm::StringRef"),
|
|
266 )
|
|
267 yield "key", string_ref
|
221
|
268
|
252
|
269 value = value_ptr.dereference()
|
|
270 yield "value", value
|
221
|
271
|
252
|
272 it = it + 1
|
221
|
273
|
252
|
274 def to_string(self):
|
|
275 return "llvm::StringMap with %d elements" % (self.val["NumItems"])
|
221
|
276
|
252
|
277 def display_hint(self):
|
|
278 return "map"
|
|
279
|
221
|
280
|
150
|
281 class TwinePrinter:
|
252
|
282 "Print a Twine"
|
150
|
283
|
252
|
284 def __init__(self, val):
|
|
285 self._val = val
|
150
|
286
|
252
|
287 def display_hint(self):
|
|
288 return "string"
|
150
|
289
|
252
|
290 def string_from_pretty_printer_lookup(self, val):
|
|
291 """Lookup the default pretty-printer for val and use it.
|
150
|
292
|
252
|
293 If no pretty-printer is defined for the type of val, print an error and
|
|
294 return a placeholder string."""
|
150
|
295
|
252
|
296 pp = gdb.default_visualizer(val)
|
|
297 if pp:
|
|
298 s = pp.to_string()
|
150
|
299
|
252
|
300 # The pretty-printer may return a LazyString instead of an actual Python
|
|
301 # string. Convert it to a Python string. However, GDB doesn't seem to
|
|
302 # register the LazyString type, so we can't check
|
|
303 # "type(s) == gdb.LazyString".
|
|
304 if "LazyString" in type(s).__name__:
|
|
305 s = s.value().string()
|
150
|
306
|
252
|
307 else:
|
|
308 print(
|
|
309 (
|
|
310 "No pretty printer for {} found. The resulting Twine "
|
|
311 + "representation will be incomplete."
|
|
312 ).format(val.type.name)
|
|
313 )
|
|
314 s = "(missing {})".format(val.type.name)
|
150
|
315
|
252
|
316 return s
|
150
|
317
|
252
|
318 def is_twine_kind(self, kind, expected):
|
|
319 if not kind.endswith(expected):
|
|
320 return False
|
|
321 # apparently some GDB versions add the NodeKind:: namespace
|
|
322 # (happens for me on GDB 7.11)
|
|
323 return kind in (
|
|
324 "llvm::Twine::" + expected,
|
|
325 "llvm::Twine::NodeKind::" + expected,
|
|
326 )
|
150
|
327
|
252
|
328 def string_from_child(self, child, kind):
|
|
329 """Return the string representation of the Twine::Child child."""
|
150
|
330
|
252
|
331 if self.is_twine_kind(kind, "EmptyKind") or self.is_twine_kind(
|
|
332 kind, "NullKind"
|
|
333 ):
|
|
334 return ""
|
150
|
335
|
252
|
336 if self.is_twine_kind(kind, "TwineKind"):
|
|
337 return self.string_from_twine_object(child["twine"].dereference())
|
|
338
|
|
339 if self.is_twine_kind(kind, "CStringKind"):
|
|
340 return child["cString"].string()
|
150
|
341
|
252
|
342 if self.is_twine_kind(kind, "StdStringKind"):
|
|
343 val = child["stdString"].dereference()
|
|
344 return self.string_from_pretty_printer_lookup(val)
|
150
|
345
|
252
|
346 if self.is_twine_kind(kind, "PtrAndLengthKind"):
|
|
347 val = child["ptrAndLength"]
|
|
348 data = val["ptr"]
|
|
349 length = val["length"]
|
|
350 return data.string(length=length)
|
150
|
351
|
252
|
352 if self.is_twine_kind(kind, "CharKind"):
|
|
353 return chr(child["character"])
|
150
|
354
|
252
|
355 if self.is_twine_kind(kind, "DecUIKind"):
|
|
356 return str(child["decUI"])
|
150
|
357
|
252
|
358 if self.is_twine_kind(kind, "DecIKind"):
|
|
359 return str(child["decI"])
|
|
360
|
|
361 if self.is_twine_kind(kind, "DecULKind"):
|
|
362 return str(child["decUL"].dereference())
|
150
|
363
|
252
|
364 if self.is_twine_kind(kind, "DecLKind"):
|
|
365 return str(child["decL"].dereference())
|
150
|
366
|
252
|
367 if self.is_twine_kind(kind, "DecULLKind"):
|
|
368 return str(child["decULL"].dereference())
|
150
|
369
|
252
|
370 if self.is_twine_kind(kind, "DecLLKind"):
|
|
371 return str(child["decLL"].dereference())
|
150
|
372
|
252
|
373 if self.is_twine_kind(kind, "UHexKind"):
|
|
374 val = child["uHex"].dereference()
|
|
375 return hex(int(val))
|
150
|
376
|
252
|
377 print(
|
|
378 (
|
|
379 "Unhandled NodeKind {} in Twine pretty-printer. The result will be "
|
|
380 "incomplete."
|
|
381 ).format(kind)
|
|
382 )
|
150
|
383
|
252
|
384 return "(unhandled {})".format(kind)
|
150
|
385
|
252
|
386 def string_from_twine_object(self, twine):
|
|
387 """Return the string representation of the Twine object twine."""
|
150
|
388
|
252
|
389 lhs = twine["LHS"]
|
|
390 rhs = twine["RHS"]
|
236
|
391
|
252
|
392 lhs_kind = str(twine["LHSKind"])
|
|
393 rhs_kind = str(twine["RHSKind"])
|
|
394
|
|
395 lhs_str = self.string_from_child(lhs, lhs_kind)
|
|
396 rhs_str = self.string_from_child(rhs, rhs_kind)
|
150
|
397
|
252
|
398 return lhs_str + rhs_str
|
150
|
399
|
252
|
400 def to_string(self):
|
|
401 return self.string_from_twine_object(self._val)
|
150
|
402
|
252
|
403 def display_hint(self):
|
|
404 return "string"
|
|
405
|
236
|
406
|
150
|
407 def get_pointer_int_pair(val):
|
252
|
408 """Get tuple from llvm::PointerIntPair."""
|
|
409 info_name = val.type.template_argument(4).strip_typedefs().name
|
|
410 # Note: this throws a gdb.error if the info type is not used (by means of a
|
|
411 # call to getPointer() or similar) in the current translation unit.
|
|
412 enum_type = gdb.lookup_type(info_name + "::MaskAndShiftConstants")
|
|
413 enum_dict = gdb.types.make_enum_dict(enum_type)
|
|
414 ptr_mask = enum_dict[info_name + "::PointerBitMask"]
|
|
415 int_shift = enum_dict[info_name + "::IntShift"]
|
|
416 int_mask = enum_dict[info_name + "::IntMask"]
|
|
417 pair_union = val["Value"]
|
|
418 pointer = pair_union & ptr_mask
|
|
419 value = (pair_union >> int_shift) & int_mask
|
|
420 return (pointer, value)
|
|
421
|
150
|
422
|
173
|
423 class PointerIntPairPrinter:
|
252
|
424 """Print a PointerIntPair."""
|
173
|
425
|
252
|
426 def __init__(self, pointer, value):
|
|
427 self.pointer = pointer
|
|
428 self.value = value
|
173
|
429
|
252
|
430 def children(self):
|
|
431 yield ("pointer", self.pointer)
|
|
432 yield ("value", self.value)
|
173
|
433
|
252
|
434 def to_string(self):
|
|
435 return "(%s, %s)" % (self.pointer.type, self.value.type)
|
|
436
|
236
|
437
|
150
|
438 def make_pointer_int_pair_printer(val):
|
252
|
439 """Factory for an llvm::PointerIntPair printer."""
|
|
440 try:
|
|
441 pointer, value = get_pointer_int_pair(val)
|
|
442 except gdb.error:
|
|
443 return None # If PointerIntPair cannot be analyzed, print as raw value.
|
|
444 pointer_type = val.type.template_argument(0)
|
|
445 value_type = val.type.template_argument(2)
|
|
446 return PointerIntPairPrinter(pointer.cast(pointer_type), value.cast(value_type))
|
|
447
|
173
|
448
|
|
449 class PointerUnionPrinter:
|
252
|
450 """Print a PointerUnion."""
|
173
|
451
|
252
|
452 def __init__(self, pointer):
|
|
453 self.pointer = pointer
|
173
|
454
|
252
|
455 def children(self):
|
|
456 yield ("pointer", self.pointer)
|
173
|
457
|
252
|
458 def to_string(self):
|
|
459 return "Containing %s" % self.pointer.type
|
|
460
|
150
|
461
|
|
462 def make_pointer_union_printer(val):
|
252
|
463 """Factory for an llvm::PointerUnion printer."""
|
|
464 try:
|
|
465 pointer, value = get_pointer_int_pair(val["Val"])
|
|
466 except gdb.error:
|
|
467 return None # If PointerIntPair cannot be analyzed, print as raw value.
|
|
468 pointer_type = val.type.template_argument(int(value))
|
|
469 return PointerUnionPrinter(pointer.cast(pointer_type))
|
|
470
|
150
|
471
|
|
472 class IlistNodePrinter:
|
252
|
473 """Print an llvm::ilist_node object."""
|
150
|
474
|
252
|
475 def __init__(self, val):
|
|
476 impl_type = val.type.fields()[0].type
|
|
477 base_type = impl_type.fields()[0].type
|
|
478 derived_type = val.type.template_argument(0)
|
150
|
479
|
252
|
480 def get_prev_and_sentinel(base):
|
|
481 # One of Prev and PrevAndSentinel exists. Depending on #defines used to
|
|
482 # compile LLVM, the base_type's template argument is either true of false.
|
|
483 if base_type.template_argument(0):
|
|
484 return get_pointer_int_pair(base["PrevAndSentinel"])
|
|
485 return base["Prev"], None
|
150
|
486
|
252
|
487 # Casts a base_type pointer to the appropriate derived type.
|
|
488 def cast_pointer(pointer):
|
|
489 sentinel = get_prev_and_sentinel(pointer.dereference())[1]
|
|
490 pointer = pointer.cast(impl_type.pointer())
|
|
491 if sentinel:
|
|
492 return pointer
|
|
493 return pointer.cast(derived_type.pointer())
|
150
|
494
|
252
|
495 # Repeated cast becaue val.type's base_type is ambiguous when using tags.
|
|
496 base = val.cast(impl_type).cast(base_type)
|
|
497 (prev, sentinel) = get_prev_and_sentinel(base)
|
|
498 prev = prev.cast(base_type.pointer())
|
|
499 self.prev = cast_pointer(prev)
|
|
500 self.next = cast_pointer(val["Next"])
|
|
501 self.sentinel = sentinel
|
150
|
502
|
252
|
503 def children(self):
|
|
504 if self.sentinel:
|
|
505 yield "sentinel", "yes"
|
|
506 yield "prev", self.prev
|
|
507 yield "next", self.next
|
|
508
|
150
|
509
|
|
510 class IlistPrinter:
|
252
|
511 """Print an llvm::simple_ilist or llvm::iplist object."""
|
150
|
512
|
252
|
513 def __init__(self, val):
|
|
514 self.node_type = val.type.template_argument(0)
|
|
515 sentinel = val["Sentinel"]
|
|
516 # First field is common base type of sentinel and ilist_node.
|
|
517 base_type = sentinel.type.fields()[0].type
|
|
518 self.sentinel = sentinel.address.cast(base_type.pointer())
|
150
|
519
|
252
|
520 def _pointers(self):
|
|
521 pointer = self.sentinel
|
|
522 while True:
|
|
523 pointer = pointer["Next"].cast(pointer.type)
|
|
524 if pointer == self.sentinel:
|
|
525 return
|
|
526 yield pointer.cast(self.node_type.pointer())
|
150
|
527
|
252
|
528 def children(self):
|
|
529 for k, v in enumerate(self._pointers()):
|
|
530 yield ("[%d]" % k, v.dereference())
|
150
|
531
|
|
532
|
|
533 pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport")
|
252
|
534 pp.add_printer("llvm::SmallString", "^llvm::SmallString<.*>$", SmallStringPrinter)
|
|
535 pp.add_printer("llvm::StringRef", "^llvm::StringRef$", StringRefPrinter)
|
|
536 pp.add_printer(
|
|
537 "llvm::SmallVectorImpl", "^llvm::SmallVector(Impl)?<.*>$", SmallVectorPrinter
|
|
538 )
|
|
539 pp.add_printer("llvm::ArrayRef", "^llvm::(Mutable)?ArrayRef<.*>$", ArrayRefPrinter)
|
|
540 pp.add_printer("llvm::Expected", "^llvm::Expected<.*>$", ExpectedPrinter)
|
|
541 pp.add_printer("llvm::Optional", "^llvm::Optional<.*>$", OptionalPrinter)
|
|
542 pp.add_printer("llvm::DenseMap", "^llvm::DenseMap<.*>$", DenseMapPrinter)
|
|
543 pp.add_printer("llvm::StringMap", "^llvm::StringMap<.*>$", StringMapPrinter)
|
|
544 pp.add_printer("llvm::Twine", "^llvm::Twine$", TwinePrinter)
|
|
545 pp.add_printer(
|
|
546 "llvm::PointerIntPair", "^llvm::PointerIntPair<.*>$", make_pointer_int_pair_printer
|
|
547 )
|
|
548 pp.add_printer(
|
|
549 "llvm::PointerUnion", "^llvm::PointerUnion<.*>$", make_pointer_union_printer
|
|
550 )
|
|
551 pp.add_printer("llvm::ilist_node", "^llvm::ilist_node<.*>$", IlistNodePrinter)
|
|
552 pp.add_printer("llvm::iplist", "^llvm::iplist<.*>$", IlistPrinter)
|
|
553 pp.add_printer("llvm::simple_ilist", "^llvm::simple_ilist<.*>$", IlistPrinter)
|
150
|
554 gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
|