xref: /linux-6.15/scripts/gdb/linux/rbtree.py (revision 0c77e103)
1449ca0c9SStephen Boyd# SPDX-License-Identifier: GPL-2.0
2449ca0c9SStephen Boyd#
3449ca0c9SStephen Boyd# Copyright 2019 Google LLC.
4449ca0c9SStephen Boyd
5449ca0c9SStephen Boydimport gdb
6449ca0c9SStephen Boyd
7449ca0c9SStephen Boydfrom linux import utils
8449ca0c9SStephen Boyd
9449ca0c9SStephen Boydrb_root_type = utils.CachedType("struct rb_root")
10449ca0c9SStephen Boydrb_node_type = utils.CachedType("struct rb_node")
11449ca0c9SStephen Boyd
12*0c77e103SKuan-Ying Leedef rb_inorder_for_each(root):
13*0c77e103SKuan-Ying Lee    def inorder(node):
14*0c77e103SKuan-Ying Lee        if node:
15*0c77e103SKuan-Ying Lee            yield from inorder(node['rb_left'])
16*0c77e103SKuan-Ying Lee            yield node
17*0c77e103SKuan-Ying Lee            yield from inorder(node['rb_right'])
18*0c77e103SKuan-Ying Lee
19*0c77e103SKuan-Ying Lee    yield from inorder(root['rb_node'])
20*0c77e103SKuan-Ying Lee
21*0c77e103SKuan-Ying Leedef rb_inorder_for_each_entry(root, gdbtype, member):
22*0c77e103SKuan-Ying Lee    for node in rb_inorder_for_each(root):
23*0c77e103SKuan-Ying Lee        yield utils.container_of(node, gdbtype, member)
24449ca0c9SStephen Boyd
25449ca0c9SStephen Boyddef rb_first(root):
26449ca0c9SStephen Boyd    if root.type == rb_root_type.get_type():
2750e36be1SAymeric Agon-Rambosson        node = root.address.cast(rb_root_type.get_type().pointer())
28449ca0c9SStephen Boyd    elif root.type != rb_root_type.get_type().pointer():
29449ca0c9SStephen Boyd        raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
30449ca0c9SStephen Boyd
31449ca0c9SStephen Boyd    node = root['rb_node']
32a3ec9f38SNick Desaulniers    if node == 0:
33449ca0c9SStephen Boyd        return None
34449ca0c9SStephen Boyd
35449ca0c9SStephen Boyd    while node['rb_left']:
36449ca0c9SStephen Boyd        node = node['rb_left']
37449ca0c9SStephen Boyd
38449ca0c9SStephen Boyd    return node
39449ca0c9SStephen Boyd
40449ca0c9SStephen Boyd
41449ca0c9SStephen Boyddef rb_last(root):
42449ca0c9SStephen Boyd    if root.type == rb_root_type.get_type():
4350e36be1SAymeric Agon-Rambosson        node = root.address.cast(rb_root_type.get_type().pointer())
44449ca0c9SStephen Boyd    elif root.type != rb_root_type.get_type().pointer():
45449ca0c9SStephen Boyd        raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
46449ca0c9SStephen Boyd
47449ca0c9SStephen Boyd    node = root['rb_node']
48a3ec9f38SNick Desaulniers    if node == 0:
49449ca0c9SStephen Boyd        return None
50449ca0c9SStephen Boyd
51449ca0c9SStephen Boyd    while node['rb_right']:
52449ca0c9SStephen Boyd        node = node['rb_right']
53449ca0c9SStephen Boyd
54449ca0c9SStephen Boyd    return node
55449ca0c9SStephen Boyd
56449ca0c9SStephen Boyd
57449ca0c9SStephen Boyddef rb_parent(node):
58449ca0c9SStephen Boyd    parent = gdb.Value(node['__rb_parent_color'] & ~3)
59449ca0c9SStephen Boyd    return parent.cast(rb_node_type.get_type().pointer())
60449ca0c9SStephen Boyd
61449ca0c9SStephen Boyd
62449ca0c9SStephen Boyddef rb_empty_node(node):
63449ca0c9SStephen Boyd    return node['__rb_parent_color'] == node.address
64449ca0c9SStephen Boyd
65449ca0c9SStephen Boyd
66449ca0c9SStephen Boyddef rb_next(node):
67449ca0c9SStephen Boyd    if node.type == rb_node_type.get_type():
68449ca0c9SStephen Boyd        node = node.address.cast(rb_node_type.get_type().pointer())
69449ca0c9SStephen Boyd    elif node.type != rb_node_type.get_type().pointer():
70449ca0c9SStephen Boyd        raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
71449ca0c9SStephen Boyd
72449ca0c9SStephen Boyd    if rb_empty_node(node):
73449ca0c9SStephen Boyd        return None
74449ca0c9SStephen Boyd
75449ca0c9SStephen Boyd    if node['rb_right']:
76449ca0c9SStephen Boyd        node = node['rb_right']
77449ca0c9SStephen Boyd        while node['rb_left']:
78449ca0c9SStephen Boyd            node = node['rb_left']
79449ca0c9SStephen Boyd        return node
80449ca0c9SStephen Boyd
81449ca0c9SStephen Boyd    parent = rb_parent(node)
82449ca0c9SStephen Boyd    while parent and node == parent['rb_right']:
83449ca0c9SStephen Boyd            node = parent
84449ca0c9SStephen Boyd            parent = rb_parent(node)
85449ca0c9SStephen Boyd
86449ca0c9SStephen Boyd    return parent
87449ca0c9SStephen Boyd
88449ca0c9SStephen Boyd
89449ca0c9SStephen Boyddef rb_prev(node):
90449ca0c9SStephen Boyd    if node.type == rb_node_type.get_type():
91449ca0c9SStephen Boyd        node = node.address.cast(rb_node_type.get_type().pointer())
92449ca0c9SStephen Boyd    elif node.type != rb_node_type.get_type().pointer():
93449ca0c9SStephen Boyd        raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
94449ca0c9SStephen Boyd
95449ca0c9SStephen Boyd    if rb_empty_node(node):
96449ca0c9SStephen Boyd        return None
97449ca0c9SStephen Boyd
98449ca0c9SStephen Boyd    if node['rb_left']:
99449ca0c9SStephen Boyd        node = node['rb_left']
100449ca0c9SStephen Boyd        while node['rb_right']:
101449ca0c9SStephen Boyd            node = node['rb_right']
102449ca0c9SStephen Boyd        return node.dereference()
103449ca0c9SStephen Boyd
104449ca0c9SStephen Boyd    parent = rb_parent(node)
105449ca0c9SStephen Boyd    while parent and node == parent['rb_left'].dereference():
106449ca0c9SStephen Boyd            node = parent
107449ca0c9SStephen Boyd            parent = rb_parent(node)
108449ca0c9SStephen Boyd
109449ca0c9SStephen Boyd    return parent
110449ca0c9SStephen Boyd
111449ca0c9SStephen Boyd
112449ca0c9SStephen Boydclass LxRbFirst(gdb.Function):
113449ca0c9SStephen Boyd    """Lookup and return a node from an RBTree
114449ca0c9SStephen Boyd
115449ca0c9SStephen Boyd$lx_rb_first(root): Return the node at the given index.
116449ca0c9SStephen BoydIf index is omitted, the root node is dereferenced and returned."""
117449ca0c9SStephen Boyd
118449ca0c9SStephen Boyd    def __init__(self):
119449ca0c9SStephen Boyd        super(LxRbFirst, self).__init__("lx_rb_first")
120449ca0c9SStephen Boyd
121449ca0c9SStephen Boyd    def invoke(self, root):
122449ca0c9SStephen Boyd        result = rb_first(root)
123449ca0c9SStephen Boyd        if result is None:
124449ca0c9SStephen Boyd            raise gdb.GdbError("No entry in tree")
125449ca0c9SStephen Boyd
126449ca0c9SStephen Boyd        return result
127449ca0c9SStephen Boyd
128449ca0c9SStephen Boyd
129449ca0c9SStephen BoydLxRbFirst()
130449ca0c9SStephen Boyd
131449ca0c9SStephen Boyd
132449ca0c9SStephen Boydclass LxRbLast(gdb.Function):
133449ca0c9SStephen Boyd    """Lookup and return a node from an RBTree.
134449ca0c9SStephen Boyd
135449ca0c9SStephen Boyd$lx_rb_last(root): Return the node at the given index.
136449ca0c9SStephen BoydIf index is omitted, the root node is dereferenced and returned."""
137449ca0c9SStephen Boyd
138449ca0c9SStephen Boyd    def __init__(self):
139449ca0c9SStephen Boyd        super(LxRbLast, self).__init__("lx_rb_last")
140449ca0c9SStephen Boyd
141449ca0c9SStephen Boyd    def invoke(self, root):
142449ca0c9SStephen Boyd        result = rb_last(root)
143449ca0c9SStephen Boyd        if result is None:
144449ca0c9SStephen Boyd            raise gdb.GdbError("No entry in tree")
145449ca0c9SStephen Boyd
146449ca0c9SStephen Boyd        return result
147449ca0c9SStephen Boyd
148449ca0c9SStephen Boyd
149449ca0c9SStephen BoydLxRbLast()
150449ca0c9SStephen Boyd
151449ca0c9SStephen Boyd
152449ca0c9SStephen Boydclass LxRbNext(gdb.Function):
153449ca0c9SStephen Boyd    """Lookup and return a node from an RBTree.
154449ca0c9SStephen Boyd
155449ca0c9SStephen Boyd$lx_rb_next(node): Return the node at the given index.
156449ca0c9SStephen BoydIf index is omitted, the root node is dereferenced and returned."""
157449ca0c9SStephen Boyd
158449ca0c9SStephen Boyd    def __init__(self):
159449ca0c9SStephen Boyd        super(LxRbNext, self).__init__("lx_rb_next")
160449ca0c9SStephen Boyd
161449ca0c9SStephen Boyd    def invoke(self, node):
162449ca0c9SStephen Boyd        result = rb_next(node)
163449ca0c9SStephen Boyd        if result is None:
164449ca0c9SStephen Boyd            raise gdb.GdbError("No entry in tree")
165449ca0c9SStephen Boyd
166449ca0c9SStephen Boyd        return result
167449ca0c9SStephen Boyd
168449ca0c9SStephen Boyd
169449ca0c9SStephen BoydLxRbNext()
170449ca0c9SStephen Boyd
171449ca0c9SStephen Boyd
172449ca0c9SStephen Boydclass LxRbPrev(gdb.Function):
173449ca0c9SStephen Boyd    """Lookup and return a node from an RBTree.
174449ca0c9SStephen Boyd
175449ca0c9SStephen Boyd$lx_rb_prev(node): Return the node at the given index.
176449ca0c9SStephen BoydIf index is omitted, the root node is dereferenced and returned."""
177449ca0c9SStephen Boyd
178449ca0c9SStephen Boyd    def __init__(self):
179449ca0c9SStephen Boyd        super(LxRbPrev, self).__init__("lx_rb_prev")
180449ca0c9SStephen Boyd
181449ca0c9SStephen Boyd    def invoke(self, node):
182449ca0c9SStephen Boyd        result = rb_prev(node)
183449ca0c9SStephen Boyd        if result is None:
184449ca0c9SStephen Boyd            raise gdb.GdbError("No entry in tree")
185449ca0c9SStephen Boyd
186449ca0c9SStephen Boyd        return result
187449ca0c9SStephen Boyd
188449ca0c9SStephen Boyd
189449ca0c9SStephen BoydLxRbPrev()
190