rbtree.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. # SPDX-License-Identifier: GPL-2.0
  2. #
  3. # Copyright 2019 Google LLC.
  4. import gdb
  5. from linux import utils
  6. rb_root_type = utils.CachedType("struct rb_root")
  7. rb_node_type = utils.CachedType("struct rb_node")
  8. def rb_inorder_for_each(root):
  9. def inorder(node):
  10. if node:
  11. yield from inorder(node['rb_left'])
  12. yield node
  13. yield from inorder(node['rb_right'])
  14. yield from inorder(root['rb_node'])
  15. def rb_inorder_for_each_entry(root, gdbtype, member):
  16. for node in rb_inorder_for_each(root):
  17. yield utils.container_of(node, gdbtype, member)
  18. def rb_first(root):
  19. if root.type == rb_root_type.get_type():
  20. node = root.address.cast(rb_root_type.get_type().pointer())
  21. elif root.type != rb_root_type.get_type().pointer():
  22. raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
  23. node = root['rb_node']
  24. if node == 0:
  25. return None
  26. while node['rb_left']:
  27. node = node['rb_left']
  28. return node
  29. def rb_last(root):
  30. if root.type == rb_root_type.get_type():
  31. node = root.address.cast(rb_root_type.get_type().pointer())
  32. elif root.type != rb_root_type.get_type().pointer():
  33. raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
  34. node = root['rb_node']
  35. if node == 0:
  36. return None
  37. while node['rb_right']:
  38. node = node['rb_right']
  39. return node
  40. def rb_parent(node):
  41. parent = gdb.Value(node['__rb_parent_color'] & ~3)
  42. return parent.cast(rb_node_type.get_type().pointer())
  43. def rb_empty_node(node):
  44. return node['__rb_parent_color'] == node.address
  45. def rb_next(node):
  46. if node.type == rb_node_type.get_type():
  47. node = node.address.cast(rb_node_type.get_type().pointer())
  48. elif node.type != rb_node_type.get_type().pointer():
  49. raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
  50. if rb_empty_node(node):
  51. return None
  52. if node['rb_right']:
  53. node = node['rb_right']
  54. while node['rb_left']:
  55. node = node['rb_left']
  56. return node
  57. parent = rb_parent(node)
  58. while parent and node == parent['rb_right']:
  59. node = parent
  60. parent = rb_parent(node)
  61. return parent
  62. def rb_prev(node):
  63. if node.type == rb_node_type.get_type():
  64. node = node.address.cast(rb_node_type.get_type().pointer())
  65. elif node.type != rb_node_type.get_type().pointer():
  66. raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
  67. if rb_empty_node(node):
  68. return None
  69. if node['rb_left']:
  70. node = node['rb_left']
  71. while node['rb_right']:
  72. node = node['rb_right']
  73. return node.dereference()
  74. parent = rb_parent(node)
  75. while parent and node == parent['rb_left'].dereference():
  76. node = parent
  77. parent = rb_parent(node)
  78. return parent
  79. class LxRbFirst(gdb.Function):
  80. """Lookup and return a node from an RBTree
  81. $lx_rb_first(root): Return the node at the given index.
  82. If index is omitted, the root node is dereferenced and returned."""
  83. def __init__(self):
  84. super(LxRbFirst, self).__init__("lx_rb_first")
  85. def invoke(self, root):
  86. result = rb_first(root)
  87. if result is None:
  88. raise gdb.GdbError("No entry in tree")
  89. return result
  90. LxRbFirst()
  91. class LxRbLast(gdb.Function):
  92. """Lookup and return a node from an RBTree.
  93. $lx_rb_last(root): Return the node at the given index.
  94. If index is omitted, the root node is dereferenced and returned."""
  95. def __init__(self):
  96. super(LxRbLast, self).__init__("lx_rb_last")
  97. def invoke(self, root):
  98. result = rb_last(root)
  99. if result is None:
  100. raise gdb.GdbError("No entry in tree")
  101. return result
  102. LxRbLast()
  103. class LxRbNext(gdb.Function):
  104. """Lookup and return a node from an RBTree.
  105. $lx_rb_next(node): Return the node at the given index.
  106. If index is omitted, the root node is dereferenced and returned."""
  107. def __init__(self):
  108. super(LxRbNext, self).__init__("lx_rb_next")
  109. def invoke(self, node):
  110. result = rb_next(node)
  111. if result is None:
  112. raise gdb.GdbError("No entry in tree")
  113. return result
  114. LxRbNext()
  115. class LxRbPrev(gdb.Function):
  116. """Lookup and return a node from an RBTree.
  117. $lx_rb_prev(node): Return the node at the given index.
  118. If index is omitted, the root node is dereferenced and returned."""
  119. def __init__(self):
  120. super(LxRbPrev, self).__init__("lx_rb_prev")
  121. def invoke(self, node):
  122. result = rb_prev(node)
  123. if result is None:
  124. raise gdb.GdbError("No entry in tree")
  125. return result
  126. LxRbPrev()