2 # gdb helper commands and functions for Linux kernel debugging
6 # Copyright (c) 2016 Linaro Ltd
11 # This work is licensed under the terms of the GNU GPL version 2.
16 from linux import utils
17 from linux import constants
19 radix_tree_root_type = utils.CachedType("struct radix_tree_root")
20 radix_tree_node_type = utils.CachedType("struct radix_tree_node")
23 def is_indirect_ptr(node):
24 long_type = utils.get_long_type()
25 return (node.cast(long_type) & constants.LX_RADIX_TREE_INDIRECT_PTR)
28 def indirect_to_ptr(node):
29 long_type = utils.get_long_type()
31 indirect_ptr = node.cast(long_type) & ~constants.LX_RADIX_TREE_INDIRECT_PTR
32 return indirect_ptr.cast(node_type)
36 height = height & constants.LX_RADIX_TREE_HEIGHT_MASK
37 return gdb.parse_and_eval("height_to_maxindex["+str(height)+"]")
40 def lookup(root, index):
41 if root.type == radix_tree_root_type.get_type().pointer():
42 root = root.dereference()
43 elif root.type != radix_tree_root_type.get_type():
44 raise gdb.GdbError("Must be struct radix_tree_root not {}"
51 if not (is_indirect_ptr(node)):
56 node = indirect_to_ptr(node)
58 height = node['path'] & constants.LX_RADIX_TREE_HEIGHT_MASK
59 if (index > maxindex(height)):
62 shift = (height-1) * constants.LX_RADIX_TREE_MAP_SHIFT
65 new_index = (index >> shift) & constants.LX_RADIX_TREE_MAP_MASK
66 slot = node['slots'][new_index]
68 node = slot.cast(node.type.pointer()).dereference()
72 shift -= constants.LX_RADIX_TREE_MAP_SHIFT
81 class LxRadixTree(gdb.Function):
82 """ Lookup and return a node from a RadixTree.
84 $lx_radix_tree_lookup(root_node [, index]): Return the node at the given index.
85 If index is omitted, the root node is dereferenced and returned."""
88 super(LxRadixTree, self).__init__("lx_radix_tree_lookup")
90 def invoke(self, root, index=0):
91 result = lookup(root, index)
93 raise gdb.GdbError("No entry in tree at index {}".format(index))