diff --git a/meta/lib/oeqa/selftest/cases/gdbserver.py b/meta/lib/oeqa/selftest/cases/gdbserver.py
index 3124902543c..3621d9c13eb 100644
--- a/meta/lib/oeqa/selftest/cases/gdbserver.py
+++ b/meta/lib/oeqa/selftest/cases/gdbserver.py
@@ -4,122 +4,63 @@
 # SPDX-License-Identifier: MIT
 #
 import os
-from subprocess import Popen, PIPE
-import threading
 import time
+import tempfile
+import shutil
+import concurrent.futures
 
 from oeqa.selftest.case import OESelftestTestCase
-from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars, runqemu , runCmd
-from oeqa.core.exception import OEQATimeoutError
-
-
-#The test runs gdbserver on qemu and connects the gdb client from host over TCP.
-#
-#It builds a cross gdb on the host and compiles the program to be debugged on the target,
-#launches the gdbserver and tries to connect cross gdb to it.
-
-
-class GdbTest(OESelftestTestCase):
-
-    def run_gdb(self, native_sysroot=None, **options):
-        # Add path to cross gdb to environment.
-        extra_paths = "%s/usr/bin/%s" % (self.recipe_sysroot_native, self.target_sys)
-        nenv = dict(options.get('env', os.environ))
-        nenv['PATH'] = extra_paths + ':' + nenv.get('PATH', '')
-        options['env'] = nenv
-
-        for count in range(5):
-            # Let the gdb server start before by putting client thread to sleep.
-            # Still, if gdb client happens to start before gdbserver, if will
-            # return "gdb connection timed out". In that case try
-            # connecting again
-            time.sleep(1)
-            cmd = "%s-gdb -ex 'set sysroot %s' -ex \"target remote %s:%s\" -ex continue -ex quit %s" \
-                       %(self.target_sys, self.recipe_sysroot_native, self.qemu_ip, self.gdbserver_port, self.binary)
-            r = runCmd(cmd, native_sysroot=self.recipe_sysroot_native, **options)
-            if "Connection timed out" not in r.output:
-                break
-            if count == 4:
-                self.assertTrue(False, "gdb unable to connect to gdbserver")
-
-    def run_gdb_client(self):
-        self.run_gdb(native_sysroot=self.recipe_sysroot_native, ignore_status=False)
+from oeqa.utils.commands import bitbake, get_bb_var, runqemu, runCmd
 
+class GdbServerTest(OESelftestTestCase):
     def test_gdb_server(self):
-        self.target_dst = "/tmp/"
-        self.source  = "test.c"
-        self.binary  = "test"
-        self.target_source = self.target_dst + self.source
-        self.target_binary = self.target_dst + self.binary
-        self.gdbserver_port = 2001
-
-        try:
-            # These aren't the actual IP addresses but testexport class needs something defined
-            features  = 'TEST_SERVER_IP = "192.168.7.1"\n'
-            features += 'TEST_TARGET_IP = "192.168.7.2"\n'
-            features += 'EXTRA_IMAGE_FEATURES += "ssh-server-openssh"\n'
-            features += 'CORE_IMAGE_EXTRA_INSTALL += "gdbserver packagegroup-core-buildessential"\n'
-            self.write_config(features)
-
-            self.target_arch = get_bb_var('TARGET_ARCH')
-            self.target_sys  = get_bb_var('TARGET_SYS')
-
-            recipe = "gdb-cross-%s" %self.target_arch
-            gdb_cross_bitbake_command = "%s -c addto_recipe_sysroot" %recipe
-
-            bitbake(gdb_cross_bitbake_command)
-
-            self.recipe_sysroot_native = get_bb_var('RECIPE_SYSROOT_NATIVE', recipe)
-
-            bitbake('core-image-minimal')
-
-            self.cross_gdb_name = "%s-gdb" %self.target_sys
-
-            # wrap the execution with a qemu instance
-            with runqemu("core-image-minimal", runqemuparams = "nographic") as qemu:
-                status, target_gcc = qemu.run_serial("which gcc")
-
-                self.assertNotEqual(target_gcc, None, 'gcc not found on the target')
-
-                self.qemu_ip = qemu.ip
-
-                # self.tc.files_dir = meta/lib/oeqa/files
-                src = os.path.join(self.tc.files_dir, 'test.c')
-
-                self.logger.debug("src : %s qemu.ip : %s self.target_dst : %s" % (src , self.qemu_ip , self.target_dst))
-                cmd = "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR %s root@%s:%s"  % (src, qemu.ip, self.target_dst)
-                result = runCmd(cmd)
-
-                cmd = "cat %s" %(self.target_source)
-                status, output = qemu.run_serial(cmd)
-                self.assertIn("1234", output, "Source file copied to target is different that what is expected")
-
-                cmd = "%s %s -o %s -lm -g" % (target_gcc, self.target_source, self.target_binary)
-                status, output = qemu.run_serial(cmd)
-
-                cmd = "ls %s" %self.target_binary
-                status, output = qemu.run_serial(cmd)
-                self.assertNotIn("No such file or directory", output, "Test file compilation failed on target")
-
-                status, output = qemu.run_serial(self.target_binary)
-                self.assertIn("1234", output, "Test binary is different than what is expected")
-
-                cmd = "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR root@%s:%s %s"  % (qemu.ip, self.target_binary, os.getcwd())
-                result = runCmd(cmd)
-
-                cmd = "strip -s --strip-debug %s" %self.target_binary
-                status, output = qemu.run_serial(cmd)
-
-                gdb_client_thread = threading.Thread(target=self.run_gdb_client)
-                gdb_client_thread.start()
-
-                cmd = "gdbserver localhost:%s %s" %(self.gdbserver_port, self.target_binary)
-                status, output = qemu.run_serial(cmd)
-                self.logger.debug("gdbserver status : %s output : %s" % (status, output))
-
-                gdb_client_thread.join()
-                self.assertIn("1234", output, "Expected string (1234) not present in test output")
-
-        except OEQATimeoutError:
-            self.fail("gdbserver test timeout error")
-
+        target_arch = self.td["TARGET_ARCH"]
+        target_sys = self.td["TARGET_SYS"]
+        deploy_dir = get_bb_var("DEPLOY_DIR_IMAGE")
+
+        features = """
+IMAGE_GEN_DEBUGFS = "1"
+IMAGE_FSTYPES_DEBUGFS = "tar.bz2"
+CORE_IMAGE_EXTRA_INSTALL = "gdbserver"
+        """
+        self.write_config(features)
+
+        gdb_recipe = "gdb-cross-" + target_arch
+        gdb_binary = target_sys + "-gdb"
+
+        bitbake("core-image-minimal %s:do_addto_recipe_sysroot" % gdb_recipe)
+
+        native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", gdb_recipe)
+        r = runCmd("%s --version" % gdb_binary, native_sysroot=native_sysroot, target_sys=target_sys)
+        self.assertEqual(r.status, 0)
+        self.assertIn("GNU gdb", r.output)
+
+        with tempfile.TemporaryDirectory(prefix="debugfs-") as debugfs:
+            filename = os.path.join(deploy_dir, "core-image-minimal-%s-dbg.tar.bz2" % self.td["MACHINE"])
+            shutil.unpack_archive(filename, debugfs)
+            filename = os.path.join(deploy_dir, "core-image-minimal-%s.tar.bz2" % self.td["MACHINE"])
+            shutil.unpack_archive(filename, debugfs)
+
+            with runqemu("core-image-minimal", runqemuparams="nographic") as qemu:
+                status, output = qemu.run_serial("kmod --help")
+                self.assertIn("modprobe", output)
+
+                with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
+                    def run_gdb():
+                        for _ in range(5):
+                            time.sleep(2)
+                            cmd = "%s --batch -ex 'set sysroot %s' -ex \"target extended-remote %s:9999\" -ex \"info line kmod_help\"" % (gdb_binary, debugfs, qemu.ip)
+                            self.logger.warning("starting gdb %s" % cmd)
+                            r = runCmd(cmd, native_sysroot=native_sysroot, target_sys=target_sys)
+                            self.assertEqual(0, r.status)
+                            line_re = r"Line \d+ of \"/usr/src/debug/kmod/.*/tools/kmod.c\" starts at address 0x[0-9A-Fa-f]+ <kmod_help>"
+                            self.assertRegex(r.output, line_re)
+                            break
+                        else:
+                            self.fail("Timed out connecting to gdb")
+                    future = executor.submit(run_gdb)
+
+                    status, output = qemu.run_serial("gdbserver --once :9999 kmod --help")
+                    self.assertEqual(status, 1)
+                    # The future either returns None, or raises an exception
+                    future.result()
