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