aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/gdb/linux
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham@linaro.org>2016-05-23 19:25:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-23 20:04:14 -0400
commite127a73d41ac471d7e3ba950cf128f42d6ee3448 (patch)
tree2924b84523d67d46d9d533ac88e011a82054b5e3 /scripts/gdb/linux
parent4bc393dbcf1915224e8947211a0ca906f9de7c56 (diff)
scripts/gdb: add a Radix Tree Parser
Linux makes use of the Radix Tree data structure to store pointers indexed by integer values. This structure is utilised across many structures in the kernel including the IRQ descriptor tables, and several filesystems. This module provides a method to lookup values from a structure given its head node. Usage: The function lx_radix_tree_lookup, must be given a symbol of type struct radix_tree_root, and an index into that tree. The object returned is a generic integer value, and must be cast correctly to the type based on the storage in the data structure. For example, to print the irq descriptor in the sparse irq_desc_tree at index 18, try the following: (gdb) print (struct irq_desc)$lx_radix_tree_lookup(irq_desc_tree, 18) Link: http://lkml.kernel.org/r/d2028c55e50cf95a9b7f8ca0d11885174b0cc709.1462865983.git.jan.kiszka@siemens.com Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts/gdb/linux')
-rw-r--r--scripts/gdb/linux/constants.py.in7
-rw-r--r--scripts/gdb/linux/radixtree.py97
2 files changed, 104 insertions, 0 deletions
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 7986f4e0da12..07e6c2befe36 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -14,6 +14,7 @@
14 14
15#include <linux/fs.h> 15#include <linux/fs.h>
16#include <linux/mount.h> 16#include <linux/mount.h>
17#include <linux/radix-tree.h>
17 18
18/* We need to stringify expanded macros so that they can be parsed */ 19/* We need to stringify expanded macros so that they can be parsed */
19 20
@@ -50,3 +51,9 @@ LX_VALUE(MNT_NOEXEC)
50LX_VALUE(MNT_NOATIME) 51LX_VALUE(MNT_NOATIME)
51LX_VALUE(MNT_NODIRATIME) 52LX_VALUE(MNT_NODIRATIME)
52LX_VALUE(MNT_RELATIME) 53LX_VALUE(MNT_RELATIME)
54
55/* linux/radix-tree.h */
56LX_VALUE(RADIX_TREE_INDIRECT_PTR)
57LX_GDBPARSED(RADIX_TREE_HEIGHT_MASK)
58LX_GDBPARSED(RADIX_TREE_MAP_SHIFT)
59LX_GDBPARSED(RADIX_TREE_MAP_MASK)
diff --git a/scripts/gdb/linux/radixtree.py b/scripts/gdb/linux/radixtree.py
new file mode 100644
index 000000000000..0fdef4e2971a
--- /dev/null
+++ b/scripts/gdb/linux/radixtree.py
@@ -0,0 +1,97 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# Radix Tree Parser
5#
6# Copyright (c) 2016 Linaro Ltd
7#
8# Authors:
9# Kieran Bingham <kieran.bingham@linaro.org>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15
16from linux import utils
17from linux import constants
18
19radix_tree_root_type = utils.CachedType("struct radix_tree_root")
20radix_tree_node_type = utils.CachedType("struct radix_tree_node")
21
22
23def is_indirect_ptr(node):
24 long_type = utils.get_long_type()
25 return (node.cast(long_type) & constants.LX_RADIX_TREE_INDIRECT_PTR)
26
27
28def indirect_to_ptr(node):
29 long_type = utils.get_long_type()
30 node_type = node.type
31 indirect_ptr = node.cast(long_type) & ~constants.LX_RADIX_TREE_INDIRECT_PTR
32 return indirect_ptr.cast(node_type)
33
34
35def maxindex(height):
36 height = height & constants.LX_RADIX_TREE_HEIGHT_MASK
37 return gdb.parse_and_eval("height_to_maxindex["+str(height)+"]")
38
39
40def 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 {}"
45 .format(root.type))
46
47 node = root['rnode']
48 if node is 0:
49 return None
50
51 if not (is_indirect_ptr(node)):
52 if (index > 0):
53 return None
54 return node
55
56 node = indirect_to_ptr(node)
57
58 height = node['path'] & constants.LX_RADIX_TREE_HEIGHT_MASK
59 if (index > maxindex(height)):
60 return None
61
62 shift = (height-1) * constants.LX_RADIX_TREE_MAP_SHIFT
63
64 while True:
65 new_index = (index >> shift) & constants.LX_RADIX_TREE_MAP_MASK
66 slot = node['slots'][new_index]
67
68 node = slot.cast(node.type.pointer()).dereference()
69 if node is 0:
70 return None
71
72 shift -= constants.LX_RADIX_TREE_MAP_SHIFT
73 height -= 1
74
75 if (height <= 0):
76 break
77
78 return node
79
80
81class LxRadixTree(gdb.Function):
82 """ Lookup and return a node from a RadixTree.
83
84$lx_radix_tree_lookup(root_node [, index]): Return the node at the given index.
85If index is omitted, the root node is dereferenced and returned."""
86
87 def __init__(self):
88 super(LxRadixTree, self).__init__("lx_radix_tree_lookup")
89
90 def invoke(self, root, index=0):
91 result = lookup(root, index)
92 if result is None:
93 raise gdb.GdbError("No entry in tree at index {}".format(index))
94
95 return result
96
97LxRadixTree()