Linux Audio

Check our new training course

Loading...
v4.17
  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")
 19
 20
 21def list_for_each(head):
 22    if head.type == list_head.get_type().pointer():
 23        head = head.dereference()
 24    elif head.type != list_head.get_type():
 25        raise gdb.GdbError("Must be struct list_head not {}"
 26                           .format(head.type))
 27
 28    node = head['next'].dereference()
 29    while node.address != head.address:
 30        yield node.address
 31        node = node['next'].dereference()
 32
 33
 34def list_for_each_entry(head, gdbtype, member):
 35    for node in list_for_each(head):
 36        if node.type != list_head.get_type().pointer():
 37            raise TypeError("Type {} found. Expected struct list_head *."
 38                            .format(node.type))
 39        yield utils.container_of(node, gdbtype, member)
 40
 41
 42def list_check(head):
 43    nb = 0
 44    if (head.type == list_head.get_type().pointer()):
 45        head = head.dereference()
 46    elif (head.type != list_head.get_type()):
 47        raise gdb.GdbError('argument must be of type (struct list_head [*])')
 48    c = head
 49    try:
 50        gdb.write("Starting with: {}\n".format(c))
 51    except gdb.MemoryError:
 52        gdb.write('head is not accessible\n')
 53        return
 54    while True:
 55        p = c['prev'].dereference()
 56        n = c['next'].dereference()
 57        try:
 58            if p['next'] != c.address:
 59                gdb.write('prev.next != current: '
 60                          'current@{current_addr}={current} '
 61                          'prev@{p_addr}={p}\n'.format(
 62                              current_addr=c.address,
 63                              current=c,
 64                              p_addr=p.address,
 65                              p=p,
 66                          ))
 67                return
 68        except gdb.MemoryError:
 69            gdb.write('prev is not accessible: '
 70                      'current@{current_addr}={current}\n'.format(
 71                          current_addr=c.address,
 72                          current=c
 73                      ))
 74            return
 75        try:
 76            if n['prev'] != c.address:
 77                gdb.write('next.prev != current: '
 78                          'current@{current_addr}={current} '
 79                          'next@{n_addr}={n}\n'.format(
 80                              current_addr=c.address,
 81                              current=c,
 82                              n_addr=n.address,
 83                              n=n,
 84                          ))
 85                return
 86        except gdb.MemoryError:
 87            gdb.write('next is not accessible: '
 88                      'current@{current_addr}={current}\n'.format(
 89                          current_addr=c.address,
 90                          current=c
 91                      ))
 92            return
 93        c = n
 94        nb += 1
 95        if c == head:
 96            gdb.write("list is consistent: {} node(s)\n".format(nb))
 97            return
 98
 99
100class LxListChk(gdb.Command):
101    """Verify a list consistency"""
102
103    def __init__(self):
104        super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
105                                        gdb.COMPLETE_EXPRESSION)
106
107    def invoke(self, arg, from_tty):
108        argv = gdb.string_to_argv(arg)
109        if len(argv) != 1:
110            raise gdb.GdbError("lx-list-check takes one argument")
111        list_check(gdb.parse_and_eval(argv[0]))
112
113LxListChk()
v4.10.11
  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")
 19
 20
 21def list_for_each(head):
 22    if head.type == list_head.get_type().pointer():
 23        head = head.dereference()
 24    elif head.type != list_head.get_type():
 25        raise gdb.GdbError("Must be struct list_head not {}"
 26                           .format(head.type))
 27
 28    node = head['next'].dereference()
 29    while node.address != head.address:
 30        yield node.address
 31        node = node['next'].dereference()
 32
 33
 34def list_for_each_entry(head, gdbtype, member):
 35    for node in list_for_each(head):
 36        if node.type != list_head.get_type().pointer():
 37            raise TypeError("Type {} found. Expected struct list_head *."
 38                            .format(node.type))
 39        yield utils.container_of(node, gdbtype, member)
 40
 41
 42def list_check(head):
 43    nb = 0
 44    if (head.type == list_head.get_type().pointer()):
 45        head = head.dereference()
 46    elif (head.type != list_head.get_type()):
 47        raise gdb.GdbError('argument must be of type (struct list_head [*])')
 48    c = head
 49    try:
 50        gdb.write("Starting with: {}\n".format(c))
 51    except gdb.MemoryError:
 52        gdb.write('head is not accessible\n')
 53        return
 54    while True:
 55        p = c['prev'].dereference()
 56        n = c['next'].dereference()
 57        try:
 58            if p['next'] != c.address:
 59                gdb.write('prev.next != current: '
 60                          'current@{current_addr}={current} '
 61                          'prev@{p_addr}={p}\n'.format(
 62                              current_addr=c.address,
 63                              current=c,
 64                              p_addr=p.address,
 65                              p=p,
 66                          ))
 67                return
 68        except gdb.MemoryError:
 69            gdb.write('prev is not accessible: '
 70                      'current@{current_addr}={current}\n'.format(
 71                          current_addr=c.address,
 72                          current=c
 73                      ))
 74            return
 75        try:
 76            if n['prev'] != c.address:
 77                gdb.write('next.prev != current: '
 78                          'current@{current_addr}={current} '
 79                          'next@{n_addr}={n}\n'.format(
 80                              current_addr=c.address,
 81                              current=c,
 82                              n_addr=n.address,
 83                              n=n,
 84                          ))
 85                return
 86        except gdb.MemoryError:
 87            gdb.write('next is not accessible: '
 88                      'current@{current_addr}={current}\n'.format(
 89                          current_addr=c.address,
 90                          current=c
 91                      ))
 92            return
 93        c = n
 94        nb += 1
 95        if c == head:
 96            gdb.write("list is consistent: {} node(s)\n".format(nb))
 97            return
 98
 99
100class LxListChk(gdb.Command):
101    """Verify a list consistency"""
102
103    def __init__(self):
104        super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
105                                        gdb.COMPLETE_EXPRESSION)
106
107    def invoke(self, arg, from_tty):
108        argv = gdb.string_to_argv(arg)
109        if len(argv) != 1:
110            raise gdb.GdbError("lx-list-check takes one argument")
111        list_check(gdb.parse_and_eval(argv[0]))
112
113LxListChk()