xref: /linux-6.15/scripts/gdb/linux/radixtree.py (revision b7235d6b)
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