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 <[email protected]> 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_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 77class 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 89LxListChk() 90