prettyprinters.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. from __future__ import print_function
  2. import sys
  3. import gdb.printing
  4. class Iterator:
  5. def __iter__(self):
  6. return self
  7. if sys.version_info.major == 2:
  8. def next(self):
  9. return self.__next__()
  10. def children(self):
  11. return self
  12. def escape_bytes(val, l):
  13. return '"' + val.string(encoding='Latin-1', length=l).encode('unicode_escape').decode() + '"'
  14. class SmallStringPrinter:
  15. """Print an llvm::SmallString object."""
  16. def __init__(self, val):
  17. self.val = val
  18. def to_string(self):
  19. begin = self.val['BeginX']
  20. return escape_bytes(begin.cast(gdb.lookup_type('char').pointer()), self.val['Size'])
  21. class StringRefPrinter:
  22. """Print an llvm::StringRef object."""
  23. def __init__(self, val):
  24. self.val = val
  25. def to_string(self):
  26. return escape_bytes(self.val['Data'], self.val['Length'])
  27. class SmallVectorPrinter(Iterator):
  28. """Print an llvm::SmallVector object."""
  29. def __init__(self, val):
  30. self.val = val
  31. t = val.type.template_argument(0).pointer()
  32. self.begin = val['BeginX'].cast(t)
  33. self.size = val['Size']
  34. self.i = 0
  35. def __next__(self):
  36. if self.i == self.size:
  37. raise StopIteration
  38. ret = '[{}]'.format(self.i), (self.begin+self.i).dereference()
  39. self.i += 1
  40. return ret
  41. def to_string(self):
  42. return 'llvm::SmallVector of Size {}, Capacity {}'.format(self.size, self.val['Capacity'])
  43. def display_hint (self):
  44. return 'array'
  45. class ArrayRefPrinter:
  46. """Print an llvm::ArrayRef object."""
  47. class _iterator:
  48. def __init__(self, begin, end):
  49. self.cur = begin
  50. self.end = end
  51. self.count = 0
  52. def __iter__(self):
  53. return self
  54. def __next__(self):
  55. if self.cur == self.end:
  56. raise StopIteration
  57. count = self.count
  58. self.count = self.count + 1
  59. cur = self.cur
  60. self.cur = self.cur + 1
  61. return '[%d]' % count, cur.dereference()
  62. if sys.version_info.major == 2:
  63. next = __next__
  64. def __init__(self, val):
  65. self.val = val
  66. def children(self):
  67. data = self.val['Data']
  68. return self._iterator(data, data + self.val['Length'])
  69. def to_string(self):
  70. return 'llvm::ArrayRef of length %d' % (self.val['Length'])
  71. def display_hint (self):
  72. return 'array'
  73. class ExpectedPrinter(Iterator):
  74. """Print an llvm::Expected object."""
  75. def __init__(self, val):
  76. self.val = val
  77. def __next__(self):
  78. val = self.val
  79. if val is None:
  80. raise StopIteration
  81. self.val = None
  82. if val['HasError']:
  83. return ('error', val['ErrorStorage'].address.cast(
  84. gdb.lookup_type('llvm::ErrorInfoBase').pointer()).dereference())
  85. return ('value', val['TStorage'].address.cast(
  86. val.type.template_argument(0).pointer()).dereference())
  87. def to_string(self):
  88. return 'llvm::Expected{}'.format(' is error' if self.val['HasError'] else '')
  89. class OptionalPrinter(Iterator):
  90. """Print an llvm::Optional object."""
  91. def __init__(self, val):
  92. self.val = val
  93. def __next__(self):
  94. val = self.val
  95. if val is None:
  96. raise StopIteration
  97. self.val = None
  98. if not val['Storage']['hasVal']:
  99. raise StopIteration
  100. return ('value', val['Storage']['value'])
  101. def to_string(self):
  102. return 'llvm::Optional{}'.format('' if self.val['Storage']['hasVal'] else ' is not initialized')
  103. class DenseMapPrinter:
  104. "Print a DenseMap"
  105. class _iterator:
  106. def __init__(self, key_info_t, begin, end):
  107. self.key_info_t = key_info_t
  108. self.cur = begin
  109. self.end = end
  110. self.advancePastEmptyBuckets()
  111. self.first = True
  112. def __iter__(self):
  113. return self
  114. def advancePastEmptyBuckets(self):
  115. # disabled until the comments below can be addressed
  116. # keeping as notes/posterity/hints for future contributors
  117. return
  118. n = self.key_info_t.name
  119. is_equal = gdb.parse_and_eval(n + '::isEqual')
  120. empty = gdb.parse_and_eval(n + '::getEmptyKey()')
  121. tombstone = gdb.parse_and_eval(n + '::getTombstoneKey()')
  122. # the following is invalid, GDB fails with:
  123. # Python Exception <class 'gdb.error'> Attempt to take address of value
  124. # not located in memory.
  125. # because isEqual took parameter (for the unsigned long key I was testing)
  126. # by const ref, and GDB
  127. # It's also not entirely general - we should be accessing the "getFirst()"
  128. # member function, not the 'first' member variable, but I've yet to figure
  129. # out how to find/call member functions (especially (const) overloaded
  130. # ones) on a gdb.Value.
  131. while self.cur != self.end and (is_equal(self.cur.dereference()['first'], empty) or is_equal(self.cur.dereference()['first'], tombstone)):
  132. self.cur = self.cur + 1
  133. def __next__(self):
  134. if self.cur == self.end:
  135. raise StopIteration
  136. cur = self.cur
  137. v = cur.dereference()['first' if self.first else 'second']
  138. if not self.first:
  139. self.cur = self.cur + 1
  140. self.advancePastEmptyBuckets()
  141. self.first = True
  142. else:
  143. self.first = False
  144. return 'x', v
  145. if sys.version_info.major == 2:
  146. next = __next__
  147. def __init__(self, val):
  148. self.val = val
  149. def children(self):
  150. t = self.val.type.template_argument(3).pointer()
  151. begin = self.val['Buckets'].cast(t)
  152. end = (begin + self.val['NumBuckets']).cast(t)
  153. return self._iterator(self.val.type.template_argument(2), begin, end)
  154. def to_string(self):
  155. return 'llvm::DenseMap with %d elements' % (self.val['NumEntries'])
  156. def display_hint(self):
  157. return 'map'
  158. class TwinePrinter:
  159. "Print a Twine"
  160. def __init__(self, val):
  161. self._val = val
  162. def display_hint(self):
  163. return 'string'
  164. def string_from_pretty_printer_lookup(self, val):
  165. '''Lookup the default pretty-printer for val and use it.
  166. If no pretty-printer is defined for the type of val, print an error and
  167. return a placeholder string.'''
  168. pp = gdb.default_visualizer(val)
  169. if pp:
  170. s = pp.to_string()
  171. # The pretty-printer may return a LazyString instead of an actual Python
  172. # string. Convert it to a Python string. However, GDB doesn't seem to
  173. # register the LazyString type, so we can't check
  174. # "type(s) == gdb.LazyString".
  175. if 'LazyString' in type(s).__name__:
  176. s = s.value().address.string()
  177. else:
  178. print(('No pretty printer for {} found. The resulting Twine ' +
  179. 'representation will be incomplete.').format(val.type.name))
  180. s = '(missing {})'.format(val.type.name)
  181. return s
  182. def is_twine_kind(self, kind, expected):
  183. if not kind.endswith(expected):
  184. return False
  185. # apparently some GDB versions add the NodeKind:: namespace
  186. # (happens for me on GDB 7.11)
  187. return kind in ('llvm::Twine::' + expected,
  188. 'llvm::Twine::NodeKind::' + expected)
  189. def string_from_child(self, child, kind):
  190. '''Return the string representation of the Twine::Child child.'''
  191. if self.is_twine_kind(kind, 'EmptyKind') or self.is_twine_kind(kind, 'NullKind'):
  192. return ''
  193. if self.is_twine_kind(kind, 'TwineKind'):
  194. return self.string_from_twine_object(child['twine'].dereference())
  195. if self.is_twine_kind(kind, 'CStringKind'):
  196. return child['cString'].string()
  197. if self.is_twine_kind(kind, 'StdStringKind'):
  198. val = child['stdString'].dereference()
  199. return self.string_from_pretty_printer_lookup(val)
  200. if self.is_twine_kind(kind, 'StringRefKind'):
  201. val = child['stringRef'].dereference()
  202. pp = StringRefPrinter(val)
  203. return pp.to_string()
  204. if self.is_twine_kind(kind, 'SmallStringKind'):
  205. val = child['smallString'].dereference()
  206. pp = SmallStringPrinter(val)
  207. return pp.to_string()
  208. if self.is_twine_kind(kind, 'CharKind'):
  209. return chr(child['character'])
  210. if self.is_twine_kind(kind, 'DecUIKind'):
  211. return str(child['decUI'])
  212. if self.is_twine_kind(kind, 'DecIKind'):
  213. return str(child['decI'])
  214. if self.is_twine_kind(kind, 'DecULKind'):
  215. return str(child['decUL'].dereference())
  216. if self.is_twine_kind(kind, 'DecLKind'):
  217. return str(child['decL'].dereference())
  218. if self.is_twine_kind(kind, 'DecULLKind'):
  219. return str(child['decULL'].dereference())
  220. if self.is_twine_kind(kind, 'DecLLKind'):
  221. return str(child['decLL'].dereference())
  222. if self.is_twine_kind(kind, 'UHexKind'):
  223. val = child['uHex'].dereference()
  224. return hex(int(val))
  225. print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
  226. 'incomplete.').format(kind))
  227. return '(unhandled {})'.format(kind)
  228. def string_from_twine_object(self, twine):
  229. '''Return the string representation of the Twine object twine.'''
  230. lhs_str = ''
  231. rhs_str = ''
  232. lhs = twine['LHS']
  233. rhs = twine['RHS']
  234. lhs_kind = str(twine['LHSKind'])
  235. rhs_kind = str(twine['RHSKind'])
  236. lhs_str = self.string_from_child(lhs, lhs_kind)
  237. rhs_str = self.string_from_child(rhs, rhs_kind)
  238. return lhs_str + rhs_str
  239. def to_string(self):
  240. return self.string_from_twine_object(self._val)
  241. pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport")
  242. pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter)
  243. pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter)
  244. pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter)
  245. pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter)
  246. pp.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter)
  247. pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter)
  248. pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter)
  249. pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter)
  250. gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)