From: AdrianF <adrian.freihofer@siemens.com>
To: openembedded-core@lists.openembedded.org
Cc: Adrian Freihofer <adrian.freihofer@siemens.com>
Subject: [PATCH 1/9] devtool: ide-sdk: fix GDB loading stale libs instead of recipe's own build
Date: Sun, 6 Sep 2026 23:01:59 +0200 [thread overview]
Message-ID: <20260906210307.2793974-2-adrian.freihofer@siemens.com> (raw)
In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
Setting GDB's sysroot to the recipe's D (image/) directory is often not
enough: D only contains "usr/lib", but the target reports merged-usr
paths like "/lib/libfoo.so.0", so the sysroot lookup fails and GDB
falls back to solib-search-path, resolving the library from the full
image's rootfs-dbg/rootfs instead. Recipes that install libraries
outside the standard libdir hit this on every rebuild, silently
debugging with stale symbols from the last full image build. Confirmed
against gdb-17.2 gdb/solib.c (solib_find_1()) by capturing the GDB MI
trace of an attach session and cross-checking against that code.
Fix: add RecipeModified._find_elf_dirs(), which walks D and returns
every directory containing an ELF file, and prepend those directories
to additionalSOLibSearchPath, ahead of the rootfs-dbg/rootfs entries,
in every generated launch config. Since with usrmerge in
DISTRO_FEATURES (the default) base_libdir and libdir resolve to the
same path, this can introduce literal duplicates in the list; dedupe
with list(dict.fromkeys(...)) instead of a set, since the order of
the list is essential: it defines GDB's solib-search-path priority.
Also extend the launch.json oe-selftest assertions to check that the
first additionalSOLibSearchPath entry is the recipe's own image (D)
directory, not rootfs-dbg.
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 5 ++
scripts/lib/devtool/ide_sdk.py | 62 +++++++++++++++++--------
2 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 3e0eb7948f..de59feadb8 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -3591,6 +3591,11 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests):
so_paths = config.get("additionalSOLibSearchPath", [])
self.assertIn("/.debug", so_paths, f"Configuration '{config['name']}' should include debug symbol paths")
self.assertIn("/rootfs-dbg/", so_paths, f"Configuration '{config['name']}' should include rootfs-dbg paths")
+ # The recipe's own D/usr/lib must come first, so GDB's solib-search-path basename fallback
+ # prefers freshly rebuilt libraries over a stale rootfs-dbg/rootfs copy from the last full image build.
+ first_so_path = so_paths.split(":", 1)[0]
+ self.assertIn("/image/", first_so_path, f"Configuration '{config['name']}' first SO lib search path should be the recipe's own image dir: {first_so_path}")
+ self.assertNotIn("rootfs-dbg", first_so_path, f"Configuration '{config['name']}' first SO lib search path should not be rootfs-dbg: {first_so_path}")
# Verify source file mappings
source_map = config.get("sourceFileMap", {})
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 9225546c5e..6558137134 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -827,27 +827,50 @@ class RecipeModified:
return True
return False
+ @staticmethod
+ def _find_elf_dirs(root):
+ """Return every directory under root that contains an ELF file"""
+ elf_dirs = []
+ for dirpath, _dirnames, filenames in os.walk(root):
+ for filename in filenames:
+ file_path = os.path.join(dirpath, filename)
+ if os.path.islink(file_path):
+ continue
+ try:
+ with open(file_path, 'rb') as elf_file:
+ is_elf = elf_file.read(4) == b'\x7fELF'
+ except OSError:
+ continue
+ if is_elf:
+ elf_dirs.append(dirpath)
+ break
+ return elf_dirs
+
def solib_search_path(self, image):
- """Search for debug symbols in the rootfs and rootfs-dbg
+ """Search for debug symbols
- The debug symbols of shared libraries which are provided by other packages
- are grabbed from the -dbg packages in the rootfs-dbg.
+ This recipe's own D is searched (for ELF files, wherever they are
+ installed), so that this recipe's freshly rebuilt libraries take
+ precedence over any stale copy from the last full image build.
+ "set sysroot D" alone cannot achieve this: GDB's sysroot (tested with
+ GDB 17.2) only matches "/lib" paths, but D usually only contains
+ "usr/lib" (no top-level "lib" symlink), so it falls back to
+ solib-search-path's basename matching instead. This also covers
+ libraries not installed into the standard libdirs.
- But most cross debugging tools like gdb, perf, and systemtap need to find
- executable/library first and through it debuglink note find corresponding
- symbols file. Therefore the library paths from the rootfs are added as well.
-
- Note: For the devtool modified recipe compiled from the IDE, the debug
- symbols are taken from the unstripped binaries in the image folder.
- Also, devtool deploy-target takes the files from the image folder.
- debug symbols in the image folder refer to the corresponding source files
- with absolute paths of the build machine. Debug symbols found in the
- rootfs-dbg are relocated and contain paths which refer to the source files
- installed on the target device e.g. /usr/src/...
+ D is listed first, ahead of rootfs-dbg/rootfs. For every other
+ library, i.e. one provided by another package, debug symbols are
+ grabbed from the -dbg packages in rootfs-dbg. gdb, perf, and
+ systemtap need to find the executable/library itself first, and
+ through its debuglink find the symbols file, so the plain rootfs
+ paths are added too.
"""
base_libdir = self.base_libdir.lstrip('/')
libdir = self.libdir.lstrip('/')
- so_paths = [
+ # dedupe (e.g. base_libdir = libdir) while keeping the order (using dict instead of set)
+ so_paths = dict.fromkeys([
+ # This recipe's own rebuilt libraries/plugins, ahead of rootfs-dbg/rootfs.
+ *self._find_elf_dirs(self.d),
# debug symbols for package_debug_split_style: debug-with-srcpkg or .debug
os.path.join(image.rootfs_dbg, base_libdir, ".debug"),
os.path.join(image.rootfs_dbg, libdir, ".debug"),
@@ -858,13 +881,12 @@ class RecipeModified:
# With image-combined-dbg.bbclass the binaries are copied into rootfs-dbg
os.path.join(image.rootfs_dbg, base_libdir),
os.path.join(image.rootfs_dbg, libdir),
- # Without image-combined-dbg.bbclass the binaries are only in rootfs.
- # Note: Stepping into source files located in rootfs-dbg does not
- # work without image-combined-dbg.bbclass yet.
+ # Without image-combined-dbg.bbclass the binaries are only in rootfs
+ # (stepping into rootfs-dbg sources needs image-combined-dbg.bbclass)
os.path.join(image.rootfs, base_libdir),
os.path.join(image.rootfs, libdir)
- ]
- return so_paths
+ ])
+ return list(so_paths)
def solib_search_path_str(self, image):
"""Return a : separated list of paths usable by GDB's set solib-search-path"""
--
2.55.0
next prev parent reply other threads:[~2026-09-06 21:03 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-06 21:01 [PATCH 0/9] devtool: ide-sdk: bug fixes, do_install-through-bitbake, NFS deploy prep AdrianF
2026-09-06 21:01 ` AdrianF [this message]
2026-09-06 21:02 ` [PATCH 2/9] oe-selftest: devtool ide-sdk: do not guess the slirp SSH port AdrianF
2026-09-06 21:19 ` Patchtest results for " patchtest
2026-09-06 21:02 ` [PATCH 3/9] devtool: ide-sdk: pre-select attach process with processFilter AdrianF
2026-09-06 21:02 ` [PATCH 4/9] oe-selftest: tinfoil: test prepared task runner AdrianF
2026-09-06 21:02 ` [PATCH 5/9] devtool: ide-sdk: run do_install through BitBake AdrianF
2026-09-06 21:02 ` [PATCH 6/9] oe-selftest: devtool ide-sdk: test install task AdrianF
2026-09-06 21:02 ` [PATCH 7/9] runqemu-export-rootfs: set PSEUDO_INCLUDE_PATHS for unfsd AdrianF
2026-09-06 21:02 ` [PATCH 8/9] devtool: deploy: make pseudo calls independent of bitbake.conf AdrianF
2026-09-06 21:02 ` [PATCH 9/9] devtool: deploy: remove dead files_list computation 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=20260906210307.2793974-2-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