1 # SPDX-License-Identifier: GPL-2.0
3 # Copyright 2019 Google LLC.
7 from linux import utils
9 rb_root_type = utils.CachedType("struct rb_root")
10 rb_node_type = utils.CachedType("struct rb_node")
12 def rb_inorder_for_each(root):
15 yield from inorder(node['rb_left'])
17 yield from inorder(node['rb_right'])
19 yield from inorder(root['rb_node'])
21 def rb_inorder_for_each_entry(root, gdbtype, member):
22 for node in rb_inorder_for_each(root):
23 yield utils.container_of(node, gdbtype, member)
26 if root.type == rb_root_type.get_type():
27 node = root.address.cast(rb_root_type.get_type().pointer())
28 elif root.type != rb_root_type.get_type().pointer():
29 raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
31 node = root['rb_node']
35 while node['rb_left']:
36 node = node['rb_left']
42 if root.type == rb_root_type.get_type():
43 node = root.address.cast(rb_root_type.get_type().pointer())
44 elif root.type != rb_root_type.get_type().pointer():
45 raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
47 node = root['rb_node']
51 while node['rb_right']:
52 node = node['rb_right']
58 parent = gdb.Value(node['__rb_parent_color'] & ~3)
59 return parent.cast(rb_node_type.get_type().pointer())
62 def rb_empty_node(node):
63 return node['__rb_parent_color'] == node.address
67 if node.type == rb_node_type.get_type():
68 node = node.address.cast(rb_node_type.get_type().pointer())
69 elif node.type != rb_node_type.get_type().pointer():
70 raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
72 if rb_empty_node(node):
76 node = node['rb_right']
77 while node['rb_left']:
78 node = node['rb_left']
81 parent = rb_parent(node)
82 while parent and node == parent['rb_right']:
84 parent = rb_parent(node)
90 if node.type == rb_node_type.get_type():
91 node = node.address.cast(rb_node_type.get_type().pointer())
92 elif node.type != rb_node_type.get_type().pointer():
93 raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
95 if rb_empty_node(node):
99 node = node['rb_left']
100 while node['rb_right']:
101 node = node['rb_right']
102 return node.dereference()
104 parent = rb_parent(node)
105 while parent and node == parent['rb_left'].dereference():
107 parent = rb_parent(node)
112 class LxRbFirst(gdb.Function):
113 """Lookup and return a node from an RBTree
115 $lx_rb_first(root): Return the node at the given index.
116 If index is omitted, the root node is dereferenced and returned."""
119 super(LxRbFirst, self).__init__("lx_rb_first")
121 def invoke(self, root):
122 result = rb_first(root)
124 raise gdb.GdbError("No entry in tree")
132 class LxRbLast(gdb.Function):
133 """Lookup and return a node from an RBTree.
135 $lx_rb_last(root): Return the node at the given index.
136 If index is omitted, the root node is dereferenced and returned."""
139 super(LxRbLast, self).__init__("lx_rb_last")
141 def invoke(self, root):
142 result = rb_last(root)
144 raise gdb.GdbError("No entry in tree")
152 class LxRbNext(gdb.Function):
153 """Lookup and return a node from an RBTree.
155 $lx_rb_next(node): Return the node at the given index.
156 If index is omitted, the root node is dereferenced and returned."""
159 super(LxRbNext, self).__init__("lx_rb_next")
161 def invoke(self, node):
162 result = rb_next(node)
164 raise gdb.GdbError("No entry in tree")
172 class LxRbPrev(gdb.Function):
173 """Lookup and return a node from an RBTree.
175 $lx_rb_prev(node): Return the node at the given index.
176 If index is omitted, the root node is dereferenced and returned."""
179 super(LxRbPrev, self).__init__("lx_rb_prev")
181 def invoke(self, node):
182 result = rb_prev(node)
184 raise gdb.GdbError("No entry in tree")