2 # gdb helper commands and functions for Linux kernel debugging
6 # Copyright (c) Thiebaud Weksteen, 2015
11 # This work is licensed under the terms of the GNU GPL version 2.
16 from linux import utils
18 list_head = utils.CachedType("struct list_head")
19 hlist_head = utils.CachedType("struct hlist_head")
20 hlist_node = utils.CachedType("struct hlist_node")
23 def 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 {}"
31 gdb.write("list_for_each: Uninitialized list '{}' treated as empty\n"
32 .format(head.address))
35 node = head['next'].dereference()
36 while node.address != head.address:
38 node = node['next'].dereference()
41 def list_for_each_entry(head, gdbtype, member):
42 for node in list_for_each(head):
43 yield utils.container_of(node, gdbtype, member)
46 def 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 {}"
53 node = head['first'].dereference()
56 node = node['next'].dereference()
59 def hlist_for_each_entry(head, gdbtype, member):
60 for node in hlist_for_each(head):
61 yield utils.container_of(node, gdbtype, member)
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 [*])')
72 gdb.write("Starting with: {}\n".format(c))
73 except gdb.MemoryError:
74 gdb.write('head is not accessible\n')
77 p = c['prev'].dereference()
78 n = c['next'].dereference()
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,
90 except gdb.MemoryError:
91 gdb.write('prev is not accessible: '
92 'current@{current_addr}={current}\n'.format(
93 current_addr=c.address,
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,
108 except gdb.MemoryError:
109 gdb.write('next is not accessible: '
110 'current@{current_addr}={current}\n'.format(
111 current_addr=c.address,
118 gdb.write("list is consistent: {} node(s)\n".format(nb))
122 class LxListChk(gdb.Command):
123 """Verify a list consistency"""
126 super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
127 gdb.COMPLETE_EXPRESSION)
129 def invoke(self, arg, from_tty):
130 argv = gdb.string_to_argv(arg)
132 raise gdb.GdbError("lx-list-check takes one argument")
133 list_check(gdb.parse_and_eval(argv[0]))