1*b7235d6bSKieran Bingham# SPDX-License-Identifier: GPL-2.0 2*b7235d6bSKieran Bingham# 3*b7235d6bSKieran Bingham# Radix Tree Parser 4*b7235d6bSKieran Bingham# 5*b7235d6bSKieran Bingham# Copyright (c) 2016 Linaro Ltd 6*b7235d6bSKieran Bingham# Copyright (c) 2023 Broadcom 7*b7235d6bSKieran Bingham# 8*b7235d6bSKieran Bingham# Authors: 9*b7235d6bSKieran Bingham# Kieran Bingham <[email protected]> 10*b7235d6bSKieran Bingham# Florian Fainelli <[email protected]> 11*b7235d6bSKieran Bingham 12*b7235d6bSKieran Binghamimport gdb 13*b7235d6bSKieran Bingham 14*b7235d6bSKieran Binghamfrom linux import utils 15*b7235d6bSKieran Binghamfrom linux import constants 16*b7235d6bSKieran Bingham 17*b7235d6bSKieran Binghamradix_tree_root_type = utils.CachedType("struct xarray") 18*b7235d6bSKieran Binghamradix_tree_node_type = utils.CachedType("struct xa_node") 19*b7235d6bSKieran Bingham 20*b7235d6bSKieran Binghamdef is_internal_node(node): 21*b7235d6bSKieran Bingham long_type = utils.get_long_type() 22*b7235d6bSKieran Bingham return ((node.cast(long_type) & constants.LX_RADIX_TREE_ENTRY_MASK) == constants.LX_RADIX_TREE_INTERNAL_NODE) 23*b7235d6bSKieran Bingham 24*b7235d6bSKieran Binghamdef entry_to_node(node): 25*b7235d6bSKieran Bingham long_type = utils.get_long_type() 26*b7235d6bSKieran Bingham node_type = node.type 27*b7235d6bSKieran Bingham indirect_ptr = node.cast(long_type) & ~constants.LX_RADIX_TREE_INTERNAL_NODE 28*b7235d6bSKieran Bingham return indirect_ptr.cast(radix_tree_node_type.get_type().pointer()) 29*b7235d6bSKieran Bingham 30*b7235d6bSKieran Binghamdef node_maxindex(node): 31*b7235d6bSKieran Bingham return (constants.LX_RADIX_TREE_MAP_SIZE << node['shift']) - 1 32*b7235d6bSKieran Bingham 33*b7235d6bSKieran Binghamdef lookup(root, index): 34*b7235d6bSKieran Bingham if root.type == radix_tree_root_type.get_type().pointer(): 35*b7235d6bSKieran Bingham node = root.dereference() 36*b7235d6bSKieran Bingham elif root.type != radix_tree_root_type.get_type(): 37*b7235d6bSKieran Bingham raise gdb.GdbError("must be {} not {}" 38*b7235d6bSKieran Bingham .format(radix_tree_root_type.get_type(), root.type)) 39*b7235d6bSKieran Bingham 40*b7235d6bSKieran Bingham node = root['xa_head'] 41*b7235d6bSKieran Bingham if node == 0: 42*b7235d6bSKieran Bingham return None 43*b7235d6bSKieran Bingham 44*b7235d6bSKieran Bingham if not (is_internal_node(node)): 45*b7235d6bSKieran Bingham if (index > 0): 46*b7235d6bSKieran Bingham return None 47*b7235d6bSKieran Bingham return node 48*b7235d6bSKieran Bingham 49*b7235d6bSKieran Bingham node = entry_to_node(node) 50*b7235d6bSKieran Bingham maxindex = node_maxindex(node) 51*b7235d6bSKieran Bingham 52*b7235d6bSKieran Bingham if (index > maxindex): 53*b7235d6bSKieran Bingham return None 54*b7235d6bSKieran Bingham 55*b7235d6bSKieran Bingham shift = node['shift'] + constants.LX_RADIX_TREE_MAP_SHIFT 56*b7235d6bSKieran Bingham 57*b7235d6bSKieran Bingham while True: 58*b7235d6bSKieran Bingham offset = (index >> node['shift']) & constants.LX_RADIX_TREE_MAP_MASK 59*b7235d6bSKieran Bingham slot = node['slots'][offset] 60*b7235d6bSKieran Bingham 61*b7235d6bSKieran Bingham if slot == 0: 62*b7235d6bSKieran Bingham return None 63*b7235d6bSKieran Bingham 64*b7235d6bSKieran Bingham node = slot.cast(node.type.pointer()).dereference() 65*b7235d6bSKieran Bingham if node == 0: 66*b7235d6bSKieran Bingham return None 67*b7235d6bSKieran Bingham 68*b7235d6bSKieran Bingham shift -= constants.LX_RADIX_TREE_MAP_SHIFT 69*b7235d6bSKieran Bingham if (shift <= 0): 70*b7235d6bSKieran Bingham break 71*b7235d6bSKieran Bingham 72*b7235d6bSKieran Bingham return node 73*b7235d6bSKieran Bingham 74*b7235d6bSKieran Binghamclass LxRadixTree(gdb.Function): 75*b7235d6bSKieran Bingham """ Lookup and return a node from a RadixTree. 76*b7235d6bSKieran Bingham 77*b7235d6bSKieran Bingham$lx_radix_tree_lookup(root_node [, index]): Return the node at the given index. 78*b7235d6bSKieran BinghamIf index is omitted, the root node is dereference and returned.""" 79*b7235d6bSKieran Bingham 80*b7235d6bSKieran Bingham def __init__(self): 81*b7235d6bSKieran Bingham super(LxRadixTree, self).__init__("lx_radix_tree_lookup") 82*b7235d6bSKieran Bingham 83*b7235d6bSKieran Bingham def invoke(self, root, index=0): 84*b7235d6bSKieran Bingham result = lookup(root, index) 85*b7235d6bSKieran Bingham if result is None: 86*b7235d6bSKieran Bingham raise gdb.GdbError("No entry in tree at index {}".format(index)) 87*b7235d6bSKieran Bingham 88*b7235d6bSKieran Bingham return result 89*b7235d6bSKieran Bingham 90*b7235d6bSKieran BinghamLxRadixTree() 91