summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qemu-gdb.py1
-rw-r--r--scripts/qemugdb/coroutine.py35
2 files changed, 35 insertions, 1 deletions
diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
index e0bfa7b5a4..4d2a9f6c43 100644
--- a/scripts/qemu-gdb.py
+++ b/scripts/qemu-gdb.py
@@ -40,6 +40,7 @@ timers.TimersCommand()
coroutine.CoroutineSPFunction()
coroutine.CoroutinePCFunction()
+coroutine.CoroutineBt()
# Default to silently passing through SIGUSR1, because QEMU sends it
# to itself a lot.
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index db61389022..7db46d4b68 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -70,6 +70,11 @@ def bt_jmpbuf(jmpbuf):
regs = get_jmpbuf_regs(jmpbuf)
old = dict()
+ # remember current stack frame and select the topmost
+ # so that register modifications don't wreck it
+ selected_frame = gdb.selected_frame()
+ gdb.newest_frame().select()
+
for i in regs:
old[i] = gdb.parse_and_eval('(uint64_t)$%s' % i)
@@ -81,8 +86,13 @@ def bt_jmpbuf(jmpbuf):
for i in regs:
gdb.execute('set $%s = %s' % (i, old[i]))
+ selected_frame.select()
+
+def co_cast(co):
+ return co.cast(gdb.lookup_type('CoroutineUContext').pointer())
+
def coroutine_to_jmpbuf(co):
- coroutine_pointer = co.cast(gdb.lookup_type('CoroutineUContext').pointer())
+ coroutine_pointer = co_cast(co)
return coroutine_pointer['env']['__jmpbuf']
@@ -100,6 +110,29 @@ class CoroutineCommand(gdb.Command):
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):
def __init__(self):
gdb.Function.__init__(self, 'qemu_coroutine_sp')