pretty-print.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import gdb.printing
  2. import re
  3. def create_iter(item, end, idx):
  4. return vectorPrinter._iterator(item, end, idx)
  5. class vectorPrinter:
  6. class _iterator:
  7. def __init__(self, item, end, idx):
  8. self.item = item
  9. self.end = end
  10. self.size = self.end - self.item
  11. self.idx = idx
  12. def __iter__(self):
  13. return self
  14. def __next__(self):
  15. if self.item >= self.end:
  16. raise StopIteration
  17. key = '[%d]' % self.idx
  18. iter = self.item.dereference()
  19. self.item += 1
  20. self.idx += 1
  21. return key, iter
  22. def __init__(self, val):
  23. self.val = val
  24. def to_string(self):
  25. return "vector of size %d, capacity %d" % (self.val['m_size'], self.val['m_capacity'])
  26. def display_hint(self):
  27. return 'array'
  28. def children(self):
  29. return self._iterator(self.val['m_arr'], self.val['m_arr'] + self.val['m_size'], 0)
  30. def _leftmost(node):
  31. ret = node
  32. while ret['left'] != 0:
  33. ret = ret['left'].dereference()
  34. return ret
  35. def _next(node):
  36. if node['right']:
  37. return _leftmost(node['right'].dereference())
  38. else:
  39. if node['parent'] == 0:
  40. return None
  41. parent = node['parent'].dereference()
  42. if parent['left'] == node.address:
  43. return parent
  44. ret = node
  45. while True:
  46. ret = ret['parent'].dereference()
  47. if ret['parent'] == 0:
  48. return None
  49. if ret['parent'].dereference()['left'] == ret.address:
  50. break
  51. return ret['parent'].dereference()
  52. class mapPrinter:
  53. def __init__(self, val):
  54. self.val = val
  55. def to_string(self):
  56. return "types::map"
  57. def display_hint(self):
  58. return 'array'
  59. def children(self):
  60. yield '[root]', self.val['root']
  61. if self.val['root'] == 0:
  62. return
  63. nd = _leftmost(self.val['root'].dereference())
  64. i = 0
  65. while True:
  66. yield "[%d]" % i, nd['v']
  67. nd = _next(nd)
  68. i += 1
  69. if nd == None:
  70. break
  71. class stringPrinter:
  72. def __init__(self, val):
  73. self.val = val
  74. def to_string(self):
  75. return self.val['m_arr']
  76. def children(self):
  77. yield 'str', self.val['m_arr']
  78. if self.val['m_arr'] == 0:
  79. return
  80. yield 'length', self.val['m_size'] - 1
  81. ptr = self.val['m_arr']
  82. i = 0
  83. while ptr.dereference() != 0:
  84. yield '[%d]' % i, ptr.dereference()
  85. ptr += 1
  86. i += 1
  87. yield '[%d]' % i, 0
  88. class listPrinter:
  89. def __init__(self, val):
  90. self.val = val
  91. def to_string(self):
  92. return "list of size %d" % (self.val['head'].reinterpret_cast(gdb.lookup_type("size_t").pointer()) + 2).dereference()
  93. def display_hint(self):
  94. return 'array'
  95. def children(self):
  96. head = self.val['head']
  97. end = self.val['tail']
  98. yield '[head]', head
  99. yield '[tail]', end
  100. if head == 0 or end == 0:
  101. return
  102. node = head['next']
  103. idx = 0
  104. while node != end:
  105. yield '[%d]' % idx, node['value']
  106. idx += 1
  107. node = node['next']
  108. class listIteratorPrinter:
  109. def __init__(self, val):
  110. self.val = val
  111. def children(self):
  112. yield '[addr]', self.val['n']
  113. if self.val['n'] == 0:
  114. return
  115. for field in self.val['n']['value'].type.fields():
  116. yield field.name, self.val['n']['value'][field.name]
  117. class mapIteratorPrinter:
  118. def __init__(self, val):
  119. self.val = val
  120. def children(self):
  121. yield '[addr]', self.val['p']
  122. if self.val['p'] == 0:
  123. return
  124. yield '[key]', self.val['p']['v']['key']
  125. yield '[value]', self.val['p']['v']['value']
  126. class vectorIteratorPrinter:
  127. def __init__(self, val):
  128. self.val = val
  129. def children(self):
  130. yield 'value', self.val['p'].dereference()
  131. def build_pretty_printer(val):
  132. type = val.type
  133. if type.code == gdb.TYPE_CODE_REF:
  134. type = type.target()
  135. if type.code == gdb.TYPE_CODE_PTR:
  136. type = type.target()
  137. type = type.unqualified().strip_typedefs()
  138. typename = type.tag
  139. if typename == None:
  140. return None
  141. if re.compile(r"^types::list<.*?>::node<.*?>$").match(typename):
  142. return None
  143. if re.compile(r"^types::map<.*?,.*?,.*?>::iterator<.*?>$").match(typename):
  144. return mapIteratorPrinter(val)
  145. if re.compile(r"^types::list<.*?>::iterator<.*?>$").match(typename):
  146. return listIteratorPrinter(val)
  147. if re.compile(r"^types::vector<.*?>::iterator<.*?>$").match(typename):
  148. return vectorIteratorPrinter(val)
  149. if re.compile(r"^types::list<.*?>$").match(typename):
  150. return listPrinter(val)
  151. if re.compile(r"^types::vector<.*?>$").match(typename):
  152. return vectorPrinter(val)
  153. if re.compile(r"^types::string<.*?>$").match(typename):
  154. return stringPrinter(val)
  155. if re.compile(r"^types::map<.*?>$").match(typename):
  156. return mapPrinter(val)
  157. return None
  158. gdb.pretty_printers.append(build_pretty_printer)