Commit b05b363df4 for qemu.org

commit b05b363df43e4fe6fb9f349f4883e875facd609a
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Date:   Tue Aug 4 18:17:41 2026 +0300

    scripts/qemugdb: coroutine: Handle target absence gracefully

    init_coredump() picks the core dump and the executable out of fixed lines
    of 'info files' output.  With no target loaded that output is empty, and
    'qemu bt' dies with:

        IndexError: list index out of range

    Search the whole output for the core dump file instead, and take the
    executable from gdb.current_progspace(), which doesn't need parsing at
    all.  Neither can raise if the pattern isn't there, so an unexpected
    output format now just means "not a coredump" rather than a traceback.

    That alone only moves the problem to gdb.execute("bt"), whose gdb.error
    escapes invoke() and still gets reported as a python traceback.  At the
    same time plain 'bt' just prints 'No stack.'.  Let's mimick this
    behaviour and simply report an error if there's no selected thread.

    Fixes: 42f3c143c3a0 ("scripts/qemugdb: coroutine: Add option for obtaining detailed trace in coredump")
    Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
    Message-ID: <20260804151743.937694-8-andrey.drobyshev@virtuozzo.com>
    Tested-by: Fabiano Rosas <farosas@suse.de>
    Reviewed-by: Kevin Wolf <kwolf@redhat.com>
    Signed-off-by: Kevin Wolf <kwolf@redhat.com>

diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index 9148264de3..3e0b37b73e 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -322,16 +322,14 @@ def coroutine_to_jmpbuf(co):
 def init_coredump():
     global coredump

-    files = gdb.execute('info files', False, True).split('\n')
+    files = gdb.execute('info files', False, True)

-    if not 'core dump' in files[1]:
+    match = re.search(r"core dump file:\s*`([^']+)'", files)
+    if match is None:
         return False

-    core_path = re.search("`(.*)'", files[2]).group(1)
-    exec_path = re.match('^Symbols from "(.*)".$', files[0]).group(1)
-
     if coredump is None:
-        coredump = Coredump(core_path, exec_path)
+        coredump = Coredump(match.group(1), gdb.current_progspace().filename)

     return True

@@ -362,6 +360,9 @@ def invoke(self, arg, from_tty):
             return self._usage()
         detailed = True if argc == 2 else False

+        if gdb.selected_thread() is None:
+            raise gdb.GdbError('No stack.')
+
         is_coredump = init_coredump()
         if detailed and not is_coredump:
             gdb.write('--detailed is only valid when debugging core dumps\n')
@@ -400,6 +401,9 @@ def invoke(self, arg, from_tty):
             return self._usage()
         detailed = True if argc == 1 else False

+        if gdb.selected_thread() is None:
+            raise gdb.GdbError('No stack.')
+
         is_coredump = init_coredump()
         if detailed and not is_coredump:
             gdb.write('--detailed is only valid when debugging core dumps\n')