From: AdrianF <adrian.freihofer@siemens.com>
To: openembedded-core@lists.openembedded.org
Cc: Adrian Freihofer <adrian.freihofer@siemens.com>
Subject: [PATCH v2 11/14] devtool: ide-sdk: add LLDB support for ide=none (clang toolchain)
Date: Tue, 4 Aug 2026 13:59:35 +0200 [thread overview]
Message-ID: <20260804120034.378787-12-adrian.freihofer@siemens.com> (raw)
In-Reply-To: <20260804120034.378787-1-adrian.freihofer@siemens.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
Bring ide=none to feature parity with ide=code for clang recipes by
adding LldbServerConfigNone and dispatching on the toolchain in
IdeNone.setup_modified_recipe.
Three files are generated per binary when toolchain == 'clang':
lldb_server_<port>_<binary>_<mode>
Shell script with start/stop logic (same pattern as the existing
gdbserver_* scripts). Passes the lldb-server SSH command produced
by LldbServerConfig._target_start_cmd, which already includes the
/proc/net/tcp readiness poll for MULTI mode.
lldbinit/lldbinit_<port>_<binary>
Init file sourced by lldb via -s. Sets up the remote platform
connection, source maps, debug-file-search-paths and
exec-search-paths, then creates the target with
"target create --remote-file <target_path> <host_debug_binary>".
lldb_<port>_<binary>
Wrapper script: cd <srctree> && lldb -s <lldbinit> "$@"
Supporting changes:
LldbServerConfig (ide_plugins/__init__.py): add server_script_file /
server_script, which were left as NotImplementedError in the base
class. Required for LldbServerConfigNone to write its start scripts
to the correct paths.
RecipeLldbNative (ide_sdk.py): rename _lldb -> lldb (plain attribute),
matching the RecipeGdbCross.gdb convention so that ide_none.py can
access the host lldb binary path without going through a property.
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
scripts/lib/devtool/ide_plugins/__init__.py | 6 +
scripts/lib/devtool/ide_plugins/ide_none.py | 138 +++++++++++++++++++-
scripts/lib/devtool/ide_sdk.py | 4 +-
3 files changed, 143 insertions(+), 5 deletions(-)
diff --git a/scripts/lib/devtool/ide_plugins/__init__.py b/scripts/lib/devtool/ide_plugins/__init__.py
index 25575f18f4..d50ba7bc65 100644
--- a/scripts/lib/devtool/ide_plugins/__init__.py
+++ b/scripts/lib/devtool/ide_plugins/__init__.py
@@ -250,6 +250,12 @@ class LldbServerConfig(DebuggerCrossConfig):
% {'pf': pid_file, 'td': tmp_dir})
return "\"/bin/sh -c '" + cmd + "'\""
+ def server_script_file(self, mode):
+ return 'lldb_server_' + self.id_pretty_mode(mode)
+
+ def server_script(self, mode):
+ return os.path.join(self.script_dir, self.server_script_file(mode))
+
def server_modes(self):
"""ATTACH mode is not applicable for lldb-server platform."""
return [self.default_mode]
diff --git a/scripts/lib/devtool/ide_plugins/ide_none.py b/scripts/lib/devtool/ide_plugins/ide_none.py
index f390331776..a8ddc3f39f 100644
--- a/scripts/lib/devtool/ide_plugins/ide_none.py
+++ b/scripts/lib/devtool/ide_plugins/ide_none.py
@@ -9,7 +9,7 @@ import os
import logging
import stat
from bb.utils import mkdirhier
-from devtool.ide_plugins import IdeBase, GdbCrossConfig, DebuggerServerModes
+from devtool.ide_plugins import IdeBase, GdbCrossConfig, LldbServerConfig, DebuggerServerModes
logger = logging.getLogger('devtool')
@@ -145,6 +145,134 @@ class GdbCrossConfigNone(GdbCrossConfig):
logger.info("Created: %s" % script_file)
+class LldbServerConfigNone(LldbServerConfig):
+ """Generate lldb helper scripts for ide=none when using the clang toolchain."""
+
+ def __init__(self, image_recipe, modified_recipe, binary,
+ default_mode=DebuggerServerModes.MULTI):
+ super().__init__(image_recipe, modified_recipe, binary, default_mode)
+
+ @property
+ def lldbinit_dir(self):
+ return os.path.join(self.script_dir, 'lldbinit')
+
+ @property
+ def lldbinit(self):
+ return os.path.join(self.lldbinit_dir, 'lldbinit_' + self.id_pretty)
+
+ @property
+ def lldb_script(self):
+ return os.path.join(self.script_dir, 'lldb_' + self.id_pretty)
+
+ def _target_lldb_server_stop_cmd(self, server_mode):
+ """SSH command to stop lldb-server on the target."""
+ if server_mode == DebuggerServerModes.MULTI:
+ pid_file = self._lldb_server_pid_file(server_mode)
+ tmp_dir = self._lldb_server_tmp_dir(server_mode)
+ cmd = ("test -f %(pf)s && kill \\$(cat %(pf)s) 2>/dev/null; rm -rf %(td)s"
+ % {'pf': pid_file, 'td': tmp_dir})
+ else:
+ cmd = "killall lldb-server 2>/dev/null || true"
+ return "\"/bin/sh -c '" + cmd + "'\""
+
+ def _gen_lldb_server_start_script(self, server_mode=None):
+ """Generate a shell script starting lldb-server on the remote device via ssh."""
+ if server_mode is None:
+ server_mode = self.default_mode
+ server_cmd_start = self._target_start_cmd(server_mode)
+ server_cmd_stop = self._target_lldb_server_stop_cmd(server_mode)
+ remote_ssh = "%s %s" % (self.debugger_cross.target_device.ssh_sshexec,
+ " ".join(self._target_ssh_args()))
+ script_lines = ['#!/bin/sh']
+ script_lines.append('if [ "$1" = "stop" ]; then')
+ script_lines.append(' shift')
+ script_lines.append(" %s %s" % (remote_ssh, server_cmd_stop))
+ script_lines.append('else')
+ script_lines.append(" %s %s" % (remote_ssh, server_cmd_start))
+ script_lines.append('fi')
+ LldbServerConfigNone.write_file(self.server_script(server_mode), script_lines, True)
+
+ def _gen_lldbinit_config(self, server_mode=None):
+ """Generate an lldbinit file for connecting to lldb-server on the target."""
+ if server_mode is None:
+ server_mode = self.default_mode
+ lines = ['# This file is generated by devtool ide-sdk']
+ if server_mode == DebuggerServerModes.MULTI:
+ lines.append('# On the remote target:')
+ lines.append('# lldb-server platform --server --listen *:%d' % self.debug_server_port)
+ else:
+ lines.append('# On the remote target:')
+ lines.append('# lldb-server platform --one-shot --server --listen *:%d' % self.debug_server_port)
+ lines.append('# On the build machine:')
+ lines.append('# cd ' + self.modified_recipe.real_srctree)
+ lines.append('# ' + self.debugger_cross.lldb + ' -s ' + self.lldbinit)
+ lines.append('platform select remote-linux')
+ lines.append('platform connect connect://%s:%d' % (
+ self.debugger_cross.host, self.debug_server_port))
+ lines.append('settings set target.process.thread.step-avoid-regexp ""')
+
+ if self.image_recipe.rootfs_dbg:
+ src_file_map = dict(self.modified_recipe.reverse_debug_prefix_map)
+ if '/usr/src/debug' in src_file_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:
+ src_file_map['/usr/src/debug'] = os.path.join(
+ self.image_recipe.rootfs_dbg, 'usr', 'src', 'debug')
+ if src_file_map:
+ # Pass all pairs as a single settings set call
+ map_args = []
+ for target_path, host_path in src_file_map.items():
+ map_args += ['"' + target_path + '"', '"' + host_path + '"']
+ lines.append('settings set target.source-map %s' % ' '.join(map_args))
+
+ debug_search_paths = ' '.join(
+ self.modified_recipe.solib_search_path(self.image_recipe))
+ lines.append('settings set target.debug-file-search-paths %s' % debug_search_paths)
+
+ exec_paths = list(dict.fromkeys([
+ os.path.join(self.modified_recipe.d, self.modified_recipe.libdir.lstrip('/')),
+ os.path.join(self.modified_recipe.d, self.modified_recipe.base_libdir.lstrip('/')),
+ os.path.join(self.modified_recipe.d, self.modified_recipe.bindir.lstrip('/')),
+ ]))
+ lines.append('settings set target.exec-search-paths %s' % ' '.join(exec_paths))
+ else:
+ logger.warning(
+ 'Cannot setup debug symbols configuration for LLDB. '
+ 'IMAGE_GEN_DEBUGFS is not enabled.')
+
+ lines.append('target create --remote-file %s %s' % (
+ self.binary.binary_path, self.binary.binary_host_path))
+
+ LldbServerConfigNone.write_file(self.lldbinit, lines)
+
+ def _gen_lldb_start_script(self):
+ """Generate a script starting lldb with the lldbinit configuration."""
+ cmd_lines = ['#!/bin/sh']
+ cmd_lines.append('cd ' + self.modified_recipe.real_srctree)
+ cmd_lines.append(self.debugger_cross.lldb + ' -s ' + self.lldbinit + ' "$@"')
+ LldbServerConfigNone.write_file(self.lldb_script, cmd_lines, True)
+
+ def initialize(self):
+ self._gen_lldb_server_start_script()
+ self._gen_lldbinit_config()
+ self._gen_lldb_start_script()
+
+ @staticmethod
+ def write_file(script_file, cmd_lines, executable=False):
+ script_dir = os.path.dirname(script_file)
+ mkdirhier(script_dir)
+ with open(script_file, 'w') as script_f:
+ script_f.write(os.linesep.join(cmd_lines))
+ script_f.write(os.linesep)
+ if executable:
+ st = os.stat(script_file)
+ os.chmod(script_file, st.st_mode | stat.S_IEXEC)
+ logger.info("Created: %s" % script_file)
+
+
class IdeNone(IdeBase):
"""Generate some generic helpers for other IDEs
@@ -177,8 +305,12 @@ class IdeNone(IdeBase):
script_path = modified_recipe.gen_install_deploy_script(args)
logger.info("Created: %s" % script_path)
- self.initialize_cross_debug_configs(
- image_recipe, modified_recipe, GdbCrossConfigNone)
+ if modified_recipe.toolchain == 'clang':
+ self.initialize_cross_debug_configs(
+ image_recipe, modified_recipe, LldbServerConfigNone)
+ else:
+ self.initialize_cross_debug_configs(
+ image_recipe, modified_recipe, GdbCrossConfigNone)
IdeBase.gen_oe_scripts_sym_link(modified_recipe)
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index b56a0925cb..42b6e381c5 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -151,7 +151,7 @@ class RecipeLldbNative(RecipeNative):
def __init__(self, args, target_device):
super().__init__('lldb-native')
self.target_device = target_device
- self._lldb = None
+ self.lldb = None
self._lldb_server_path = None
def __find_lldb_server(self, config, tinfoil):
@@ -164,7 +164,7 @@ class RecipeLldbNative(RecipeNative):
def initialize(self, config, workspace, tinfoil):
super()._initialize(config, workspace, tinfoil)
- self._lldb = os.path.join(self.staging_bindir_native, 'lldb')
+ self.lldb = os.path.join(self.staging_bindir_native, 'lldb')
self._lldb_server_path = self.__find_lldb_server(config, tinfoil)
@property
--
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 ` [PATCH v2 10/14] devtool: ide-sdk add LLDB support for clang toolchain AdrianF
2026-08-04 11:59 ` AdrianF [this message]
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-12-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