Linux Audio

Check our new training course

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()