Back to home page

OSCL-LXR

 
 

    


0001 #
0002 # gdb helper commands and functions for Linux kernel debugging
0003 #
0004 #  list tools
0005 #
0006 # Copyright (c) Thiebaud Weksteen, 2015
0007 #
0008 # Authors:
0009 #  Thiebaud Weksteen <thiebaud@weksteen.fr>
0010 #
0011 # This work is licensed under the terms of the GNU GPL version 2.
0012 #
0013 
0014 import gdb
0015 
0016 from linux import utils
0017 
0018 list_head = utils.CachedType("struct list_head")
0019 hlist_head = utils.CachedType("struct hlist_head")
0020 hlist_node = utils.CachedType("struct hlist_node")
0021 
0022 
0023 def list_for_each(head):
0024     if head.type == list_head.get_type().pointer():
0025         head = head.dereference()
0026     elif head.type != list_head.get_type():
0027         raise TypeError("Must be struct list_head not {}"
0028                            .format(head.type))
0029 
0030     if head['next'] == 0:
0031         gdb.write("list_for_each: Uninitialized list '{}' treated as empty\n"
0032                      .format(head.address))
0033         return
0034 
0035     node = head['next'].dereference()
0036     while node.address != head.address:
0037         yield node.address
0038         node = node['next'].dereference()
0039 
0040 
0041 def list_for_each_entry(head, gdbtype, member):
0042     for node in list_for_each(head):
0043         yield utils.container_of(node, gdbtype, member)
0044 
0045 
0046 def hlist_for_each(head):
0047     if head.type == hlist_head.get_type().pointer():
0048         head = head.dereference()
0049     elif head.type != hlist_head.get_type():
0050         raise TypeError("Must be struct hlist_head not {}"
0051                            .format(head.type))
0052 
0053     node = head['first'].dereference()
0054     while node.address:
0055         yield node.address
0056         node = node['next'].dereference()
0057 
0058 
0059 def hlist_for_each_entry(head, gdbtype, member):
0060     for node in hlist_for_each(head):
0061         yield utils.container_of(node, gdbtype, member)
0062 
0063 
0064 def list_check(head):
0065     nb = 0
0066     if (head.type == list_head.get_type().pointer()):
0067         head = head.dereference()
0068     elif (head.type != list_head.get_type()):
0069         raise gdb.GdbError('argument must be of type (struct list_head [*])')
0070     c = head
0071     try:
0072         gdb.write("Starting with: {}\n".format(c))
0073     except gdb.MemoryError:
0074         gdb.write('head is not accessible\n')
0075         return
0076     while True:
0077         p = c['prev'].dereference()
0078         n = c['next'].dereference()
0079         try:
0080             if p['next'] != c.address:
0081                 gdb.write('prev.next != current: '
0082                           'current@{current_addr}={current} '
0083                           'prev@{p_addr}={p}\n'.format(
0084                               current_addr=c.address,
0085                               current=c,
0086                               p_addr=p.address,
0087                               p=p,
0088                           ))
0089                 return
0090         except gdb.MemoryError:
0091             gdb.write('prev is not accessible: '
0092                       'current@{current_addr}={current}\n'.format(
0093                           current_addr=c.address,
0094                           current=c
0095                       ))
0096             return
0097         try:
0098             if n['prev'] != c.address:
0099                 gdb.write('next.prev != current: '
0100                           'current@{current_addr}={current} '
0101                           'next@{n_addr}={n}\n'.format(
0102                               current_addr=c.address,
0103                               current=c,
0104                               n_addr=n.address,
0105                               n=n,
0106                           ))
0107                 return
0108         except gdb.MemoryError:
0109             gdb.write('next is not accessible: '
0110                       'current@{current_addr}={current}\n'.format(
0111                           current_addr=c.address,
0112                           current=c
0113                       ))
0114             return
0115         c = n
0116         nb += 1
0117         if c == head:
0118             gdb.write("list is consistent: {} node(s)\n".format(nb))
0119             return
0120 
0121 
0122 class LxListChk(gdb.Command):
0123     """Verify a list consistency"""
0124 
0125     def __init__(self):
0126         super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
0127                                         gdb.COMPLETE_EXPRESSION)
0128 
0129     def invoke(self, arg, from_tty):
0130         argv = gdb.string_to_argv(arg)
0131         if len(argv) != 1:
0132             raise gdb.GdbError("lx-list-check takes one argument")
0133         list_check(gdb.parse_and_eval(argv[0]))
0134 
0135 
0136 LxListChk()