From: AdrianF <adrian.freihofer@siemens.com>
To: openembedded-core@lists.openembedded.org
Cc: Adrian Freihofer <adrian.freihofer@siemens.com>
Subject: [PATCH v2 10/14] devtool: ide-sdk add LLDB support for clang toolchain
Date: Tue, 4 Aug 2026 13:59:34 +0200 [thread overview]
Message-ID: <20260804120034.378787-11-adrian.freihofer@siemens.com> (raw)
In-Reply-To: <20260804120034.378787-1-adrian.freihofer@siemens.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
Add support for LLDB (CodeLLDB) remote debugging in VSCode when using
the clang toolchain. This includes:
- New LldbServerConfig class for configuring lldb-server on the target
- LldbServerConfigVSCode for VSCode-specific LLDB configuration
- RecipeLldbNative to handle lldb-native (architecture-agnostic) on the
host
- CodeLLDB VSCode extension recommendation for clang toolchain
- Launch configuration generator for LLDB debugging
- Proper handling of source maps and debug symbol paths for LLDB
Meson/ninja invoke the compiler with source paths relative to the build
directory B, rather than absolute paths. -fdebug-prefix-map and
-ffile-prefix-map only rewrite paths that literally start with the
mapped host prefix, so this relative DW_AT_name is never rewritten;
only the absolute DW_AT_comp_dir is. When resolving the compile unit
path, debuggers join comp_dir with the relative name, popping one
component per leading "..". In devtool workspaces the source directory
S is relocated far away from the build directory B (outside WORKDIR),
so DW_AT_name typically contains more ".." components than comp_dir
has path components. Once the join reaches "/", extra ".." are no-ops,
so the resolved path becomes "/" plus the leftover suffix of DW_AT_name
- a suffix of the real absolute source directory, not the
"/usr/src/debug/<pn>/<pv>" prefix that DEBUG_PREFIX_MAP and the
generated sourceMap assume.
Compute this "broken" resolved suffix for the recipe's own source
directory and use it instead of the original comp_dir-based mapping.
Keeping both mappings would point two different debug-info paths at
the same host path, which is ambiguous when CodeLLDB needs to reverse
the mapping (translating a locally opened file back into a debug-info
path to resolve a breakpoint): it picks the first-registered
("normal") mapping, which never matches any real compile unit here,
leaving breakpoints stuck pending with 0 locations.
Also set launch.json's relativePathBase to the build directory B, so
CodeLLDB resolves any source path that is still relative (i.e. not
covered by sourceMap/target.source-map) against B - the compiler's
working directory - instead of the default ${workspaceFolder}, which
does not necessarily match B in devtool workspaces.
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
scripts/lib/devtool/ide_plugins/__init__.py | 66 ++++++++
scripts/lib/devtool/ide_plugins/ide_code.py | 150 +++++++++++++++++-
scripts/lib/devtool/ide_sdk.py | 161 +++++++++++++++++++-
3 files changed, 368 insertions(+), 9 deletions(-)
diff --git a/scripts/lib/devtool/ide_plugins/__init__.py b/scripts/lib/devtool/ide_plugins/__init__.py
index cfb067548d..25575f18f4 100644
--- a/scripts/lib/devtool/ide_plugins/__init__.py
+++ b/scripts/lib/devtool/ide_plugins/__init__.py
@@ -187,6 +187,72 @@ class GdbCrossConfig(DebuggerCrossConfig):
return "\"kill \\$(pgrep -o -f 'gdbserver --attach :%s') 2>/dev/null || true\"" % self.debug_server_port
+class LldbServerConfig(DebuggerCrossConfig):
+ """Configure lldb-server (platform mode) on the target for CodeLLDB remote debugging.
+
+ Unlike gdbserver, lldb-server platform mode is architecture-agnostic on the host
+ side: a single lldb-native binary handles all target architectures via the
+ LLDB platform protocol that CodeLLDB speaks natively.
+
+ The ATTACH mode is not supported because lldb-server platform does not take a
+ PID argument; attaching is done client-side via 'process attach'.
+ """
+
+ def __init__(self, image_recipe, modified_recipe, binary,
+ default_mode=DebuggerServerModes.MULTI):
+ super().__init__(image_recipe, modified_recipe, binary,
+ default_mode)
+
+ def _lldb_server_tmp_dir(self, mode):
+ return os.path.join('/tmp', 'lldb_server_%s' % self.id_pretty_mode(mode))
+
+ def _lldb_server_pid_file(self, mode):
+ return os.path.join(self._lldb_server_tmp_dir(mode), 'lldb_server.pid')
+
+ def _lldb_server_log_file(self, mode):
+ return os.path.join(self._lldb_server_tmp_dir(mode), 'lldb_server.log')
+
+ def _target_start_cmd(self, mode):
+ """SSH command to start lldb-server in platform mode on the target."""
+ lldb_server = self.debugger_cross.debug_server_path
+ # Use '*:<port>' so lldb-server binds on all interfaces (0.0.0.0), not
+ # just loopback. The bare ':<port>' form only binds to 127.0.0.1 in
+ # lldb-server 21.x and the remote lldb client connects from the host.
+ # Start from /tmp because lldb-server creates temp files in its cwd and
+ # the SSH default cwd (/home/root) may not exist on a minimal image.
+ if mode == DebuggerServerModes.ONCE:
+ cmd = "cd /tmp && %s platform --one-shot --server --listen *:%s" % (
+ lldb_server, self.debug_server_port)
+ elif mode == DebuggerServerModes.MULTI:
+ hex_port = "%04X" % self.debug_server_port
+ pid_file = self._lldb_server_pid_file(mode)
+ tmp_dir = self._lldb_server_tmp_dir(mode)
+ log_file = self._lldb_server_log_file(mode)
+ cmd = "grep -q :%s /proc/net/tcp /proc/net/tcp6 2>/dev/null && exit 0; " % hex_port
+ cmd += "mkdir -p %s; " % tmp_dir
+ cmd += "cd %s; " % tmp_dir
+ cmd += "%s platform --server --listen *:%s > %s 2>&1 & " % (
+ lldb_server, self.debug_server_port, log_file)
+ cmd += "echo \\$! > %s; " % pid_file
+ cmd += "_w=0; while ! grep -q :%s /proc/net/tcp /proc/net/tcp6 2>/dev/null; " % hex_port
+ cmd += "do _w=\\$((_w+1)); [ \\$_w -lt 100 ] || { echo lldb-server did not start on port %s >&2; exit 1; }; sleep 0.1; done;" % self.debug_server_port
+ else:
+ raise DevtoolError(
+ "lldb-server does not support mode %s "
+ "(ATTACH is handled client-side with 'process attach')" % mode)
+ return "\"/bin/sh -c '" + cmd + "'\""
+
+ def _target_kill_cmd(self):
+ """SSH command to stop a MULTI-mode lldb-server on the target."""
+ pid_file = self._lldb_server_pid_file(DebuggerServerModes.MULTI)
+ tmp_dir = self._lldb_server_tmp_dir(DebuggerServerModes.MULTI)
+ cmd = ("test -f %(pf)s && kill \\$(cat %(pf)s) 2>/dev/null; rm -rf %(td)s"
+ % {'pf': pid_file, 'td': tmp_dir})
+ return "\"/bin/sh -c '" + cmd + "'\""
+
+ def server_modes(self):
+ """ATTACH mode is not applicable for lldb-server platform."""
+ return [self.default_mode]
class IdeBase:
"""Base class defining the interface for IDE plugins"""
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py
index d237ab8f66..9faba3f2d1 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -9,7 +9,7 @@ import json
import logging
import os
import shutil
-from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig, DebuggerServerModes, get_devtool_deploy_opts
+from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig, DebuggerServerModes, LldbServerConfig, get_devtool_deploy_opts
logger = logging.getLogger('devtool')
@@ -43,6 +43,28 @@ class GdbCrossConfigVSCode(GdbCrossConfig):
]
+class LldbServerConfigVSCode(LldbServerConfig):
+ """VSCode-specific lldb-server configuration for CodeLLDB remote debugging."""
+
+ def __init__(self, image_recipe, modified_recipe, binary,
+ default_mode=DebuggerServerModes.MULTI):
+ super().__init__(image_recipe, modified_recipe, binary,
+ default_mode)
+
+ def target_ssh_gdbserver_start_args(self, mode=None):
+ """SSH argument list to start lldb-server on the target"""
+ if mode is None:
+ mode = self.default_mode
+ return self._target_ssh_args() + [
+ self._target_start_cmd(mode)
+ ]
+
+ def target_ssh_gdbserver_kill_args(self):
+ """SSH argument list to stop a running MULTI-mode lldb-server"""
+ return self._target_ssh_args() + [
+ self._target_kill_cmd()
+ ]
+
class IdeVSCode(IdeBase):
"""Manage IDE configurations for VSCode
@@ -284,6 +306,10 @@ class IdeVSCode(IdeBase):
"ms-vscode.cpptools-extension-pack",
"ms-vscode.cpptools-themes"
]
+ # For clang toolchain, CodeLLDB provides native LLDB debugging in VSCode
+ if (modified_recipe.toolchain == 'clang'
+ and modified_recipe.build_tool.is_c_cpp):
+ recommendations.append("vadimcn.vscode-lldb")
if modified_recipe.build_tool is BuildTool.CMAKE:
recommendations.append("ms-vscode.cmake-tools")
if modified_recipe.build_tool is BuildTool.MESON:
@@ -327,7 +353,9 @@ class IdeVSCode(IdeBase):
self.dot_code_dir(modified_recipe), prop_file, properties_dicts)
def vscode_launch_bin_dbg(self, cross_debug_config, server_mode):
- """Dispatch to the GDB launch config generator."""
+ """Dispatch to the GDB or LLDB launch config generator."""
+ if isinstance(cross_debug_config, LldbServerConfig):
+ return self._vscode_launch_bin_dbg_lldb(cross_debug_config, server_mode)
return self._vscode_launch_bin_dbg_gdb(cross_debug_config, server_mode)
def _vscode_launch_bin_dbg_gdb(self, cross_debug_config, server_mode):
@@ -414,6 +442,116 @@ class IdeVSCode(IdeBase):
return launch_config
+ def _vscode_launch_bin_dbg_lldb(self, lldb_config, server_mode):
+ """Generate a CodeLLDB (type: lldb) launch configuration entry for launch.json.
+
+ CodeLLDB connects to lldb-server via the LLDB platform protocol. The
+ initCommands select the remote platform and open the connection before
+ the process is launched, so CodeLLDB can inspect and control it.
+
+ Using targetCreateCommands instead of "program" so we can pass both the
+ local host binary (for debug symbols) and the remote target path (where
+ devtool deploy-target has already installed the binary) to
+ "target create --remote-file". This prevents LLDB from uploading the
+ binary from its module cache to a temporary directory and ensures the
+ process starts from its installed location where the dynamic linker can
+ find shared libraries via the standard search paths.
+ """
+ modified_recipe = lldb_config.modified_recipe
+ debugger_cross = modified_recipe.debugger_cross
+
+ init_commands = [
+ "platform select remote-linux",
+ "platform connect connect://%s:%d" % (debugger_cross.host, lldb_config.debug_server_port),
+ # Clear the default step-avoid-regexp so std:: and other library
+ # namespaces are not silently skipped on step-in. (default is "std::" in LLDB 15+)
+ "settings set target.process.thread.step-avoid-regexp \"\"",
+ ]
+ # Search for header files in recipe-sysroot (same as GDB sourceFileMap).
+ source_map = {
+ "/usr/include": os.path.join(modified_recipe.recipe_sysroot, "usr", "include")
+ }
+ if lldb_config.image_recipe.rootfs_dbg:
+ # Map build-time paths back to the workspace source tree.
+ for target_path, host_path in modified_recipe.reverse_debug_prefix_map.items():
+ if host_path.startswith(modified_recipe.real_srctree):
+ source_map[target_path] = (
+ "${workspaceFolder}"
+ + host_path[len(modified_recipe.real_srctree):])
+ else:
+ source_map[target_path] = host_path
+ if "/usr/src/debug" in source_map:
+ logger.error(
+ 'Key "/usr/src/debug" already exists in source_map. '
+ 'Something with DEBUG_PREFIX_MAP looks unexpected and finding '
+ 'sources in the rootfs-dbg will not work as expected.')
+ else:
+ source_map["/usr/src/debug"] = os.path.join(
+ lldb_config.image_recipe.rootfs_dbg, "usr", "src", "debug")
+
+ # Point LLDB at the .debug directories in rootfs-dbg.
+ debug_search_paths = " ".join(
+ modified_recipe.solib_search_path(lldb_config.image_recipe))
+ init_commands.append(
+ "settings set target.debug-file-search-paths %s" % debug_search_paths)
+
+ # Point LLDB at the unstripped binaries and shared libraries in ${D}
+ # so it can load debug symbols for the recipe's own shared libraries.
+ # These are the files deployed by devtool deploy-target.
+ exec_search_paths = " ".join([
+ os.path.join(modified_recipe.d, modified_recipe.libdir.lstrip('/')),
+ os.path.join(modified_recipe.d, modified_recipe.base_libdir.lstrip('/')),
+ os.path.join(modified_recipe.d, modified_recipe.bindir.lstrip('/')),
+ ])
+ # Deduplicate in case base_libdir == libdir or paths coincide
+ exec_search_paths = " ".join(dict.fromkeys(exec_search_paths.split()))
+ init_commands.append(
+ "settings set target.exec-search-paths %s" % exec_search_paths)
+ else:
+ logger.warning(
+ "Cannot setup debug symbols configuration for LLDB. "
+ "IMAGE_GEN_DEBUGFS is not enabled.")
+
+ # "target create --remote-file <target_path> <host_debug_binary>":
+ # --remote-file tells LLDB which path to execute on the target.
+ # The positional argument is the local host binary, loaded for symbols.
+ # This keeps devtool deploy-target as the sole deployment mechanism and
+ # avoids LLDB uploading the binary to a temporary directory via its
+ # module cache. Running from the installed path ensures the dynamic
+ # linker on the target can find shared libraries at their standard
+ # locations.
+ target_create_cmd = "target create --remote-file %s %s" % (
+ lldb_config.binary.binary_path,
+ lldb_config.binary.binary_host_path)
+
+ launch_config = {
+ "name": lldb_config.id_pretty_mode(server_mode),
+ "type": "lldb",
+ "request": "launch",
+ # Use targetCreateCommands instead of "program" to control both
+ # the local binary (for debug symbols) and the remote path.
+ "targetCreateCommands": [target_create_cmd],
+ "stopOnEntry": False,
+ "cwd": "/tmp",
+ "preLaunchTask": lldb_config.id_pretty_mode(server_mode),
+ "initCommands": init_commands,
+ }
+ if source_map:
+ launch_config["sourceMap"] = source_map
+ if modified_recipe.b:
+ # CodeLLDB resolves any source path that is still relative (as
+ # opposed to being rewritten to an absolute path by sourceMap /
+ # target.source-map) against "relativePathBase", defaulting to
+ # ${workspaceFolder}. Compilers are invoked with the build
+ # directory B as their working directory, so relative DW_AT_name
+ # entries (e.g. from meson/ninja) are relative to B. Pointing
+ # relativePathBase at B lets CodeLLDB resolve these directly,
+ # which matters in particular for devtool workspaces where S
+ # (and thus ${workspaceFolder}) is relocated outside of WORKDIR.
+ launch_config["relativePathBase"] = modified_recipe.b
+
+ return launch_config
+
def vscode_launch(self, args, modified_recipe):
"""GDB launch configurations for user-space binaries.
@@ -745,8 +883,12 @@ class IdeVSCode(IdeBase):
self.vscode_extensions(modified_recipe)
self.vscode_c_cpp_properties(modified_recipe)
if args.target:
- self.initialize_cross_debug_configs(
- image_recipe, modified_recipe, GdbCrossConfigVSCode)
+ if modified_recipe.toolchain == 'clang':
+ self.initialize_cross_debug_configs(
+ image_recipe, modified_recipe, LldbServerConfigVSCode)
+ else:
+ self.initialize_cross_debug_configs(
+ image_recipe, modified_recipe, GdbCrossConfigVSCode)
self.vscode_launch(args, modified_recipe)
self.vscode_tasks(args, modified_recipe)
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 13fab50f22..b56a0925cb 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -137,6 +137,45 @@ class RecipeGdbCross(RecipeNative):
return self.target_device.host
+class RecipeLldbNative(RecipeNative):
+ """Handle lldb on the host and lldb-server on the target device.
+
+ Unlike GDB which requires a per-architecture gdb-cross-<arch> binary, LLDB
+ is architecture-agnostic: a single lldb-native installation can debug any
+ target architecture via the LLDB platform protocol.
+
+ On the target side, lldb-server (the ${PN}-server sub-package from the lldb
+ recipe) provides the platform server that CodeLLDB connects to.
+ """
+
+ def __init__(self, args, target_device):
+ super().__init__('lldb-native')
+ self.target_device = target_device
+ self._lldb = None
+ self._lldb_server_path = None
+
+ def __find_lldb_server(self, config, tinfoil):
+ """Absolute path of lldb-server on the target (from the lldb recipe)."""
+ recipe_d_lldb = parse_recipe(
+ config, tinfoil, 'lldb', appends=True, filter_workspace=False)
+ if not recipe_d_lldb:
+ raise DevtoolError("Parsing lldb recipe failed")
+ return os.path.join(recipe_d_lldb.getVar('bindir'), 'lldb-server')
+
+ def initialize(self, config, workspace, tinfoil):
+ super()._initialize(config, workspace, tinfoil)
+ self._lldb = os.path.join(self.staging_bindir_native, 'lldb')
+ self._lldb_server_path = self.__find_lldb_server(config, tinfoil)
+
+ @property
+ def debug_server_path(self):
+ return self._lldb_server_path
+
+ @property
+ def host(self):
+ return self.target_device.host
+
+
class RecipeImage:
"""Handle some image recipe related properties
@@ -169,8 +208,9 @@ class RecipeImage:
if image_d.getVar('IMAGE_GEN_DEBUGFS') == "1":
self.__rootfs_dbg = os.path.join(workdir, 'rootfs-dbg')
- self.gdbserver_missing = 'gdbserver' not in image_d.getVar(
- 'IMAGE_INSTALL') and 'tools-debug' not in image_d.getVar('IMAGE_FEATURES')
+ package_install = image_d.getVar('PACKAGE_INSTALL').split()
+ self.gdbserver_missing = 'gdbserver' not in package_install
+ self.lldb_server_missing = 'lldb-server' not in package_install
@property
def debug_support(self):
@@ -396,6 +436,7 @@ class RecipeModified:
self.b = None
self.base_libdir = None
self.bblayers = None
+ self.bindir = None
self.bitbakepath = None
self.bpn = None
self.d = None
@@ -476,6 +517,7 @@ class RecipeModified:
self.b = recipe_d.getVar('B')
self.base_libdir = recipe_d.getVar('base_libdir')
self.bblayers = recipe_d.getVar('BBLAYERS').split()
+ self.bindir = recipe_d.getVar('bindir')
self.bitbakepath = recipe_d.getVar('BITBAKEPATH')
self.bpn = recipe_d.getVar('BPN')
self.cc = recipe_d.getVar('CC')
@@ -669,8 +711,106 @@ class RecipeModified:
if unused_host_paths:
logger.info("Some source directories mapped by -fdebug-prefix-map are not included in the debugger search paths. Ignored host paths: %s", unused_host_paths)
+ self._add_broken_srctree_prefix_map(mappings)
+
return mappings
+ def _add_broken_srctree_prefix_map(self, mappings):
+ """Work around a -f*-prefix-map / DWARF path resolution issue affecting
+ out-of-tree devtool workspaces (e.g. meson recipes built via 'devtool modify'
+ with the clang toolchain).
+
+ meson/ninja may invoke the compiler with a *relative* source file path
+ when the build directory B (under WORKDIR) and the source directory S
+ (relocated outside WORKDIR by 'devtool modify') only share a distant
+ common ancestor. -fdebug-prefix-map/-ffile-prefix-map only rewrite
+ paths that literally start with the mapped host prefix, so a relative
+ path argument is never rewritten: only DW_AT_comp_dir (which is
+ absolute) gets rewritten, DW_AT_name stays relative and unrewritten.
+
+ This has only been observed to actually happen with the clang
+ toolchain: clang's meson/ninja invocation embeds a relative DW_AT_name
+ for out-of-tree sources, while gcc, even via meson/ninja, embeds an
+ absolute (and correctly -fdebug-prefix-map-rewritten) DW_AT_name, so
+ no underflow can happen there - confirmed empirically:
+ oe-selftest's test_devtool_ide_sdk_none_qemu (gcc toolchain, covering
+ both cmake-example and meson-example) fails when this workaround is
+ applied unconditionally to meson, while the dedicated clang tests
+ (test_devtool_ide_sdk_{code,none}_meson_clang) require it. cmake
+ (with the Ninja or Makefiles generators used here) always passes
+ absolute source paths to the compiler regardless of toolchain, so it
+ never needs this workaround either. Applying this workaround outside
+ of the meson+clang combination would incorrectly discard the correct
+ (and, for gcc/cmake, already working) comp_dir-based mapping - see the
+ 'del mappings[target_path]' below - falling back to the generic
+ '/usr/src/debug' mapping to the image's (stale, whole-image-build-time)
+ rootfs-dbg instead of the live source tree.
+
+ Debuggers resolve the compile unit path by joining DW_AT_comp_dir with
+ the relative DW_AT_name, popping one path component per leading "..".
+ If DW_AT_name contains more ".." components than DW_AT_comp_dir has
+ path components, the extra ".." are no-ops once the root is reached
+ (they can't go above "/"), so the final resolved path becomes "/"
+ followed by the leftover (non-"..") components of DW_AT_name - i.e. a
+ suffix of the real, absolute source directory rather than the
+ "/usr/src/debug/<pn>/<pv>" prefix that DEBUG_PREFIX_MAP and the
+ generated sourceMap/sourceFileMap assume.
+
+ This computes that resolved suffix for the recipe's own source
+ directory (S) and replaces the (now dead, since every file under S is
+ affected the same way) comp_dir-based mapping with it, so debuggers
+ relying on prefix matching (e.g. CodeLLDB, GDB) can still locate the
+ sources.
+
+ Note: the original comp_dir-based target_path is removed rather than
+ kept alongside the new one. Keeping both would mean two different
+ target paths map to the same host path (S), which is ambiguous when a
+ debugger needs to go the other way round: translating a local file
+ (opened from the host/workspace) back into a debug-info path in order
+ to resolve a source breakpoint. CodeLLDB in particular appears to
+ pick the first-registered ("normal", comp_dir-based) mapping in that
+ case, which never matches any real compile unit here, leaving the
+ breakpoint pending with 0 locations.
+ """
+ if self.build_tool is not BuildTool.MESON or self.toolchain != "clang":
+ return
+ if not self.real_srctree or not self.b:
+ return
+
+ b_real = os.path.realpath(self.b)
+ srctree_real = os.path.realpath(self.real_srctree)
+ common = os.path.commonpath([b_real, srctree_real])
+ if common in (b_real, srctree_real):
+ # B is srctree (or a parent of it), or B is nested inside srctree:
+ # either way the compiler is never invoked with a source path that
+ # climbs above the common ancestor, so no underflow can happen.
+ return
+
+ # Number of ".." path components needed to get from the compiler's
+ # working directory (the build directory B) up to the common ancestor
+ # with the source tree. This is how many leading ".." components
+ # DW_AT_name would contain for sources directly under S.
+ overshoot_components = len(os.path.relpath(b_real, common).split(os.sep))
+
+ for target_path, host_path in list(mappings.items()):
+ if host_path != srctree_real:
+ # Only the recipe's own source directory (S) is relocated by
+ # devtool modify, other mapped directories are unaffected.
+ continue
+ comp_dir_components = len([c for c in target_path.split('/') if c])
+ if overshoot_components <= comp_dir_components:
+ # The rewritten DW_AT_comp_dir has enough components to
+ # absorb all the ".." in DW_AT_name, no underflow happens.
+ continue
+ broken_target = '/' + os.path.relpath(srctree_real, common)
+ if broken_target not in mappings:
+ mappings[broken_target] = host_path
+ # The comp_dir-based target_path never actually occurs in the
+ # debug info for files under S (all of them hit the same
+ # overshoot), so keeping it around only creates an ambiguous
+ # reverse mapping (see docstring above). Drop it.
+ del mappings[target_path]
+
@property
def gdb_pretty_print_scripts(self):
if self._gdb_pretty_print_scripts is None:
@@ -1182,8 +1322,11 @@ def ide_setup(args, config, basepath, workspace):
recipe_modified.toolchain or '')
if debugger_key not in debuggers:
target_device = TargetDevice(args)
- debugger = RecipeGdbCross(
- args, recipe_modified.target_arch, target_device)
+ if recipe_modified.toolchain == 'clang':
+ debugger = RecipeLldbNative(args, target_device)
+ else:
+ debugger = RecipeGdbCross(
+ args, recipe_modified.target_arch, target_device)
debugger.initialize(config, workspace, tinfoil)
bootstrap_tasks += debugger.bootstrap_tasks
debuggers[debugger_key] = debugger
@@ -1207,12 +1350,20 @@ def ide_setup(args, config, basepath, workspace):
wants_gdbserver = any(
r.wants_gdbserver and r.toolchain == 'gcc'
for r in recipes_modified)
+ wants_lldb_server = any(
+ r.wants_gdbserver and r.toolchain == 'clang'
+ for r in recipes_modified)
for recipe_image in recipes_images:
if wants_gdbserver and recipe_image.gdbserver_missing:
logger.warning(
"gdbserver not installed in image %s. Remote debugging will not be available" % recipe_image)
+ if wants_lldb_server and recipe_image.lldb_server_missing:
+ logger.warning(
+ "lldb-server not installed in image %s. "
+ "Remote debugging with LLDB (CodeLLDB) will not be available. "
+ "Add 'lldb-server' to IMAGE_INSTALL." % recipe_image)
- if wants_gdbserver and recipe_image.combine_dbg_image is False:
+ if (wants_gdbserver or wants_lldb_server) and recipe_image.combine_dbg_image is False:
logger.warning(
'IMAGE_CLASSES += "image-combined-dbg" is missing for image %s. Remote debugging will not find debug symbols from rootfs-dbg.' % recipe_image)
--
2.55.0
next prev parent reply other threads:[~2026-08-04 12:00 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 11:59 [PATCH v2 00/14] devtool ide-sdk: clang and lldb support AdrianF
2026-08-04 11:59 ` [PATCH v2 01/14] oe-selftest: devtool: use stat for reading user/group names in ide-sdk tests AdrianF
2026-08-04 11:59 ` [PATCH v2 02/14] devtool: ide-sdk: fix duplicate -p flag in _target_ssh_args AdrianF
2026-08-04 11:59 ` [PATCH v2 03/14] devtool: ide-sdk: fix $@ overwritten by set in install_and_deploy script AdrianF
2026-08-04 11:59 ` [PATCH v2 04/14] devtool: ide-sdk: fix meson compile_commands.json AdrianF
2026-08-04 11:59 ` [PATCH v2 05/14] devtool: deploy-target: fix run strip under pseudo AdrianF
2026-08-04 11:59 ` [PATCH v2 06/14] oe-selftest: devtool ide-sdk: cover breakpoints in exe, header and library AdrianF
2026-08-04 11:59 ` [PATCH v2 07/14] oe-selftest: devtool ide-sdk: add real debug coverage for meson+code AdrianF
2026-08-04 11:59 ` [PATCH v2 08/14] devtool: ide-sdk debugger back-end abstraction AdrianF
2026-08-04 11:59 ` [PATCH v2 09/14] devtool: ide-sdk: wait for gdbserver port before returning AdrianF
2026-08-04 11:59 ` AdrianF [this message]
2026-08-04 11:59 ` [PATCH v2 11/14] devtool: ide-sdk: add LLDB support for ide=none (clang toolchain) AdrianF
2026-08-04 11:59 ` [PATCH v2 12/14] meta-selftest: refactor cpp examples into .inc files and add clang variants AdrianF
2026-08-04 11:59 ` [PATCH v2 13/14] oe-selftest: devtool ide-sdk: add clang/LLDB test AdrianF
2026-08-07 15:11 ` [OE-core] " Mathieu Dubois-Briand
2026-08-07 15:17 ` Freihofer, Adrian
2026-08-07 15:44 ` Mathieu Dubois-Briand
2026-08-09 9:46 ` adrian.freihofer
2026-08-04 11:59 ` [PATCH v2 14/14] oe-selftest: devtool ide-sdk: add test for ide=none LLDB/clang support AdrianF
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260804120034.378787-11-adrian.freihofer@siemens.com \
--to=adrian.freihofer@siemens.com \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox