Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 820107 - sys-apps/portage FEATURES=splitdebug does not mix well with hard links
Summary: sys-apps/portage FEATURES=splitdebug does not mix well with hard links
Status: RESOLVED FIXED
Alias: None
Product: Portage Development
Classification: Unclassified
Component: Core (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Portage team
URL:
Whiteboard:
Keywords: InVCS
Depends on: 823798
Blocks:
  Show dependency tree
 
Reported: 2021-10-25 01:09 UTC by Mike Gilbert
Modified: 2022-04-11 20:23 UTC (History)
3 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Gilbert gentoo-dev 2021-10-25 01:09:33 UTC
splitdebug causes Portage to move symbols to debug files under /usr/lib/debug/path/to/program. It then adds a .gnu_debuglink section to any affected binaries. This section contains the basename of the file installed under /usr/lib/debug.

When a package installs multiple hard links to the same binary that span multiple directories, splitdebug behaves strangely. Since there is only one actual ELF file on disk, .gnu_debugpath ends up being incorrect for all but one of the installed hard links.

A great example of this is dev-vcs/git, which installs /usr/bin/git along with over a hundred hard links under /usr/libexec/git-core. Sometimes you get lucky and .gnu_debuglink gets set to "git.debug". Other times, you get unlucky and it gets set to something like "git-diff-tree.debug".

The only solution I can think of is to have Portage break the hard links when splitdebug is enabled, and instead install separate copies of the file with appropriate .gnu_debuglink sections.
Comment 1 Mike Gilbert gentoo-dev 2021-10-25 01:30:10 UTC
Some alternate solutions from #gentoo-toolchain:

- Break hard links only if they reside in separate directories.

- Install a copy of the same .debug file under /usr/lib/debug/${path} for each path in which a hard link will be installed.
Comment 2 Mike Gilbert gentoo-dev 2021-10-25 01:32:29 UTC
(In reply to Mike Gilbert from comment #1)
> - Install a copy of the same .debug file under /usr/lib/debug/${path} for
> each path in which a hard link will be installed.

Or this could be optimized by installing hard links to the same .debug file for each path.
Comment 3 Zac Medico gentoo-dev 2021-10-25 01:49:21 UTC
(In reply to Mike Gilbert from comment #2)
> (In reply to Mike Gilbert from comment #1)
> > - Install a copy of the same .debug file under /usr/lib/debug/${path} for
> > each path in which a hard link will be installed.
> 
> Or this could be optimized by installing hard links to the same .debug file
> for each path.

I think it's supposed to do that in the bin/estrip save_elf_debug function, around here, but maybe it's buggy somehow:

>	if [ -f "${inode_debug}" ] ; then
>		ln "${inode_debug}" "${y}" || die "ln failed unexpectedly"
Comment 4 Zac Medico gentoo-dev 2021-10-25 02:47:26 UTC
Note that the process_elf function has a lockfile for each inode to guard against the function running multiple times on the same inode at once, which is *supposed* to ensure correct behavior despite process_elf being launched via a multiprocessing loop.
Comment 5 Mike Gilbert gentoo-dev 2021-10-25 03:12:27 UTC
Ah, you're right. I think estrip is smarter than I assumed. It does create hard links, but not the ones that matter.

To better illustrate the problem in dev-vcs/git, here's what happened on my most recent install:

> % objdump -s -j .gnu_debuglink /usr/bin/git             
> 
> /usr/bin/git:     file format elf64-x86-64
> 
> Contents of section .gnu_debuglink:
>  0000 6769742d 6164642e 64656275 67000000  git-add.debug...
>  0010 ae8f7879                             ..xy            

Given this, gdb will attempt to load /usr/lib/debug/usr/bin/git-add.debug, which does not exist.

> % ls -l /usr/lib/debug/usr/bin/git-add.debug             
> ls: cannot access '/usr/lib/debug/usr/bin/git-add.debug': No such file or directory
> 
> % gdb /usr/bin/git
> GNU gdb (Gentoo 11.1 vanilla) 11.1
> ...
> Reading symbols from /usr/bin/git...
> (No debugging symbols found in /usr/bin/git)
Comment 6 Mike Gilbert gentoo-dev 2021-10-25 05:04:41 UTC
I have a working local patch for estrip, just need to clean it up a bit.
Comment 7 Larry the Git Cow gentoo-dev 2021-11-01 17:32:14 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/proj/portage.git/commit/?id=84206c6200eb003314cf4f2d640bf73f04654012

commit 84206c6200eb003314cf4f2d640bf73f04654012
Author:     Mike Gilbert <floppym@gentoo.org>
AuthorDate: 2021-10-25 15:30:08 +0000
Commit:     Mike Gilbert <floppym@gentoo.org>
CommitDate: 2021-10-31 18:15:27 +0000

    estrip: rework hard link logic in save_elf_debug
    
    GDB loads debug files based on the file name given in the .gnu_debuglink
    section, prepended with /usr/lib/debug/${dirname}, where dirname is the
    absolute path to the parent directory of the binary being executed.
    
    For each unique inode as input, we need a link to the debug file with
    the GNU debuglink as its basename. A link to the debug file should exist
    for each directory in which the input inode exists.
    
    The debug link names should be based on the .gnu_debuglink value instead
    of the name of the file we are processing as input.
    
    The .gnu_debuglink value is based on the name of the first link
    processed for each inode. We save this value as a symlink, and then read
    it back as we process subsequent links.
    
    For example, given the following input:
    
    INODE PATH
        1 /usr/bin/git
        1 /usr/libexec/git-core/git-add
        2 /usr/bin/git-shell
        2 /usr/libexec/git-core/git-shell
    
    We generate the following inodes for the debug files:
    
    INODE DEBUGLINK
        3 git.debug
        4 git-shell.debug
    
    We should generate the following links:
    
    INODE PATH
        3 /usr/lib/debug/usr/bin/git.debug
        3 /usr/lib/debug/usr/libexec/git-core/git.debug
        4 /usr/bin/debug/usr/bin/git-shell.debug
        4 /usr/bin/debug/usr/libexec/git-core/git-shell.debug
    
    The previous code would have generated this broken output:
    
    INODE PATH
        3 /usr/lib/debug/usr/bin/git.debug
        3 /usr/lib/debug/usr/libexec/git-core/git-add.debug (*)
        4 /usr/bin/debug/usr/bin/git-shell.debug
        4 /usr/bin/debug/usr/libexec/git-core/git-shell.debug
    
    (*) This link has the wrong name.
    
    Bug: https://bugs.gentoo.org/820107
    Signed-off-by: Mike Gilbert <floppym@gentoo.org>

 bin/estrip | 60 +++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 21 deletions(-)
Comment 8 Mike Gilbert gentoo-dev 2022-04-11 20:23:28 UTC
Released in portage-3.0.29.