scripts/gdb: implement 'qemu bt'
This script first runs the regular gdb's 'bt' command, and then if we are in a coroutine it prints the coroutines backtraces in the order in which they were called. Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Message-Id: <20201217155436.927320-3-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
4cbf8efc5b
commit
b9a0de3773
@ -40,6 +40,7 @@ timers.TimersCommand()
|
|||||||
|
|
||||||
coroutine.CoroutineSPFunction()
|
coroutine.CoroutineSPFunction()
|
||||||
coroutine.CoroutinePCFunction()
|
coroutine.CoroutinePCFunction()
|
||||||
|
coroutine.CoroutineBt()
|
||||||
|
|
||||||
# Default to silently passing through SIGUSR1, because QEMU sends it
|
# Default to silently passing through SIGUSR1, because QEMU sends it
|
||||||
# to itself a lot.
|
# to itself a lot.
|
||||||
|
@ -88,8 +88,11 @@ def bt_jmpbuf(jmpbuf):
|
|||||||
|
|
||||||
selected_frame.select()
|
selected_frame.select()
|
||||||
|
|
||||||
|
def co_cast(co):
|
||||||
|
return co.cast(gdb.lookup_type('CoroutineUContext').pointer())
|
||||||
|
|
||||||
def coroutine_to_jmpbuf(co):
|
def coroutine_to_jmpbuf(co):
|
||||||
coroutine_pointer = co.cast(gdb.lookup_type('CoroutineUContext').pointer())
|
coroutine_pointer = co_cast(co)
|
||||||
return coroutine_pointer['env']['__jmpbuf']
|
return coroutine_pointer['env']['__jmpbuf']
|
||||||
|
|
||||||
|
|
||||||
@ -107,6 +110,29 @@ class CoroutineCommand(gdb.Command):
|
|||||||
|
|
||||||
bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0])))
|
bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0])))
|
||||||
|
|
||||||
|
class CoroutineBt(gdb.Command):
|
||||||
|
'''Display backtrace including coroutine switches'''
|
||||||
|
def __init__(self):
|
||||||
|
gdb.Command.__init__(self, 'qemu bt', gdb.COMMAND_STACK,
|
||||||
|
gdb.COMPLETE_NONE)
|
||||||
|
|
||||||
|
def invoke(self, arg, from_tty):
|
||||||
|
|
||||||
|
gdb.execute("bt")
|
||||||
|
|
||||||
|
if gdb.parse_and_eval("qemu_in_coroutine()") == False:
|
||||||
|
return
|
||||||
|
|
||||||
|
co_ptr = gdb.parse_and_eval("qemu_coroutine_self()")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
co = co_cast(co_ptr)
|
||||||
|
co_ptr = co["base"]["caller"]
|
||||||
|
if co_ptr == 0:
|
||||||
|
break
|
||||||
|
gdb.write("Coroutine at " + str(co_ptr) + ":\n")
|
||||||
|
bt_jmpbuf(coroutine_to_jmpbuf(co_ptr))
|
||||||
|
|
||||||
class CoroutineSPFunction(gdb.Function):
|
class CoroutineSPFunction(gdb.Function):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
gdb.Function.__init__(self, 'qemu_coroutine_sp')
|
gdb.Function.__init__(self, 'qemu_coroutine_sp')
|
||||||
|
Loading…
Reference in New Issue
Block a user