rbtree.py 4.2 KB

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