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