diff mbox

[4/4] scripts/qemugdb: backtraces for coroutines in coredump

Message ID 20180328173238.507470-5-vsementsov@virtuozzo.com (mailing list archive)
State New, archived
Headers show

Commit Message

Vladimir Sementsov-Ogievskiy March 28, 2018, 5:32 p.m. UTC
We can't get coroutine backtrace through obvious way
 - set regs
 - bt
 - restore regs
when debugging a coredump.
So, let's go hard way: clone current coredump file, patch regs
in it and execute a subprocess gdb to get backtrace from this
patched coredump.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
 scripts/qemugdb/coroutine.py | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

Comments

Stefan Hajnoczi April 4, 2018, 10:36 a.m. UTC | #1
On Wed, Mar 28, 2018 at 08:32:38PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> We can't get coroutine backtrace through obvious way
>  - set regs
>  - bt
>  - restore regs
> when debugging a coredump.
> So, let's go hard way: clone current coredump file, patch regs
> in it and execute a subprocess gdb to get backtrace from this
> patched coredump.

I have CCed you on a patch that uses 'select-frame' to temporarily
switch stacks.  This works in a coredump and does not require
cloning/patching the coredump file.

Please let me know if 'select-frame' works for you, it would be
preferrable to cloning/patching the coredump file.

Stefan
diff mbox

Patch

diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index 7070a592f3..2a05851e24 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -15,9 +15,32 @@ 
 
 import gdb
 import re
+import tempfile
+import subprocess
+import os
+import coredump
 
 VOID_PTR = gdb.lookup_type('void').pointer()
 
+def bt_regs_static(regs):
+    files = gdb.execute('info files', False, True).split('\n')
+    executable = re.match('^Symbols from "(.*)".$', files[0]).group(1)
+    dump = re.search("`(.*)'", files[2]).group(1)
+
+    with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as f:
+        temp = f.name
+
+    coredump.clone_coredump(dump, temp, regs)
+
+    cmd = ['gdb', '-batch', '-ex', "python print '----split----'",
+           '-ex', 'bt', executable, temp]
+    out = subprocess.check_output(cmd)
+    out = out.split('----split----')[1]
+
+    os.remove(temp)
+
+    print out
+
 def get_fs_base():
     '''Fetch %fs base value using arch_prctl(ARCH_GET_FS).  This is
        pthread_self().'''
@@ -122,8 +145,7 @@  class CoroutineCommand(gdb.Command):
         try:
             bt_regs(regs)
         except gdb.error:
-            print "Coroutine backtrace can't be obtained without " \
-                  "a process to debug."
+            bt_regs_static(regs)
 
 class CoroutineSPFunction(gdb.Function):
     def __init__(self):