fi
local x=$1
- [[ -f $(inode_file_link "${x}") ]] && return 0
# since we're editing the ELF here, we should recompute the build-id
# (the -i flag below). save that output so we don't need to recompute
# twice in this path) in order for gdb's debug-file-directory
# lookup to work correctly.
local x=$1
- local splitdebug=$2
+ local inode_debug=$2
+ local splitdebug=$3
local y=${ED}usr/lib/debug/${x:${#D}}.debug
# dont save debug info twice
mkdir -p "${y%/*}"
- local inode=$(inode_file_link "${x}")
- if [[ -f ${inode} ]] ; then
- ln "${inode}" "${y}"
+ if [ -f "${inode_debug}" ] ; then
+ ln "${inode_debug}" "${y}" || die "ln failed unexpectedly"
else
if [[ -n ${splitdebug} ]] ; then
mv "${splitdebug}" "${y}"
local args="a-x,o-w"
[[ -g ${x} || -u ${x} ]] && args+=",go-r"
chmod ${args} "${y}"
- ln "${y}" "${inode}"
+ ln "${y}" "${inode_debug}" || die "ln failed unexpectedly"
fi
# if we don't already have build-id from debugedit, look it up
# Usage: process_elf <elf>
process_elf() {
- local x=$1 strip_flags=${*:2}
+ local x=$1 inode_link=$2 strip_flags=${*:3}
+ local already_stripped lockfile
__vecho " ${x:${#ED}}"
# So, use a lockfile to prevent interference (easily observed with
# dev-vcs/git which creates ~111 hardlinks to one file in
# /usr/libexec/git-core).
- local lockfile=$(inode_file_link "${x}")_lockfile
- if ! ln "${x}" "${lockfile}" 2>/dev/null ; then
+ lockfile=${inode_link}_lockfile
+ if ! ln "${inode_link}" "${lockfile}" 2>/dev/null ; then
while [[ -f ${lockfile} ]] ; do
sleep 1
done
unset lockfile
fi
- save_elf_sources "${x}"
+ [ -f "${inode_link}_stripped" ] && already_stripped=true || already_stripped=false
+
+ ${already_stripped} || save_elf_sources "${x}"
if ${strip_this} ; then
if [[ -n ${SPLIT_STRIP_FLAGS} ]] ; then
local shortname="${x##*/}.debug"
local splitdebug="${tmpdir}/splitdebug/${shortname}.${BASHPID}"
+ ${already_stripped} || \
${STRIP} ${strip_flags} \
-f "${splitdebug}" \
-F "${shortname}" \
"${x}"
- save_elf_debug "${x}" "${splitdebug}"
+ save_elf_debug "${x}" "${inode_link}_debug" "${splitdebug}"
else
- save_elf_debug "${x}"
+ save_elf_debug "${x}" "${inode_link}_debug"
+ ${already_stripped} || \
${STRIP} ${strip_flags} "${x}"
fi
fi
+ if ${already_stripped} ; then
+ rm -f "${x}" || die "rm failed unexpectedly"
+ ln "${inode_link}_stripped" "${x}" || die "ln failed unexpectedly"
+ else
+ ln "${x}" "${inode_link}_stripped" || die "ln failed unexpectedly"
+ fi
+
[[ -n ${lockfile} ]] && rm -f "${lockfile}"
}
__multijob_post_fork
fi
+# Since strip creates a new inode, we need to know the initial set of
+# inodes in advance, so that we can avoid interference due to trying
+# to strip the same (hardlinked) file multiple times in parallel.
+# See bug #421099.
+while read -r x ; do
+ inode_link=$(inode_file_link "${x}")
+ echo "${x}" >> "${inode_link}" || die "echo failed"
+done < <(
+ scanelf -yqRBF '#k%F' -k '.symtab' "$@"
+ find "$@" -type f ! -type l -name '*.a'
+)
+
# Now we look for unstripped binaries.
-for x in \
- $(scanelf -yqRBF '#k%F' -k '.symtab' "$@") \
- $(find "$@" -type f -name '*.a')
+cd "${tmpdir}/inodes" || die "cd failed"
+for inode_link in * ; do
+while read -r x
do
+
if ! ${banner} ; then
__vecho "strip: ${STRIP} ${PORTAGE_STRIP_FLAGS}"
banner=true
${STRIP} -g "${x}"
fi
elif [[ ${f} == *"SB executable"* || ${f} == *"SB shared object"* ]] ; then
- process_elf "${x}" ${PORTAGE_STRIP_FLAGS}
+ process_elf "${x}" "${inode_link}" ${PORTAGE_STRIP_FLAGS}
elif [[ ${f} == *"SB relocatable"* ]] ; then
- process_elf "${x}" ${SAFE_STRIP_FLAGS}
+ process_elf "${x}" "${inode_link}" ${SAFE_STRIP_FLAGS}
fi
if ${was_not_writable} ; then
fi
) &
__multijob_post_fork
+
+done < "${inode_link}"
done
# With a bit more work, we could run the rsync processes below in