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")