2 # gdb helper commands and functions for Linux kernel debugging
6 # Copyright (c) 2016 Linaro Ltd
9 # Kieran Bingham <kieran.bingham@linaro.org>
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
))