qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Quality of life patches for qemu coroutine debugging
@ 2020-12-17 15:38 Maxim Levitsky
  2020-12-17 15:38 ` [PATCH 1/2] scripts/gdb: fix 'qemu coroutine' when users selects a non topmost stack frame Maxim Levitsky
  2020-12-17 15:38 ` [PATCH 2/2] scripts/gdb: implement 'qemu bt' Maxim Levitsky
  0 siblings, 2 replies; 3+ messages in thread
From: Maxim Levitsky @ 2020-12-17 15:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Paolo Bonzini, Maxim Levitsky, Eduardo Habkost, Cleber Rosa

These are two patches that improve a bit the qemu gdb scripts in regard to
coroutines.

First patch fixes a bug in 'qemu coroutine' in regard to usage on non topmost
stack frame.

Second patch implements 'qemu bt' as Stefan suggested.

Best regards,
        Maxim Levitsky

Maxim Levitsky (2):
  scripts/gdb: fix 'qemu coroutine' when users selects a non topmost
    stack frame
  scripts/gdb: implement 'qemu bt'

 scripts/qemu-gdb.py          |  1 +
 scripts/qemugdb/coroutine.py | 39 +++++++++++++++++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

-- 
2.26.2




^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] scripts/gdb: fix 'qemu coroutine' when users selects a non topmost stack frame
  2020-12-17 15:38 [PATCH 0/2] Quality of life patches for qemu coroutine debugging Maxim Levitsky
@ 2020-12-17 15:38 ` Maxim Levitsky
  2020-12-17 15:38 ` [PATCH 2/2] scripts/gdb: implement 'qemu bt' Maxim Levitsky
  1 sibling, 0 replies; 3+ messages in thread
From: Maxim Levitsky @ 2020-12-17 15:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Paolo Bonzini, Maxim Levitsky, Eduardo Habkost, Cleber Rosa

The code that dumps the stack frame works like that:
* save current registers
* overwrite current registers (including rip/rsp) with coroutine snapshot
  in the jmpbuf
* print backtrace
* restore the saved registers.

If the user has currently selected a non topmost stack frame in gdb,
the above code will still restore the selected frame registers,
but the gdb will then lose the selected frame index, which makes it impossible
to switch back to frame 0, to continue debugging the executable.

Therefore switch temporarily to the topmost frame of the stack
for the above code.

Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 scripts/qemugdb/coroutine.py | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index db61389022..e1399211e6 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,6 +86,8 @@ def bt_jmpbuf(jmpbuf):
     for i in regs:
         gdb.execute('set $%s = %s' % (i, old[i]))
 
+    selected_frame.select()
+
 def coroutine_to_jmpbuf(co):
     coroutine_pointer = co.cast(gdb.lookup_type('CoroutineUContext').pointer())
     return coroutine_pointer['env']['__jmpbuf']
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] scripts/gdb: implement 'qemu bt'
  2020-12-17 15:38 [PATCH 0/2] Quality of life patches for qemu coroutine debugging Maxim Levitsky
  2020-12-17 15:38 ` [PATCH 1/2] scripts/gdb: fix 'qemu coroutine' when users selects a non topmost stack frame Maxim Levitsky
@ 2020-12-17 15:38 ` Maxim Levitsky
  1 sibling, 0 replies; 3+ messages in thread
From: Maxim Levitsky @ 2020-12-17 15:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: Fam Zheng, Paolo Bonzini, Maxim Levitsky, Eduardo Habkost, Cleber Rosa

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>
---
 scripts/qemu-gdb.py          |  1 +
 scripts/qemugdb/coroutine.py | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 1 deletion(-)

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 e1399211e6..39d53a102e 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -88,8 +88,11 @@ def bt_jmpbuf(jmpbuf):
 
     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']
 
 
@@ -107,6 +110,33 @@ 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")
+
+        thread = gdb.selected_thread()
+        if thread == None or not thread.is_stopped():
+            raise gdb.GdbError("No currrent thread")
+
+        if gdb.parse_and_eval("qemu_in_coroutine()") == False:
+            return
+
+        co_ptr = gdb.parse_and_eval("qemu_coroutine_self()")
+        gdb.write("Coroutine at " + str(co_ptr) + ":\n")
+
+        while True:
+            co = co_cast(co_ptr)
+            co_ptr = co["base"]["caller"]
+            if co_ptr == 0:
+                break
+            bt_jmpbuf(coroutine_to_jmpbuf(co_ptr))
+
 class CoroutineSPFunction(gdb.Function):
     def __init__(self):
         gdb.Function.__init__(self, 'qemu_coroutine_sp')
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-12-17 15:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-17 15:38 [PATCH 0/2] Quality of life patches for qemu coroutine debugging Maxim Levitsky
2020-12-17 15:38 ` [PATCH 1/2] scripts/gdb: fix 'qemu coroutine' when users selects a non topmost stack frame Maxim Levitsky
2020-12-17 15:38 ` [PATCH 2/2] scripts/gdb: implement 'qemu bt' Maxim Levitsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).