diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 114536fc16..87dc8a1ee5 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4472,6 +4472,133 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
             if task['label'].startswith('install && deploy-target '))
         self.assertEqual(install_task['dependsOn'], [build_task['label']])
 
+    @OETestTag("runqemu")
+    def test_code_cargo_qemu_slirp(self):
+        recipe_name = 'cargo-example'
+        testimage = 'oe-selftest-image'
+        self._check_workspace()
+        self._write_bb_config()
+        tempdir = self._devtool_ide_sdk_recipe(
+            recipe_name, 'Cargo.toml', testimage)
+        port_start = self._reserve_slirp_port_block()
+        port_opts = ' -G %d' % port_start
+        runCmd(
+            'devtool ide-sdk %s %s --ide=code --target root@localhost '
+            '--port 2222 --no-host-check%s' % (
+                recipe_name, testimage, port_opts),
+            output_log=self._cmd_logger)
+        source_remap = '--remap-path-prefix=%s=%s' % (
+            os.path.realpath(tempdir),
+            get_bb_var('TARGET_DBGSRC_DIR', recipe_name))
+        rustflags = shlex.split(get_bb_var('RUSTFLAGS', recipe_name))
+        self.assertIn(
+            source_remap, rustflags,
+            'Cargo BitBake builds must remap the external source tree for DWARF')
+        self._verify_slirp_bbappend(testimage)
+
+        with runqemu(
+                testimage, runqemuparams='nographic slirp snapshot') as qemu:
+            self.assertIsNotNone(qemu.port, 'No SSH port for the slirp target')
+            runCmd(
+                'devtool ide-sdk %s %s %s --skip-bitbake --ide=code%s' % (
+                    recipe_name, testimage,
+                    '-t root@%s -P %s --no-host-check' % (qemu.ip, qemu.port),
+                    port_opts),
+                output_log=self._cmd_logger)
+            rustflags = shlex.split(get_bb_var('RUSTFLAGS', recipe_name))
+            self.assertIn(
+                source_remap, rustflags,
+                'Repeated ide-sdk runs must preserve the Cargo source remap')
+            self._verify_rust_lldb_debugging(tempdir, expected_input=4)
+
+    def _verify_rust_lldb_debugging(self, tempdir, expected_input):
+        with open(os.path.join(tempdir, '.vscode', 'launch.json')) as launch_file:
+            launch = json.load(launch_file)['configurations'][0]
+        with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_file:
+            tasks = json.load(tasks_file)['tasks']
+
+        self.assertEqual(launch['type'], 'lldb')
+        target_dbgsrc_dir = get_bb_var('TARGET_DBGSRC_DIR', 'cargo-example')
+        self.assertEqual(
+            launch['sourceMap'][target_dbgsrc_dir], os.path.realpath(tempdir))
+        self._run_vscode_task_with_dependencies(
+            tempdir, launch['preLaunchTask'], run_main_task=False)
+        server_task = next(
+            task for task in tasks if task['label'] == launch['preLaunchTask'])
+        self.assertEqual(server_task['command'], 'ssh')
+        ssh_args = [server_task['command']] + server_task['args']
+        if ssh_args[-1].startswith('"') and ssh_args[-1].endswith('"'):
+            ssh_args[-1] = ssh_args[-1][1:-1].replace('\\$', '$')
+        runCmd(ssh_args, output_log=self._cmd_logger)
+
+        source_line = self._find_source_break_line(
+            tempdir, 'src/main.rs', '    match n {')
+        println_line = self._find_source_break_line(
+            tempdir, 'src/main.rs', 'println!')
+        lldb_batch = [
+            os.path.join(
+                get_bb_var('RECIPE_SYSROOT_NATIVE', 'lldb-native'),
+                'usr', 'bin', 'lldb'),
+            '--batch',
+        ]
+        for command in launch['initCommands'] + launch['targetCreateCommands']:
+            lldb_batch += ['-o', command]
+        source_map_args = []
+        for source, destination in launch.get('sourceMap', {}).items():
+            source_map_args += [source, destination]
+        if source_map_args:
+            lldb_batch += [
+                '-o', 'settings set target.source-map %s' %
+                ' '.join(source_map_args)]
+        lldb_batch += [
+            '-o', 'breakpoint set --file main.rs --line %d' % source_line,
+            '-o', 'breakpoint set --file main.rs --line %d' % println_line,
+            '-o', 'breakpoint disable 2',
+            '-o', 'breakpoint list',
+            '-o', 'run',
+            '-o', 'frame variable n',
+            '-o', 'thread backtrace',
+            '-o', 'breakpoint disable 1',
+            '-o', 'breakpoint enable 2',
+            '-o', 'continue',
+            '-o', 'frame info',
+            '-o', 'frame select 1',
+            '-o', 'frame info',
+            '-o', 'frame select 3',
+            '-o', "image lookup -v -r -n 'std::rt::lang_start.*'",
+            '-o', 'thread backtrace',
+            '-o', 'exit',
+        ]
+        result = runCmd(lldb_batch, timeout=60, output_log=self._cmd_logger)
+        self.assertNotIn('(pending)', result.output)
+        self.assertIn('cargo_example::fibonacci', result.output)
+        self.assertIn('cargo_example::main', result.output)
+        self.assertIn('std::rt::lang_start', result.output)
+        self.assertIn('__libc_start', result.output)
+        self.assertRegex(result.output, r'n\s*=\s*%d' % expected_input)
+        libstd_rustsrc = get_bb_var('RUSTSRC', 'libstd-rs')
+        libstd_work_shared = os.path.join(
+            get_bb_var('TMPDIR', 'libstd-rs'), 'work-shared')
+        rust_std_target_root = os.path.join(
+            get_bb_var('TARGET_DBGSRC_DIR', 'libstd-rs'),
+            os.path.relpath(libstd_rustsrc, libstd_work_shared),
+            'library')
+        rust_std_sdk_root = os.path.join(
+            get_bb_var('RECIPE_SYSROOT_NATIVE', 'cargo-example'),
+            'usr', 'lib', 'rustlib', 'src', 'rust', 'library')
+        rust_std_source = os.path.join(
+            rust_std_target_root, 'std', 'src', 'rt.rs')
+        self.assertEqual(
+            launch['sourceMap'][rust_std_target_root], rust_std_sdk_root)
+        self.assertIn(
+            rust_std_source, result.output,
+            'Rust runtime backtrace did not resolve to the SDK debug path:\n%s' %
+            result.output)
+        self.assertNotIn(libstd_rustsrc, result.output)
+        self.assertTrue(
+            os.path.isfile(os.path.join(rust_std_sdk_root, 'std', 'src', 'rt.rs')),
+            'Rust standard-library source is missing from the recipe SDK sysroot')
+
 
 class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests):
 
