diff options
Diffstat (limited to 'portage_with_autodep/bin/ebuild-helpers/prepstrip')
-rwxr-xr-x | portage_with_autodep/bin/ebuild-helpers/prepstrip | 290 |
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}" |