@@ -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]
@@ -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)
@@ -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