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