1# 2# GDB debugging support: aio/iohandler debug 3# 4# Copyright (c) 2015 Red Hat, Inc. 5# 6# Author: Dr. David Alan Gilbert <dgilbert@redhat.com> 7# 8# This work is licensed under the terms of the GNU GPL, version 2 or 9# later. See the COPYING file in the top-level directory. 10# 11 12import gdb 13from qemugdb import coroutine 14 15def isnull(ptr): 16 return ptr == gdb.Value(0).cast(ptr.type) 17 18def dump_aiocontext(context, verbose): 19 '''Display a dump and backtrace for an aiocontext''' 20 cur = context['aio_handlers']['lh_first'] 21 # Get pointers to functions we're going to process specially 22 sym_fd_coroutine_enter = gdb.parse_and_eval('fd_coroutine_enter') 23 24 while not isnull(cur): 25 entry = cur.dereference() 26 gdb.write('----\n%s\n' % entry) 27 if verbose and cur['io_read'] == sym_fd_coroutine_enter: 28 coptr = (cur['opaque'].cast(gdb.lookup_type('FDYieldUntilData').pointer()))['co'] 29 coptr = coptr.cast(gdb.lookup_type('CoroutineUContext').pointer()) 30 coroutine.bt_jmpbuf(coptr['env']['__jmpbuf']) 31 cur = cur['node']['le_next']; 32 33 gdb.write('----\n') 34 35class HandlersCommand(gdb.Command): 36 '''Display aio handlers''' 37 def __init__(self): 38 gdb.Command.__init__(self, 'qemu handlers', gdb.COMMAND_DATA, 39 gdb.COMPLETE_NONE) 40 41 def invoke(self, arg, from_tty): 42 verbose = False 43 argv = gdb.string_to_argv(arg) 44 45 if len(argv) > 0 and argv[0] == '--verbose': 46 verbose = True 47 argv.pop(0) 48 49 if len(argv) > 1: 50 gdb.write('usage: qemu handlers [--verbose] [handler]\n') 51 return 52 53 if len(argv) == 1: 54 handlers_name = argv[0] 55 else: 56 handlers_name = 'qemu_aio_context' 57 dump_aiocontext(gdb.parse_and_eval(handlers_name), verbose) 58