aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'portage_with_autodep/bin/ebuild-helpers/prepstrip')
-rwxr-xr-xportage_with_autodep/bin/ebuild-helpers/prepstrip290
1 files changed, 209 insertions, 81 deletions
diff --git a/portage_with_autodep/bin/ebuild-helpers/prepstrip b/portage_with_autodep/bin/ebuild-helpers/prepstrip
index d25259d..85d5d6a 100755
--- a/portage_with_autodep/bin/ebuild-helpers/prepstrip
+++ b/portage_with_autodep/bin/ebuild-helpers/prepstrip
@@ -1,85 +1,153 @@
#!/bin/bash
-# Copyright 1999-2011 Gentoo Foundation
+# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/helper-functions.sh
+
+# avoid multiple calls to `has`. this creates things like:
+# FEATURES_foo=false
+# if "foo" is not in $FEATURES
+tf() { "$@" && echo true || echo false ; }
+exp_tf() {
+ local flag var=$1
+ shift
+ for flag in "$@" ; do
+ eval ${var}_${flag}=$(tf has ${flag} ${!var})
+ done
+}
+exp_tf FEATURES compressdebug installsources nostrip splitdebug
+exp_tf RESTRICT binchecks installsources strip
+
+[[ " ${FEATURES} " == *" force-prefix "* ]] || \
+ case "${EAPI}" in 0|1|2) EPREFIX= ED=${D} ;; esac
banner=false
SKIP_STRIP=false
-if has nostrip ${FEATURES} || \
- has strip ${RESTRICT}
-then
+if ${RESTRICT_strip} || ${FEATURES_nostrip} ; then
SKIP_STRIP=true
banner=true
- has installsources ${FEATURES} || exit 0
+ ${FEATURES_installsources} || exit 0
fi
-STRIP=${STRIP:-${CHOST}-strip}
-type -P -- ${STRIP} > /dev/null || STRIP=strip
-OBJCOPY=${OBJCOPY:-${CHOST}-objcopy}
-type -P -- ${OBJCOPY} > /dev/null || OBJCOPY=objcopy
+# look up the tools we might be using
+for t in STRIP:strip OBJCOPY:objcopy READELF:readelf ; do
+ v=${t%:*} # STRIP
+ t=${t#*:} # strip
+ eval ${v}=\"${!v:-${CHOST}-${t}}\"
+ type -P -- ${!v} >/dev/null || eval ${v}=${t}
+done
-# We'll leave out -R .note for now until we can check out the relevance
-# of the section when it has the ALLOC flag set on it ...
-export SAFE_STRIP_FLAGS="--strip-unneeded"
-export PORTAGE_STRIP_FLAGS=${PORTAGE_STRIP_FLAGS-${SAFE_STRIP_FLAGS} -R .comment}
-prepstrip_sources_dir=/usr/src/debug/${CATEGORY}/${PF}
+# Figure out what tool set we're using to strip stuff
+unset SAFE_STRIP_FLAGS DEF_STRIP_FLAGS SPLIT_STRIP_FLAGS
+case $(${STRIP} --version 2>/dev/null) in
+*elfutils*) # dev-libs/elfutils
+ # elfutils default behavior is always safe, so don't need to specify
+ # any flags at all
+ SAFE_STRIP_FLAGS=""
+ DEF_STRIP_FLAGS="--remove-comment"
+ SPLIT_STRIP_FLAGS="-f"
+ ;;
+*GNU*) # sys-devel/binutils
+ # We'll leave out -R .note for now until we can check out the relevance
+ # of the section when it has the ALLOC flag set on it ...
+ SAFE_STRIP_FLAGS="--strip-unneeded"
+ DEF_STRIP_FLAGS="-R .comment -R .GCC.command.line"
+ SPLIT_STRIP_FLAGS=
+ ;;
+esac
+: ${PORTAGE_STRIP_FLAGS=${SAFE_STRIP_FLAGS} ${DEF_STRIP_FLAGS}}
-if has installsources ${FEATURES} && ! type -P debugedit >/dev/null ; then
- ewarn "FEATURES=installsources is enabled but the debugedit binary could not"
- ewarn "be found. This feature will not work unless debugedit is installed!"
-fi
+prepstrip_sources_dir=${EPREFIX}/usr/src/debug/${CATEGORY}/${PF}
+
+type -P debugedit >/dev/null && debugedit_found=true || debugedit_found=false
+debugedit_warned=false
-unset ${!INODE_*}
+multijob_init
-inode_var_name() {
- if [[ $USERLAND = BSD ]] ; then
- stat -f 'INODE_%d_%i' "$1"
+# Setup $T filesystem layout that we care about.
+tmpdir="${T}/prepstrip"
+rm -rf "${tmpdir}"
+mkdir -p "${tmpdir}"/{inodes,splitdebug,sources}
+
+# Usage: inode_var_name: <file>
+inode_file_link() {
+ echo -n "${tmpdir}/inodes/"
+ if [[ ${USERLAND} == "BSD" ]] ; then
+ stat -f '%i' "$1"
else
- stat -c 'INODE_%d_%i' "$1"
+ stat -c '%i' "$1"
fi
}
+# Usage: save_elf_sources <elf>
save_elf_sources() {
- has installsources ${FEATURES} || return 0
- has installsources ${RESTRICT} && return 0
- type -P debugedit >/dev/null || return 0
+ ${FEATURES_installsources} || return 0
+ ${RESTRICT_installsources} && return 0
+ if ! ${debugedit_found} ; then
+ if ! ${debugedit_warned} ; then
+ debugedit_warned=true
+ ewarn "FEATURES=installsources is enabled but the debugedit binary could not"
+ ewarn "be found. This feature will not work unless debugedit is installed!"
+ fi
+ return 0
+ fi
local x=$1
- local inode=$(inode_var_name "$x")
- [[ -n ${!inode} ]] && return 0
- debugedit -b "${WORKDIR}" -d "${prepstrip_sources_dir}" \
- -l "${T}"/debug.sources "${x}"
+ [[ -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
+ # it later on in the save_elf_debug step.
+ buildid=$(debugedit -i \
+ -b "${WORKDIR}" \
+ -d "${prepstrip_sources_dir}" \
+ -l "${tmpdir}/sources/${x##*/}.${BASHPID}" \
+ "${x}")
}
+# Usage: save_elf_debug <elf> [splitdebug file]
save_elf_debug() {
- has splitdebug ${FEATURES} || return 0
+ ${FEATURES_splitdebug} || return 0
+ # NOTE: Debug files must be installed in
+ # ${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 y="${D}usr/lib/debug/${x:${#D}}.debug"
+ local splitdebug=$2
+ local y=${ED}usr/lib/debug/${x:${#D}}.debug
# dont save debug info twice
[[ ${x} == *".debug" ]] && return 0
- # this will recompute the build-id, but for now that's ok
- local buildid="$( type -P debugedit >/dev/null && debugedit -i "${x}" )"
-
- mkdir -p $(dirname "${y}")
+ mkdir -p "${y%/*}"
- local inode=$(inode_var_name "$x")
- if [[ -n ${!inode} ]] ; then
- ln "${D}usr/lib/debug/${!inode:${#D}}.debug" "$y"
+ local inode=$(inode_file_link "${x}")
+ if [[ -f ${inode} ]] ; then
+ ln "${inode}" "${y}"
else
- eval $inode=\$x
- ${OBJCOPY} --only-keep-debug "${x}" "${y}"
- ${OBJCOPY} --add-gnu-debuglink="${y}" "${x}"
- [[ -g ${x} ]] && chmod go-r "${y}"
- [[ -u ${x} ]] && chmod go-r "${y}"
- chmod a-x,o-w "${y}"
+ if [[ -n ${splitdebug} ]] ; then
+ mv "${splitdebug}" "${y}"
+ 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}"
+ fi
+ local args="a-x,o-w"
+ [[ -g ${x} || -u ${x} ]] && args+=",go-r"
+ chmod ${args} "${y}"
+ ln "${y}" "${inode}"
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} -x .note.gnu.build-id "${x}" 2>/dev/null \
+ | awk '$NF ~ /GNU/ { getline; printf $2$3$4$5; getline; print $2 }')
+ fi
if [[ -n ${buildid} ]] ; then
- local buildid_dir="${D}usr/lib/debug/.build-id/${buildid:0:2}"
+ local buildid_dir="${ED}usr/lib/debug/.build-id/${buildid:0:2}"
local buildid_file="${buildid_dir}/${buildid:2}"
mkdir -p "${buildid_dir}"
ln -s "../../${x:${#D}}.debug" "${buildid_file}.debug"
@@ -87,33 +155,78 @@ save_elf_debug() {
fi
}
+# Usage: process_elf <elf>
+process_elf() {
+ local x=$1 strip_flags=${*:2}
+
+ vecho " ${x:${#ED}}"
+ save_elf_sources "${x}"
+
+ if ${strip_this} ; then
+
+ # If two processes try to strip the same hardlink at the same
+ # time, it will cause one of them to lose the splitdebug info.
+ # So, use a lockfile to prevent interference (easily observed
+ # with dev-vcs/git which creates ~109 hardlinks to one file in
+ # /usr/libexec/git-core).
+ local lockfile=$(inode_file_link "${x}")_lockfile
+ if ! ln "${x}" "${lockfile}" ; then
+ while [[ -f ${lockfile} ]] ; do
+ sleep 1
+ done
+ unset lockfile
+ fi
+
+ # see if we can split & strip at the same time
+ if [[ -n ${SPLIT_STRIP_FLAGS} ]] ; then
+ local shortname="${x##*/}.debug"
+ local splitdebug="${tmpdir}/splitdebug/${shortname}.${BASHPID}"
+ ${STRIP} ${strip_flags} \
+ -f "${splitdebug}" \
+ -F "${shortname}" \
+ "${x}"
+ save_elf_debug "${x}" "${splitdebug}"
+ else
+ save_elf_debug "${x}"
+ ${STRIP} ${strip_flags} "${x}"
+ fi
+ [[ -n ${lockfile} ]] && rm -f "${lockfile}"
+ fi
+}
+
# The existance of the section .symtab tells us that a binary is stripped.
# We want to log already stripped binaries, as this may be a QA violation.
# They prevent us from getting the splitdebug data.
-if ! has binchecks ${RESTRICT} && \
- ! has strip ${RESTRICT} ; then
- log=$T/scanelf-already-stripped.log
+if ! ${RESTRICT_binchecks} && ! ${RESTRICT_strip} ; then
+ # We need to do the non-stripped scan serially first before we turn around
+ # and start stripping the files ourselves. The log parsing can be done in
+ # parallel though.
+ log=${tmpdir}/scanelf-already-stripped.log
+ scanelf -yqRBF '#k%F' -k '!.symtab' "$@" | sed -e "s#^${ED}##" > "${log}"
+ (
+ multijob_child_init
qa_var="QA_PRESTRIPPED_${ARCH/-/_}"
[[ -n ${!qa_var} ]] && QA_PRESTRIPPED="${!qa_var}"
- scanelf -yqRBF '#k%F' -k '!.symtab' "$@" | sed -e "s#^$D##" > "$log"
- if [[ -n $QA_PRESTRIPPED && -s $log && \
+ if [[ -n ${QA_PRESTRIPPED} && -s ${log} && \
${QA_STRICT_PRESTRIPPED-unset} = unset ]] ; then
shopts=$-
set -o noglob
- for x in $QA_PRESTRIPPED ; do
- sed -e "s#^${x#/}\$##" -i "$log"
+ for x in ${QA_PRESTRIPPED} ; do
+ sed -e "s#^${x#/}\$##" -i "${log}"
done
set +o noglob
- set -$shopts
+ set -${shopts}
fi
- sed -e "/^\$/d" -e "s#^#/#" -i "$log"
- if [[ -s $log ]] ; then
+ sed -e "/^\$/d" -e "s#^#/#" -i "${log}"
+ if [[ -s ${log} ]] ; then
vecho -e "\n"
eqawarn "QA Notice: Pre-stripped files found:"
- eqawarn "$(<"$log")"
+ eqawarn "$(<"${log}")"
else
- rm -f "$log"
+ rm -f "${log}"
fi
+ ) &
+ multijob_post_fork
fi
# Now we look for unstripped binaries.
@@ -126,8 +239,10 @@ do
banner=true
fi
- f=$(file "${x}") || continue
- [[ -z ${f} ]] && continue
+ (
+ multijob_child_init
+ f=$(file "${x}") || exit 0
+ [[ -z ${f} ]] && exit 0
if ! ${SKIP_STRIP} ; then
# The noglob funk is to support STRIP_MASK="/*/booga" and to keep
@@ -136,50 +251,61 @@ do
set -o noglob
strip_this=true
for m in $(eval echo ${STRIP_MASK}) ; do
- [[ /${x#${D}} == ${m} ]] && strip_this=false && break
+ [[ /${x#${ED}} == ${m} ]] && strip_this=false && break
done
set +o noglob
else
strip_this=false
fi
+ # In Prefix we are usually an unprivileged user, so we can't strip
+ # unwritable objects. Make them temporarily writable for the
+ # stripping.
+ was_not_writable=false
+ if [[ ! -w ${x} ]] ; then
+ was_not_writable=true
+ chmod u+w "${x}"
+ fi
+
# only split debug info for final linked objects
# or kernel modules as debuginfo for intermediatary
# files (think crt*.o from gcc/glibc) is useless and
# actually causes problems. install sources for all
# elf types though cause that stuff is good.
+ buildid=
if [[ ${f} == *"current ar archive"* ]] ; then
- vecho " ${x:${#D}}"
+ vecho " ${x:${#ED}}"
if ${strip_this} ; then
# hmm, can we split debug/sources for .a ?
${STRIP} -g "${x}"
fi
elif [[ ${f} == *"SB executable"* || ${f} == *"SB shared object"* ]] ; then
- vecho " ${x:${#D}}"
- save_elf_sources "${x}"
- if ${strip_this} ; then
- save_elf_debug "${x}"
- ${STRIP} ${PORTAGE_STRIP_FLAGS} "${x}"
- fi
+ process_elf "${x}" ${PORTAGE_STRIP_FLAGS}
elif [[ ${f} == *"SB relocatable"* ]] ; then
- vecho " ${x:${#D}}"
- save_elf_sources "${x}"
- if ${strip_this} ; then
- [[ ${x} == *.ko ]] && save_elf_debug "${x}"
- ${STRIP} ${SAFE_STRIP_FLAGS} "${x}"
- fi
+ process_elf "${x}" ${SAFE_STRIP_FLAGS}
fi
+
+ if ${was_not_writable} ; then
+ chmod u-w "${x}"
+ fi
+ ) &
+ multijob_post_fork
done
-if [[ -s ${T}/debug.sources ]] && \
- has installsources ${FEATURES} && \
- ! has installsources ${RESTRICT} && \
- type -P debugedit >/dev/null
+# With a bit more work, we could run the rsync processes below in
+# parallel, but not sure that'd be an overall improvement.
+multijob_finish
+
+cd "${tmpdir}"/sources/ && cat * > "${tmpdir}/debug.sources" 2>/dev/null
+if [[ -s ${tmpdir}/debug.sources ]] && \
+ ${FEATURES_installsources} && \
+ ! ${RESTRICT_installsources} && \
+ ${debugedit_found}
then
vecho "installsources: rsyncing source files"
[[ -d ${D}${prepstrip_sources_dir} ]] || mkdir -p "${D}${prepstrip_sources_dir}"
- grep -zv '/<[^/>]*>$' "${T}"/debug.sources | \
+ grep -zv '/<[^/>]*>$' "${tmpdir}"/debug.sources | \
(cd "${WORKDIR}"; LANG=C sort -z -u | \
rsync -tL0 --files-from=- "${WORKDIR}/" "${D}${prepstrip_sources_dir}/" )
@@ -188,6 +314,8 @@ then
# https://bugzilla.redhat.com/show_bug.cgi?id=444310
while read -r -d $'\0' emptydir
do
- >> "$emptydir"/.keepdir
+ >> "${emptydir}"/.keepdir
done < <(find "${D}${prepstrip_sources_dir}/" -type d -empty -print0)
fi
+
+rm -rf "${tmpdir}"