Skip to content

Commit 3a7f657

Browse files
committed
fix(debuginfo): find split debug files via NIX_DEBUG_INFO_DIRS
find_debug_file() only searched the /usr/lib/debug tree, which does not exist on NixOS: Nix ships separate debug outputs under their own store paths. Factor the build-id .build-id/xx/yyyy.debug probe into try_buildid_dir() and honour NIX_DEBUG_INFO_DIRS -- the established colon-separated convention also used by the nixpkgs gdb/lldb wrappers -- so split debug info resolves inside the dev-shell.
1 parent 4fa2dc3 commit 3a7f657

1 file changed

Lines changed: 65 additions & 8 deletions

File tree

coregrind/m_debuginfo/readelf.c

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,37 @@ DiImage* find_debug_file_debuginfod( const HChar* objpath,
15001500
}
15011501
#endif
15021502

1503+
/* Try one directory as a root for the standard .build-id/xx/yyyy.debug
1504+
layout. On success, returns the opened image and sets *debugpath_out
1505+
to a freshly allocated path (which the caller owns); on failure,
1506+
returns NULL and leaves *debugpath_out untouched. */
1507+
static
1508+
DiImage* try_buildid_dir( const HChar* dir, SizeT dirlen,
1509+
const HChar* buildid, Bool rel_ok,
1510+
HChar** debugpath_out )
1511+
{
1512+
DiImage* dimg;
1513+
HChar* debugpath;
1514+
1515+
if (dirlen == 0)
1516+
return NULL;
1517+
1518+
debugpath = ML_(dinfo_zalloc)("di.tbid.1",
1519+
dirlen + VG_(strlen)(buildid) + 19);
1520+
VG_(memcpy)(debugpath, dir, dirlen);
1521+
VG_(sprintf)(debugpath + dirlen, "/.build-id/%c%c/%s.debug",
1522+
buildid[0], buildid[1], buildid + 2);
1523+
1524+
dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1525+
if (dimg == NULL) {
1526+
ML_(dinfo_free)(debugpath);
1527+
return NULL;
1528+
}
1529+
1530+
*debugpath_out = debugpath;
1531+
return dimg;
1532+
}
1533+
15031534
/* Try to find a separate debug file for a given object file. If
15041535
found, return its DiImage, which should be freed by the caller. If
15051536
|buildid| is non-NULL, then a debug object matching it is
@@ -1519,16 +1550,42 @@ DiImage* find_debug_file( struct _DebugInfo* di,
15191550
HChar* debugpath = NULL; /* where we found it */
15201551

15211552
if (buildid != NULL) {
1522-
debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1523-
VG_(strlen)(buildid) + 33);
1553+
/* Nix packages ship separate debug outputs under their own store
1554+
paths, never under /usr/lib/debug (which doesn't exist on
1555+
NixOS). NIX_DEBUG_INFO_DIRS is the established convention (also
1556+
honoured by gdb/lldb via nixpkgs wrappers) for a colon-separated
1557+
list of trees that mirror the standard .build-id/xx/yyyy.debug
1558+
layout; try each, then --extra-debuginfo-path, before falling
1559+
back to the FHS path. */
1560+
const HChar* nix_dirs = VG_(getenv)("NIX_DEBUG_INFO_DIRS");
1561+
const HChar* p = nix_dirs;
1562+
1563+
while (dimg == NULL && p != NULL && *p != 0) {
1564+
const HChar* colon = VG_(strchr)(p, ':');
1565+
SizeT dirlen = colon ? (SizeT)(colon - p) : VG_(strlen)(p);
1566+
1567+
dimg = try_buildid_dir(p, dirlen, buildid, rel_ok, &debugpath);
1568+
1569+
p = colon ? colon + 1 : p + dirlen;
1570+
}
15241571

1525-
VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1526-
buildid[0], buildid[1], buildid + 2);
1572+
if (dimg == NULL && extrapath != NULL) {
1573+
dimg = try_buildid_dir(extrapath, VG_(strlen)(extrapath),
1574+
buildid, rel_ok, &debugpath);
1575+
}
1576+
1577+
if (dimg == NULL) {
1578+
debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1579+
VG_(strlen)(buildid) + 33);
15271580

1528-
dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1529-
if (!dimg) {
1530-
ML_(dinfo_free)(debugpath);
1531-
debugpath = NULL;
1581+
VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1582+
buildid[0], buildid[1], buildid + 2);
1583+
1584+
dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1585+
if (!dimg) {
1586+
ML_(dinfo_free)(debugpath);
1587+
debugpath = NULL;
1588+
}
15321589
}
15331590
}
15341591

0 commit comments

Comments
 (0)