1084f6b1eSThiébaud Weksteen# 2084f6b1eSThiébaud Weksteen# gdb helper commands and functions for Linux kernel debugging 3084f6b1eSThiébaud Weksteen# 4084f6b1eSThiébaud Weksteen# list tools 5084f6b1eSThiébaud Weksteen# 6084f6b1eSThiébaud Weksteen# Copyright (c) Thiebaud Weksteen, 2015 7084f6b1eSThiébaud Weksteen# 8084f6b1eSThiébaud Weksteen# Authors: 9084f6b1eSThiébaud Weksteen# Thiebaud Weksteen <thiebaud@weksteen.fr> 10084f6b1eSThiébaud Weksteen# 11084f6b1eSThiébaud Weksteen# This work is licensed under the terms of the GNU GPL version 2. 12084f6b1eSThiébaud Weksteen# 13084f6b1eSThiébaud Weksteen 14084f6b1eSThiébaud Weksteenimport gdb 15084f6b1eSThiébaud Weksteen 16084f6b1eSThiébaud Weksteenfrom linux import utils 17084f6b1eSThiébaud Weksteen 18084f6b1eSThiébaud Weksteenlist_head = utils.CachedType("struct list_head") 1947d0d128SLeonard Crestezhlist_head = utils.CachedType("struct hlist_head") 2047d0d128SLeonard Crestezhlist_node = utils.CachedType("struct hlist_node") 21084f6b1eSThiébaud Weksteen 22084f6b1eSThiébaud Weksteen 23a84be61dSKieran Binghamdef list_for_each(head): 24a84be61dSKieran Bingham if head.type == list_head.get_type().pointer(): 25a84be61dSKieran Bingham head = head.dereference() 26a84be61dSKieran Bingham elif head.type != list_head.get_type(): 2766d5c7c6SLeonard Crestez raise TypeError("Must be struct list_head not {}" 28a84be61dSKieran Bingham .format(head.type)) 29a84be61dSKieran Bingham 30*db7fbf49SGeorge Prekas if head['next'] == 0: 31*db7fbf49SGeorge Prekas gdb.write("list_for_each: Uninitialized list '{}' treated as empty\n" 32*db7fbf49SGeorge Prekas .format(head.address)) 33*db7fbf49SGeorge Prekas return 34*db7fbf49SGeorge Prekas 35a84be61dSKieran Bingham node = head['next'].dereference() 36a84be61dSKieran Bingham while node.address != head.address: 37a84be61dSKieran Bingham yield node.address 38a84be61dSKieran Bingham node = node['next'].dereference() 39a84be61dSKieran Bingham 40a84be61dSKieran Bingham 41a84be61dSKieran Binghamdef list_for_each_entry(head, gdbtype, member): 42a84be61dSKieran Bingham for node in list_for_each(head): 43a84be61dSKieran Bingham yield utils.container_of(node, gdbtype, member) 44a84be61dSKieran Bingham 45a84be61dSKieran Bingham 4647d0d128SLeonard Crestezdef hlist_for_each(head): 4747d0d128SLeonard Crestez if head.type == hlist_head.get_type().pointer(): 4847d0d128SLeonard Crestez head = head.dereference() 4947d0d128SLeonard Crestez elif head.type != hlist_head.get_type(): 5066d5c7c6SLeonard Crestez raise TypeError("Must be struct hlist_head not {}" 5147d0d128SLeonard Crestez .format(head.type)) 5247d0d128SLeonard Crestez 5347d0d128SLeonard Crestez node = head['first'].dereference() 5447d0d128SLeonard Crestez while node.address: 5547d0d128SLeonard Crestez yield node.address 5647d0d128SLeonard Crestez node = node['next'].dereference() 5747d0d128SLeonard Crestez 5847d0d128SLeonard Crestez 5947d0d128SLeonard Crestezdef hlist_for_each_entry(head, gdbtype, member): 6047d0d128SLeonard Crestez for node in hlist_for_each(head): 6147d0d128SLeonard Crestez yield utils.container_of(node, gdbtype, member) 6247d0d128SLeonard Crestez 6347d0d128SLeonard Crestez 64084f6b1eSThiébaud Weksteendef list_check(head): 65084f6b1eSThiébaud Weksteen nb = 0 66433296b3SJan Kiszka if (head.type == list_head.get_type().pointer()): 67433296b3SJan Kiszka head = head.dereference() 68433296b3SJan Kiszka elif (head.type != list_head.get_type()): 69433296b3SJan Kiszka raise gdb.GdbError('argument must be of type (struct list_head [*])') 70084f6b1eSThiébaud Weksteen c = head 71084f6b1eSThiébaud Weksteen try: 72084f6b1eSThiébaud Weksteen gdb.write("Starting with: {}\n".format(c)) 73084f6b1eSThiébaud Weksteen except gdb.MemoryError: 74084f6b1eSThiébaud Weksteen gdb.write('head is not accessible\n') 75084f6b1eSThiébaud Weksteen return 76084f6b1eSThiébaud Weksteen while True: 77084f6b1eSThiébaud Weksteen p = c['prev'].dereference() 78084f6b1eSThiébaud Weksteen n = c['next'].dereference() 79084f6b1eSThiébaud Weksteen try: 80084f6b1eSThiébaud Weksteen if p['next'] != c.address: 81084f6b1eSThiébaud Weksteen gdb.write('prev.next != current: ' 82084f6b1eSThiébaud Weksteen 'current@{current_addr}={current} ' 83084f6b1eSThiébaud Weksteen 'prev@{p_addr}={p}\n'.format( 84084f6b1eSThiébaud Weksteen current_addr=c.address, 85084f6b1eSThiébaud Weksteen current=c, 86084f6b1eSThiébaud Weksteen p_addr=p.address, 87084f6b1eSThiébaud Weksteen p=p, 88084f6b1eSThiébaud Weksteen )) 89084f6b1eSThiébaud Weksteen return 90084f6b1eSThiébaud Weksteen except gdb.MemoryError: 91084f6b1eSThiébaud Weksteen gdb.write('prev is not accessible: ' 92084f6b1eSThiébaud Weksteen 'current@{current_addr}={current}\n'.format( 93084f6b1eSThiébaud Weksteen current_addr=c.address, 94084f6b1eSThiébaud Weksteen current=c 95084f6b1eSThiébaud Weksteen )) 96084f6b1eSThiébaud Weksteen return 97084f6b1eSThiébaud Weksteen try: 98084f6b1eSThiébaud Weksteen if n['prev'] != c.address: 99084f6b1eSThiébaud Weksteen gdb.write('next.prev != current: ' 100084f6b1eSThiébaud Weksteen 'current@{current_addr}={current} ' 101084f6b1eSThiébaud Weksteen 'next@{n_addr}={n}\n'.format( 102084f6b1eSThiébaud Weksteen current_addr=c.address, 103084f6b1eSThiébaud Weksteen current=c, 104084f6b1eSThiébaud Weksteen n_addr=n.address, 105084f6b1eSThiébaud Weksteen n=n, 106084f6b1eSThiébaud Weksteen )) 107084f6b1eSThiébaud Weksteen return 108084f6b1eSThiébaud Weksteen except gdb.MemoryError: 109084f6b1eSThiébaud Weksteen gdb.write('next is not accessible: ' 110084f6b1eSThiébaud Weksteen 'current@{current_addr}={current}\n'.format( 111084f6b1eSThiébaud Weksteen current_addr=c.address, 112084f6b1eSThiébaud Weksteen current=c 113084f6b1eSThiébaud Weksteen )) 114084f6b1eSThiébaud Weksteen return 115084f6b1eSThiébaud Weksteen c = n 116084f6b1eSThiébaud Weksteen nb += 1 117084f6b1eSThiébaud Weksteen if c == head: 118084f6b1eSThiébaud Weksteen gdb.write("list is consistent: {} node(s)\n".format(nb)) 119084f6b1eSThiébaud Weksteen return 120084f6b1eSThiébaud Weksteen 121084f6b1eSThiébaud Weksteen 122084f6b1eSThiébaud Weksteenclass LxListChk(gdb.Command): 123084f6b1eSThiébaud Weksteen """Verify a list consistency""" 124084f6b1eSThiébaud Weksteen 125084f6b1eSThiébaud Weksteen def __init__(self): 1263328bc9eSJan Kiszka super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA, 1273328bc9eSJan Kiszka gdb.COMPLETE_EXPRESSION) 128084f6b1eSThiébaud Weksteen 129084f6b1eSThiébaud Weksteen def invoke(self, arg, from_tty): 130084f6b1eSThiébaud Weksteen argv = gdb.string_to_argv(arg) 131084f6b1eSThiébaud Weksteen if len(argv) != 1: 132084f6b1eSThiébaud Weksteen raise gdb.GdbError("lx-list-check takes one argument") 133084f6b1eSThiébaud Weksteen list_check(gdb.parse_and_eval(argv[0])) 134084f6b1eSThiébaud Weksteen 135494dbe02SStephen Boyd 136084f6b1eSThiébaud WeksteenLxListChk() 137