pretty-print.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. from typing import Any, Iterator
  2. from gdb import Frame
  3. import gdb.printing
  4. from gdb.FrameDecorator import FrameDecorator
  5. import re
  6. from os import environ
  7. def delegateChildren(val: gdb.Value):
  8. try:
  9. for field in val.type.fields():
  10. try:
  11. yield field.name, val[field]
  12. except:
  13. yield field.name, '<Error>'
  14. except TypeError:
  15. return
  16. def delegateToString(val: gdb.Value):
  17. try:
  18. val.type.fields()
  19. return None
  20. except:
  21. return val
  22. class NonNull:
  23. def __init__(self, val: gdb.Value):
  24. pointer = val['pointer']
  25. if pointer.type.code == gdb.TYPE_CODE_PTR:
  26. self.pointer = pointer
  27. self.length = None
  28. self.type = pointer.type.target().name
  29. else:
  30. fields = pointer.type.fields()
  31. self.pointer, self.length = pointer[fields[0]], pointer[fields[1]]
  32. self.type = '[%s]' % self.pointer['data'].type
  33. def is_slice(self):
  34. return self.length is not None
  35. class NonNullPrinter:
  36. def __init__(self, val: gdb.Value):
  37. self.ptr = NonNull(val)
  38. def to_string(self):
  39. return 'NonNull<%s>(0x%x)' % (self.ptr.type, self.ptr.pointer)
  40. def children(self):
  41. try:
  42. for item in delegateChildren(self.ptr.pointer.dereference()):
  43. yield item
  44. except:
  45. yield '[error]', '<Error>'
  46. class ThreadLocalPrinter:
  47. def tls_base(self):
  48. return gdb.parse_and_eval("$gs_base")
  49. def __init__(self, val: gdb.Value):
  50. name = val.type.unqualified().strip_typedefs().name
  51. symbol, _ = gdb.lookup_symbol(name.replace('_access_', '_percpu_inner_'))
  52. value = symbol.value()
  53. value_type = value.type
  54. self.address = self.tls_base() + value.address.cast(gdb.lookup_type('size_t'))
  55. self.address = self.address.cast(value_type.pointer())
  56. def to_string(self):
  57. return delegateToString(self.address.dereference())
  58. def children(self):
  59. yield '[data]', self.address.dereference()
  60. class LockPrinter:
  61. def __init__(self, val: gdb.Value):
  62. self.val = val
  63. def to_string(self):
  64. return delegateToString(self.val['value']['value'])
  65. def children(self):
  66. return delegateChildren(self.val['value']['value'])
  67. class PagePrinter:
  68. def PAGE_ARRAY():
  69. return 0xffffff8040000000
  70. def __init__(self, val: gdb.Value):
  71. self.val = val
  72. def display_hint(self):
  73. 'string'
  74. def to_string(self):
  75. return 'Pages of order %d' % self.val['order']
  76. class UnwrapPrinter:
  77. def __init__(self, val: gdb.Value, name: str):
  78. self.val = val
  79. self.name = name
  80. def to_string(self):
  81. return delegateToString(self.val[self.name])
  82. def children(self):
  83. return delegateChildren(self.val[self.name])
  84. class DentryPrinter:
  85. def __init__(self, val: gdb.Value):
  86. self.val = val
  87. def to_string(self):
  88. try:
  89. return 'Dentry'
  90. except:
  91. return '<Error>'
  92. def children(self):
  93. yield 'hash', self.val['hash']
  94. yield 'name', self.val['name']
  95. class ArcPrinter:
  96. def __init__(self, valobj: gdb.Value):
  97. self._valobj = valobj
  98. self._ptr = NonNull(valobj['ptr'])
  99. for field in self._ptr.pointer.type.fields():
  100. print(field.name, self._ptr.pointer[field])
  101. self._value = self._ptr.pointer['data']
  102. self._strong = self._ptr.pointer['strong']['v']['value']
  103. self._weak = self._ptr.pointer['weak']['v']['value'] - 1
  104. def to_string(self):
  105. if self._ptr.type == '[u8]':
  106. return 'Arc(%s)' % self._value.address.lazy_string(encoding='utf-8', length=self._ptr.length)
  107. else:
  108. return 'Arc(strong={}, weak={})'.format(int(self._strong), int(self._weak))
  109. def children(self):
  110. if not self._ptr.is_slice():
  111. for item in delegateChildren(self._value):
  112. yield item
  113. else:
  114. iter = (self._value.address + idx for idx in range(self._ptr.length))
  115. for idx, ptr in enumerate(iter):
  116. elem = ptr.dereference()
  117. try:
  118. str(elem)
  119. yield str(idx), elem
  120. except RuntimeError:
  121. yield str(idx), '[inaccessible]'
  122. break
  123. def build_pretty_printer(val: gdb.Value):
  124. type: gdb.Type = val.type.unqualified().strip_typedefs()
  125. typename = type.tag
  126. if typename == None:
  127. return None
  128. if re.compile(r"^.*::_access_[a-zA-Z0-9_]*$").match(typename):
  129. return ThreadLocalPrinter(val)
  130. if re.compile(r"^gbos_rust_part::sync::lock::Lock<.*>$").match(typename):
  131. return LockPrinter(val)
  132. if re.compile(r"^gbos_rust_part::kernel::mem::paging::Page$").match(typename):
  133. return PagePrinter(val)
  134. if re.compile(r"^gbos_rust_part::kernel::([a-zA-Z_]+::)*Dentry$").match(typename):
  135. return DentryPrinter(val)
  136. if re.compile(r"^(core::([a-z_]+::)+)UnsafeCell<.+>$").match(typename):
  137. return UnwrapPrinter(val, 'value')
  138. if re.compile(r"^(core::([a-z_]+::)+)NonNull<.+>$").match(typename):
  139. return NonNullPrinter(val)
  140. if re.compile(r"^(alloc::([a-z_]+::)+)Arc<.+>$").match(typename):
  141. return ArcPrinter(val)
  142. return None
  143. gdb.execute('skip -rfu ^core::([a-zA-Z0-9_]+::)*[a-zA-Z0-9_<>]+')
  144. gdb.execute('skip -rfu ^alloc::([a-zA-Z0-9_]+::)*[a-zA-Z0-9_<>]+')
  145. gdb.execute('skip -rfu ^std::([a-zA-Z0-9_]+::)*[a-zA-Z0-9_<>]+')
  146. gdb.execute('skip -rfu "^gbos_rust_part::sync::lock::Lock<[a-zA-Z0-9_<>: ,]+, [a-zA-Z0-9_<>: ,]+>::new<[a-zA-Z0-9_<>: ,]+, [a-zA-Z0-9_<>: ,]+>"')
  147. gdb.execute('skip -rfu "^gbos_rust_part::sync::locked::Locked<[a-zA-Z0-9_<>: ,]+, [a-zA-Z0-9_<>: ,]+>::new<[a-zA-Z0-9_<>: ,]+, [a-zA-Z0-9_<>: ,]+>"')
  148. # gdb.execute('source ' + environ['HOME'] + '/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/etc/gdb_load_rust_pretty_printers.py')
  149. gdb.pretty_printers.append(build_pretty_printer)