Loading...
Note: File does not exist in v3.15.
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# list tools
5#
6# Copyright (c) Thiebaud Weksteen, 2015
7#
8# Authors:
9# Thiebaud Weksteen <thiebaud@weksteen.fr>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15
16from linux import utils
17
18list_head = utils.CachedType("struct list_head")
19hlist_head = utils.CachedType("struct hlist_head")
20hlist_node = utils.CachedType("struct hlist_node")
21
22
23def list_for_each(head):
24 if head.type == list_head.get_type().pointer():
25 head = head.dereference()
26 elif head.type != list_head.get_type():
27 raise TypeError("Must be struct list_head not {}"
28 .format(head.type))
29
30 if head['next'] == 0:
31 gdb.write("list_for_each: Uninitialized list '{}' treated as empty\n"
32 .format(head.address))
33 return
34
35 node = head['next'].dereference()
36 while node.address != head.address:
37 yield node.address
38 node = node['next'].dereference()
39
40
41def list_for_each_entry(head, gdbtype, member):
42 for node in list_for_each(head):
43 yield utils.container_of(node, gdbtype, member)
44
45
46def hlist_for_each(head):
47 if head.type == hlist_head.get_type().pointer():
48 head = head.dereference()
49 elif head.type != hlist_head.get_type():
50 raise TypeError("Must be struct hlist_head not {}"
51 .format(head.type))
52
53 node = head['first'].dereference()
54 while node.address:
55 yield node.address
56 node = node['next'].dereference()
57
58
59def hlist_for_each_entry(head, gdbtype, member):
60 for node in hlist_for_each(head):
61 yield utils.container_of(node, gdbtype, member)
62
63
64def list_check(head):
65 nb = 0
66 if (head.type == list_head.get_type().pointer()):
67 head = head.dereference()
68 elif (head.type != list_head.get_type()):
69 raise gdb.GdbError('argument must be of type (struct list_head [*])')
70 c = head
71 try:
72 gdb.write("Starting with: {}\n".format(c))
73 except gdb.MemoryError:
74 gdb.write('head is not accessible\n')
75 return
76 while True:
77 p = c['prev'].dereference()
78 n = c['next'].dereference()
79 try:
80 if p['next'] != c.address:
81 gdb.write('prev.next != current: '
82 'current@{current_addr}={current} '
83 'prev@{p_addr}={p}\n'.format(
84 current_addr=c.address,
85 current=c,
86 p_addr=p.address,
87 p=p,
88 ))
89 return
90 except gdb.MemoryError:
91 gdb.write('prev is not accessible: '
92 'current@{current_addr}={current}\n'.format(
93 current_addr=c.address,
94 current=c
95 ))
96 return
97 try:
98 if n['prev'] != c.address:
99 gdb.write('next.prev != current: '
100 'current@{current_addr}={current} '
101 'next@{n_addr}={n}\n'.format(
102 current_addr=c.address,
103 current=c,
104 n_addr=n.address,
105 n=n,
106 ))
107 return
108 except gdb.MemoryError:
109 gdb.write('next is not accessible: '
110 'current@{current_addr}={current}\n'.format(
111 current_addr=c.address,
112 current=c
113 ))
114 return
115 c = n
116 nb += 1
117 if c == head:
118 gdb.write("list is consistent: {} node(s)\n".format(nb))
119 return
120
121
122class LxListChk(gdb.Command):
123 """Verify a list consistency"""
124
125 def __init__(self):
126 super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
127 gdb.COMPLETE_EXPRESSION)
128
129 def invoke(self, arg, from_tty):
130 argv = gdb.string_to_argv(arg)
131 if len(argv) != 1:
132 raise gdb.GdbError("lx-list-check takes one argument")
133 list_check(gdb.parse_and_eval(argv[0]))
134
135
136LxListChk()