Commit | Line | Data |
---|---|---|
084f6b1e TW |
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 | ||
14 | import gdb | |
15 | ||
16 | from linux import utils | |
17 | ||
18 | list_head = utils.CachedType("struct list_head") | |
19 | ||
20 | ||
21 | def list_check(head): | |
22 | nb = 0 | |
23 | c = head | |
24 | if (c.type != list_head.get_type()): | |
25 | raise gdb.GdbError('The argument should be of type (struct list_head)') | |
26 | try: | |
27 | gdb.write("Starting with: {}\n".format(c)) | |
28 | except gdb.MemoryError: | |
29 | gdb.write('head is not accessible\n') | |
30 | return | |
31 | while True: | |
32 | p = c['prev'].dereference() | |
33 | n = c['next'].dereference() | |
34 | try: | |
35 | if p['next'] != c.address: | |
36 | gdb.write('prev.next != current: ' | |
37 | 'current@{current_addr}={current} ' | |
38 | 'prev@{p_addr}={p}\n'.format( | |
39 | current_addr=c.address, | |
40 | current=c, | |
41 | p_addr=p.address, | |
42 | p=p, | |
43 | )) | |
44 | return | |
45 | except gdb.MemoryError: | |
46 | gdb.write('prev is not accessible: ' | |
47 | 'current@{current_addr}={current}\n'.format( | |
48 | current_addr=c.address, | |
49 | current=c | |
50 | )) | |
51 | return | |
52 | try: | |
53 | if n['prev'] != c.address: | |
54 | gdb.write('next.prev != current: ' | |
55 | 'current@{current_addr}={current} ' | |
56 | 'next@{n_addr}={n}\n'.format( | |
57 | current_addr=c.address, | |
58 | current=c, | |
59 | n_addr=n.address, | |
60 | n=n, | |
61 | )) | |
62 | return | |
63 | except gdb.MemoryError: | |
64 | gdb.write('next is not accessible: ' | |
65 | 'current@{current_addr}={current}\n'.format( | |
66 | current_addr=c.address, | |
67 | current=c | |
68 | )) | |
69 | return | |
70 | c = n | |
71 | nb += 1 | |
72 | if c == head: | |
73 | gdb.write("list is consistent: {} node(s)\n".format(nb)) | |
74 | return | |
75 | ||
76 | ||
77 | class LxListChk(gdb.Command): | |
78 | """Verify a list consistency""" | |
79 | ||
80 | def __init__(self): | |
81 | super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA) | |
82 | ||
83 | def invoke(self, arg, from_tty): | |
84 | argv = gdb.string_to_argv(arg) | |
85 | if len(argv) != 1: | |
86 | raise gdb.GdbError("lx-list-check takes one argument") | |
87 | list_check(gdb.parse_and_eval(argv[0])) | |
88 | ||
89 | LxListChk() |