diff options
author | Mike Gilbert <floppym@gentoo.org> | 2021-10-25 11:30:08 -0400 |
---|---|---|
committer | Mike Gilbert <floppym@gentoo.org> | 2021-10-31 14:15:27 -0400 |
commit | 84206c6200eb003314cf4f2d640bf73f04654012 (patch) | |
tree | e1bc20168b1a8cab8b3694bc00a699d59f86b0ed | |
parent | .github: test against Python 3.10 final (diff) | |
download | portage-84206c6200eb003314cf4f2d640bf73f04654012.tar.gz portage-84206c6200eb003314cf4f2d640bf73f04654012.tar.bz2 portage-84206c6200eb003314cf4f2d640bf73f04654012.zip |
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>
-rwxr-xr-x | bin/estrip | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/bin/estrip b/bin/estrip index abe523fff..e33977091 100755 --- a/bin/estrip +++ b/bin/estrip @@ -189,7 +189,7 @@ save_elf_sources() { "${x}") } -# Usage: save_elf_debug <elf> [splitdebug file] +# Usage: save_elf_debug <src> <inode_debug> [splitdebug] save_elf_debug() { ${FEATURES_splitdebug} || return 0 ${PORTAGE_RESTRICT_splitdebug} && return 0 @@ -198,49 +198,67 @@ save_elf_debug() { # ${EPREFIX}/usr/lib/debug/${EPREFIX} (note that ${EPREFIX} occurs # twice in this path) in order for gdb's debug-file-directory # lookup to work correctly. - local x=$1 - local inode_debug=$2 - local splitdebug=$3 - local d_noslash=${D%/} - local y=${ED%/}/usr/lib/debug/${x:${#d_noslash}}.debug + local src=$1 # File from which we extract symbols. + local inode_debug=$2 # Temp path for hard link tracking + local splitdebug=$3 # Existing debug file optionally created by eu-strip in parent function - # dont save debug info twice - [[ ${x} == *".debug" ]] && return 0 + # Source paths + local src_basename=${src##*/} + local src_dirname=${src%/*} - mkdir -p "${y%/*}" + # Destination paths + local dst_dirname=${ED%/}/usr/lib/debug/${src_dirname#${D%/}/} + local dst_basename dst - if [ -f "${inode_debug}" ] ; then - ln "${inode_debug}" "${y}" || die "ln failed unexpectedly" + # dont save debug info twice + [[ ${src} == *".debug" ]] && return 0 + + mkdir -p "${dst_dirname}" || die + + if [[ -L ${inode_debug} ]] ; then + # We already created a debug file for this inode. + # Read back the file name, and create another hard link if necessary. + dst_basename=$(readlink "${inode_debug}") || die + dst_basename=${dst_basename##*/} + dst=${dst_dirname}/${dst_basename} + if [[ ! -e ${dst} ]]; then + ln -L "${inode_debug}" "${dst}" || die + fi else + dst_basename=${src_basename}.debug + dst=${dst_dirname}/${dst_basename} if [[ -n ${splitdebug} ]] ; then - mv "${splitdebug}" "${y}" + mv "${splitdebug}" "${dst}" else local objcopy_flags="--only-keep-debug" ${FEATURES_compressdebug} && objcopy_flags+=" --compress-debug-sections" - ${OBJCOPY} ${objcopy_flags} "${x}" "${y}" - ${OBJCOPY} --add-gnu-debuglink="${y}" "${x}" + ${OBJCOPY} ${objcopy_flags} "${src}" "${dst}" && + ${OBJCOPY} --add-gnu-debuglink="${dst}" "${src}" fi # Only do the following if the debug file was # successfully created (see bug #446774). - if [ $? -eq 0 ] ; then + if [[ $? -eq 0 ]] ; then local args="a-x,o-w" - [[ -g ${x} || -u ${x} ]] && args+=",go-r" - chmod ${args} "${y}" - ln "${y}" "${inode_debug}" || die "ln failed unexpectedly" + [[ -g ${src} || -u ${src} ]] && args+=",go-r" + chmod ${args} "${dst}" + # symlink so we can read the name back. + ln -s "${dst}" "${inode_debug}" || die fi fi # if we don't already have build-id from debugedit, look it up if [[ -z ${buildid} ]] ; then # convert the readelf output to something useful - buildid=$(${READELF} -n "${x}" 2>/dev/null | awk '/Build ID:/{ print $NF; exit }') + buildid=$(${READELF} -n "${src}" 2>/dev/null | awk '/Build ID:/{ print $NF; exit }') fi if [[ -n ${buildid} ]] ; then local buildid_dir="${ED%/}/usr/lib/debug/.build-id/${buildid:0:2}" local buildid_file="${buildid_dir}/${buildid:2}" + local src_buildid_rel="../../../../../${src#${ED%/}/}" + local dst_buildid_rel="../../${dst#${ED%/}/usr/lib/debug/}" mkdir -p "${buildid_dir}" - [ -L "${buildid_file}".debug ] || ln -s "../../${x:$((${#d_noslash} + 1))}.debug" "${buildid_file}.debug" - [ -L "${buildid_file}" ] || ln -s "/${x:$((${#d_noslash} + 1))}" "${buildid_file}" + [[ -L "${buildid_file}".debug ]] || ln -s "${dst_buildid_rel}" "${buildid_file}.debug" + [[ -L "${buildid_file}" ]] || ln -s "${src_buildid_rel}" "${buildid_file}" fi } |