Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: "Michał Górny" <mgorny@g.o>, Mike Frysinger <vapier@g.o>
Subject: [gentoo-portage-dev] [PATCH 2/7] Disarm prepstrip & prepallstrip
Date: Sun, 25 Mar 2018 20:32:19
Message-Id: 20180325202826.7827-3-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 0/7] Add dostrip for EAPI 7 by Zac Medico
1 From: Michał Górny <mgorny@g.o>
2
3 Move stripping logic to a new estrip helper (that is not exposed
4 to ebuilds) and make prepstrip & prepallstrip do nothing.
5 ---
6 bin/ebuild-helpers/prepallstrip | 11 +-
7 bin/ebuild-helpers/prepstrip | 387 +--------------------------------------
8 bin/estrip | 390 ++++++++++++++++++++++++++++++++++++++++
9 bin/misc-functions.sh | 4 +-
10 4 files changed, 400 insertions(+), 392 deletions(-)
11 create mode 100755 bin/estrip
12
13 diff --git a/bin/ebuild-helpers/prepallstrip b/bin/ebuild-helpers/prepallstrip
14 index 59fa7cc61..4c6d47bb2 100755
15 --- a/bin/ebuild-helpers/prepallstrip
16 +++ b/bin/ebuild-helpers/prepallstrip
17 @@ -1,11 +1,8 @@
18 #!/bin/bash
19 -# Copyright 1999-2012 Gentoo Foundation
20 +# Copyright 1999-2018 Gentoo Foundation
21 # Distributed under the terms of the GNU General Public License v2
22
23 -source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
24 +# Note: this really does nothing these days. It's going to be banned
25 +# when the last consumers are gone.
26
27 -if ! ___eapi_has_prefix_variables; then
28 - ED=${D}
29 -fi
30 -
31 -exec prepstrip "${ED}"
32 +exit 0
33 diff --git a/bin/ebuild-helpers/prepstrip b/bin/ebuild-helpers/prepstrip
34 index 74ab52c5b..4c6d47bb2 100755
35 --- a/bin/ebuild-helpers/prepstrip
36 +++ b/bin/ebuild-helpers/prepstrip
37 @@ -2,388 +2,7 @@
38 # Copyright 1999-2018 Gentoo Foundation
39 # Distributed under the terms of the GNU General Public License v2
40
41 -source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
42 +# Note: this really does nothing these days. It's going to be banned
43 +# when the last consumers are gone.
44
45 -# avoid multiple calls to `has`. this creates things like:
46 -# FEATURES_foo=false
47 -# if "foo" is not in $FEATURES
48 -tf() { "$@" && echo true || echo false ; }
49 -exp_tf() {
50 - local flag var=$1
51 - shift
52 - for flag in "$@" ; do
53 - eval ${var}_${flag}=$(tf has ${flag} ${!var})
54 - done
55 -}
56 -exp_tf FEATURES compressdebug installsources nostrip splitdebug xattr
57 -exp_tf RESTRICT binchecks installsources splitdebug strip
58 -
59 -if ! ___eapi_has_prefix_variables; then
60 - EPREFIX= ED=${D}
61 -fi
62 -
63 -banner=false
64 -SKIP_STRIP=false
65 -if ${RESTRICT_strip} || ${FEATURES_nostrip} ; then
66 - SKIP_STRIP=true
67 - banner=true
68 - ${FEATURES_installsources} || exit 0
69 -fi
70 -
71 -PRESERVE_XATTR=false
72 -if [[ ${KERNEL} == linux ]] && ${FEATURES_xattr} ; then
73 - PRESERVE_XATTR=true
74 - if type -P getfattr >/dev/null && type -P setfattr >/dev/null ; then
75 - dump_xattrs() {
76 - getfattr -d -m - --absolute-names "$1"
77 - }
78 - restore_xattrs() {
79 - setfattr --restore=-
80 - }
81 - else
82 - dump_xattrs() {
83 - PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
84 - "${PORTAGE_PYTHON:-/usr/bin/python}" \
85 - "${PORTAGE_BIN_PATH}/xattr-helper.py" --dump < <(echo -n "$1")
86 - }
87 - restore_xattrs() {
88 - PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
89 - "${PORTAGE_PYTHON:-/usr/bin/python}" \
90 - "${PORTAGE_BIN_PATH}/xattr-helper.py" --restore
91 - }
92 - fi
93 -fi
94 -
95 -# look up the tools we might be using
96 -for t in STRIP:strip OBJCOPY:objcopy READELF:readelf ; do
97 - v=${t%:*} # STRIP
98 - t=${t#*:} # strip
99 - eval ${v}=\"${!v:-${CHOST}-${t}}\"
100 - type -P -- ${!v} >/dev/null || eval ${v}=${t}
101 -done
102 -
103 -# Figure out what tool set we're using to strip stuff
104 -unset SAFE_STRIP_FLAGS DEF_STRIP_FLAGS SPLIT_STRIP_FLAGS
105 -case $(${STRIP} --version 2>/dev/null) in
106 -*elfutils*) # dev-libs/elfutils
107 - # elfutils default behavior is always safe, so don't need to specify
108 - # any flags at all
109 - SAFE_STRIP_FLAGS=""
110 - DEF_STRIP_FLAGS="--remove-comment"
111 - SPLIT_STRIP_FLAGS="-f"
112 - ;;
113 -*GNU*) # sys-devel/binutils
114 - # We'll leave out -R .note for now until we can check out the relevance
115 - # of the section when it has the ALLOC flag set on it ...
116 - SAFE_STRIP_FLAGS="--strip-unneeded"
117 - DEF_STRIP_FLAGS="-R .comment -R .GCC.command.line -R .note.gnu.gold-version"
118 - SPLIT_STRIP_FLAGS=
119 - ;;
120 -esac
121 -: ${PORTAGE_STRIP_FLAGS=${SAFE_STRIP_FLAGS} ${DEF_STRIP_FLAGS}}
122 -
123 -prepstrip_sources_dir=${EPREFIX}/usr/src/debug/${CATEGORY}/${PF}
124 -
125 -debugedit=$(type -P debugedit)
126 -if [[ -z ${debugedit} ]]; then
127 - debugedit_paths=(
128 - "${EPREFIX}/usr/libexec/rpm/debugedit"
129 - )
130 - for x in "${debugedit_paths[@]}"; do
131 - if [[ -x ${x} ]]; then
132 - debugedit=${x}
133 - break
134 - fi
135 - done
136 -fi
137 -[[ ${debugedit} ]] && debugedit_found=true || debugedit_found=false
138 -debugedit_warned=false
139 -
140 -# Setup $T filesystem layout that we care about.
141 -tmpdir="${T}/prepstrip"
142 -rm -rf "${tmpdir}"
143 -mkdir -p "${tmpdir}"/{inodes,splitdebug,sources}
144 -
145 -# Usage: save_elf_sources <elf>
146 -save_elf_sources() {
147 - ${FEATURES_installsources} || return 0
148 - ${RESTRICT_installsources} && return 0
149 - if ! ${debugedit_found} ; then
150 - if ! ${debugedit_warned} ; then
151 - debugedit_warned=true
152 - ewarn "FEATURES=installsources is enabled but the debugedit binary could not be"
153 - ewarn "found. This feature will not work unless debugedit or rpm is installed!"
154 - fi
155 - return 0
156 - fi
157 -
158 - local x=$1
159 -
160 - # since we're editing the ELF here, we should recompute the build-id
161 - # (the -i flag below). save that output so we don't need to recompute
162 - # it later on in the save_elf_debug step.
163 - buildid=$("${debugedit}" -i \
164 - -b "${WORKDIR}" \
165 - -d "${prepstrip_sources_dir}" \
166 - -l "${tmpdir}/sources/${x##*/}.${BASHPID:-$(__bashpid)}" \
167 - "${x}")
168 -}
169 -
170 -# Usage: save_elf_debug <elf> [splitdebug file]
171 -save_elf_debug() {
172 - ${FEATURES_splitdebug} || return 0
173 - ${RESTRICT_splitdebug} && return 0
174 -
175 - # NOTE: Debug files must be installed in
176 - # ${EPREFIX}/usr/lib/debug/${EPREFIX} (note that ${EPREFIX} occurs
177 - # twice in this path) in order for gdb's debug-file-directory
178 - # lookup to work correctly.
179 - local x=$1
180 - local inode_debug=$2
181 - local splitdebug=$3
182 - local d_noslash=${D%/}
183 - local y=${ED%/}/usr/lib/debug/${x:${#d_noslash}}.debug
184 -
185 - # dont save debug info twice
186 - [[ ${x} == *".debug" ]] && return 0
187 -
188 - mkdir -p "${y%/*}"
189 -
190 - if [ -f "${inode_debug}" ] ; then
191 - ln "${inode_debug}" "${y}" || die "ln failed unexpectedly"
192 - else
193 - if [[ -n ${splitdebug} ]] ; then
194 - mv "${splitdebug}" "${y}"
195 - else
196 - local objcopy_flags="--only-keep-debug"
197 - ${FEATURES_compressdebug} && objcopy_flags+=" --compress-debug-sections"
198 - ${OBJCOPY} ${objcopy_flags} "${x}" "${y}"
199 - ${OBJCOPY} --add-gnu-debuglink="${y}" "${x}"
200 - fi
201 - # Only do the following if the debug file was
202 - # successfully created (see bug #446774).
203 - if [ $? -eq 0 ] ; then
204 - local args="a-x,o-w"
205 - [[ -g ${x} || -u ${x} ]] && args+=",go-r"
206 - chmod ${args} "${y}"
207 - ln "${y}" "${inode_debug}" || die "ln failed unexpectedly"
208 - fi
209 - fi
210 -
211 - # if we don't already have build-id from debugedit, look it up
212 - if [[ -z ${buildid} ]] ; then
213 - # convert the readelf output to something useful
214 - buildid=$(${READELF} -n "${x}" 2>/dev/null | awk '/Build ID:/{ print $NF; exit }')
215 - fi
216 - if [[ -n ${buildid} ]] ; then
217 - local buildid_dir="${ED%/}/usr/lib/debug/.build-id/${buildid:0:2}"
218 - local buildid_file="${buildid_dir}/${buildid:2}"
219 - mkdir -p "${buildid_dir}"
220 - [ -L "${buildid_file}".debug ] || ln -s "../../${x:${#D}}.debug" "${buildid_file}.debug"
221 - [ -L "${buildid_file}" ] || ln -s "/${x:${#D}}" "${buildid_file}"
222 - fi
223 -}
224 -
225 -# Usage: process_elf <elf>
226 -process_elf() {
227 - local x=$1 inode_link=$2 strip_flags=${*:3}
228 - local already_stripped lockfile xt_data
229 -
230 - __vecho " ${x:${#ED}}"
231 -
232 - # If two processes try to debugedit or strip the same hardlink at the
233 - # same time, it may corrupt files or cause loss of splitdebug info.
234 - # So, use a lockfile to prevent interference (easily observed with
235 - # dev-vcs/git which creates ~111 hardlinks to one file in
236 - # /usr/libexec/git-core).
237 - lockfile=${inode_link}_lockfile
238 - if ! ln "${inode_link}" "${lockfile}" 2>/dev/null ; then
239 - while [[ -f ${lockfile} ]] ; do
240 - sleep 1
241 - done
242 - unset lockfile
243 - fi
244 -
245 - [ -f "${inode_link}_stripped" ] && already_stripped=true || already_stripped=false
246 -
247 - if ! ${already_stripped} ; then
248 - if ${PRESERVE_XATTR} ; then
249 - xt_data=$(dump_xattrs "${x}")
250 - fi
251 - save_elf_sources "${x}"
252 - fi
253 -
254 - if ${strip_this} ; then
255 -
256 - # see if we can split & strip at the same time
257 - if [[ -n ${SPLIT_STRIP_FLAGS} ]] ; then
258 - local shortname="${x##*/}.debug"
259 - local splitdebug="${tmpdir}/splitdebug/${shortname}.${BASHPID:-$(__bashpid)}"
260 - ${already_stripped} || \
261 - ${STRIP} ${strip_flags} \
262 - -f "${splitdebug}" \
263 - -F "${shortname}" \
264 - "${x}"
265 - save_elf_debug "${x}" "${inode_link}_debug" "${splitdebug}"
266 - else
267 - save_elf_debug "${x}" "${inode_link}_debug"
268 - ${already_stripped} || \
269 - ${STRIP} ${strip_flags} "${x}"
270 - fi
271 - fi
272 -
273 - if ${already_stripped} ; then
274 - rm -f "${x}" || die "rm failed unexpectedly"
275 - ln "${inode_link}_stripped" "${x}" || die "ln failed unexpectedly"
276 - else
277 - ln "${x}" "${inode_link}_stripped" || die "ln failed unexpectedly"
278 - if [[ ${xt_data} ]] ; then
279 - restore_xattrs <<< "${xt_data}"
280 - fi
281 - fi
282 -
283 - [[ -n ${lockfile} ]] && rm -f "${lockfile}"
284 -}
285 -
286 -# The existance of the section .symtab tells us that a binary is stripped.
287 -# We want to log already stripped binaries, as this may be a QA violation.
288 -# They prevent us from getting the splitdebug data.
289 -if ! ${RESTRICT_binchecks} && ! ${RESTRICT_strip} ; then
290 - # We need to do the non-stripped scan serially first before we turn around
291 - # and start stripping the files ourselves. The log parsing can be done in
292 - # parallel though.
293 - log=${tmpdir}/scanelf-already-stripped.log
294 - scanelf -yqRBF '#k%F' -k '!.symtab' "$@" | sed -e "s#^${ED%/}/##" > "${log}"
295 - qa_var="QA_PRESTRIPPED_${ARCH/-/_}"
296 - [[ -n ${!qa_var} ]] && QA_PRESTRIPPED="${!qa_var}"
297 - if [[ -n ${QA_PRESTRIPPED} && -s ${log} && \
298 - ${QA_STRICT_PRESTRIPPED-unset} = unset ]] ; then
299 - shopts=$-
300 - set -o noglob
301 - for x in ${QA_PRESTRIPPED} ; do
302 - sed -e "s#^${x#/}\$##" -i "${log}"
303 - done
304 - set +o noglob
305 - set -${shopts}
306 - fi
307 - sed -e "/^\$/d" -e "s#^#/#" -i "${log}"
308 - if [[ -s ${log} ]] ; then
309 - __vecho -e "\n"
310 - eqawarn "QA Notice: Pre-stripped files found:"
311 - eqawarn "$(<"${log}")"
312 - else
313 - rm -f "${log}"
314 - fi
315 -fi
316 -
317 -# Since strip creates a new inode, we need to know the initial set of
318 -# inodes in advance, so that we can avoid interference due to trying
319 -# to strip the same (hardlinked) file multiple times in parallel.
320 -# See bug #421099.
321 -if [[ ${USERLAND} == BSD ]] ; then
322 - get_inode_number() { stat -f '%i' "$1"; }
323 -else
324 - get_inode_number() { stat -c '%i' "$1"; }
325 -fi
326 -cd "${tmpdir}/inodes" || die "cd failed unexpectedly"
327 -while read -r x ; do
328 - inode_link=$(get_inode_number "${x}") || die "stat failed unexpectedly"
329 - echo "${x}" >> "${inode_link}" || die "echo failed unexpectedly"
330 -done < <(
331 - # Use sort -u to eliminate duplicates for bug #445336.
332 - (
333 - scanelf -yqRBF '#k%F' -k '.symtab' "$@"
334 - find "$@" -type f ! -type l -name '*.a'
335 - ) | LC_ALL=C sort -u
336 -)
337 -
338 -# Now we look for unstripped binaries.
339 -for inode_link in $(shopt -s nullglob; echo *) ; do
340 -while read -r x
341 -do
342 -
343 - if ! ${banner} ; then
344 - __vecho "strip: ${STRIP} ${PORTAGE_STRIP_FLAGS}"
345 - banner=true
346 - fi
347 -
348 - f=$(file "${x}") || continue
349 - [[ -z ${f} ]] && continue
350 -
351 - if ! ${SKIP_STRIP} ; then
352 - # The noglob funk is to support STRIP_MASK="/*/booga" and to keep
353 - # the for loop from expanding the globs.
354 - # The eval echo is to support STRIP_MASK="/*/{booga,bar}" sex.
355 - set -o noglob
356 - strip_this=true
357 - for m in $(eval echo ${STRIP_MASK}) ; do
358 - [[ /${x#${ED%/}} == ${m} ]] && strip_this=false && break
359 - done
360 - set +o noglob
361 - else
362 - strip_this=false
363 - fi
364 -
365 - # In Prefix we are usually an unprivileged user, so we can't strip
366 - # unwritable objects. Make them temporarily writable for the
367 - # stripping.
368 - was_not_writable=false
369 - if [[ ! -w ${x} ]] ; then
370 - was_not_writable=true
371 - chmod u+w "${x}"
372 - fi
373 -
374 - # only split debug info for final linked objects
375 - # or kernel modules as debuginfo for intermediatary
376 - # files (think crt*.o from gcc/glibc) is useless and
377 - # actually causes problems. install sources for all
378 - # elf types though cause that stuff is good.
379 -
380 - buildid=
381 - if [[ ${f} == *"current ar archive"* ]] ; then
382 - __vecho " ${x:${#ED}}"
383 - if ${strip_this} ; then
384 - # If we have split debug enabled, then do not strip this.
385 - # There is no concept of splitdebug for objects not yet
386 - # linked in (only for finally linked ELFs), so we have to
387 - # retain the debug info in the archive itself.
388 - if ! ${FEATURES_splitdebug} || ${RESTRICT_splitdebug} ; then
389 - ${STRIP} -g "${x}"
390 - fi
391 - fi
392 - elif [[ ${f} == *"SB executable"* || ${f} == *"SB shared object"* ]] ; then
393 - process_elf "${x}" "${inode_link}" ${PORTAGE_STRIP_FLAGS}
394 - elif [[ ${f} == *"SB relocatable"* ]] ; then
395 - process_elf "${x}" "${inode_link}" ${SAFE_STRIP_FLAGS}
396 - fi
397 -
398 - if ${was_not_writable} ; then
399 - chmod u-w "${x}"
400 - fi
401 -
402 -done < "${inode_link}"
403 -done
404 -
405 -cd "${tmpdir}"/sources/ && cat * > "${tmpdir}/debug.sources" 2>/dev/null
406 -if [[ -s ${tmpdir}/debug.sources ]] && \
407 - ${FEATURES_installsources} && \
408 - ! ${RESTRICT_installsources} && \
409 - ${debugedit_found}
410 -then
411 - __vecho "installsources: rsyncing source files"
412 - [[ -d ${D%/}/${prepstrip_sources_dir#/} ]] || mkdir -p "${D%/}/${prepstrip_sources_dir#/}"
413 - grep -zv '/<[^/>]*>$' "${tmpdir}"/debug.sources | \
414 - (cd "${WORKDIR}"; LANG=C sort -z -u | \
415 - rsync -tL0 --chmod=ugo-st,a+r,go-w,Da+x,Fa-x --files-from=- "${WORKDIR}/" "${D%/}/${prepstrip_sources_dir#/}/" )
416 -
417 - # Preserve directory structure.
418 - # Needed after running save_elf_sources.
419 - # https://bugzilla.redhat.com/show_bug.cgi?id=444310
420 - while read -r -d $'\0' emptydir
421 - do
422 - >> "${emptydir}"/.keepdir
423 - done < <(find "${D%/}/${prepstrip_sources_dir#/}/" -type d -empty -print0)
424 -fi
425 -
426 -cd "${T}"
427 -rm -rf "${tmpdir}"
428 +exit 0
429 diff --git a/bin/estrip b/bin/estrip
430 new file mode 100755
431 index 000000000..431624498
432 --- /dev/null
433 +++ b/bin/estrip
434 @@ -0,0 +1,390 @@
435 +#!/bin/bash
436 +# Copyright 1999-2018 Gentoo Foundation
437 +# Distributed under the terms of the GNU General Public License v2
438 +
439 +source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
440 +
441 +# avoid multiple calls to `has`. this creates things like:
442 +# FEATURES_foo=false
443 +# if "foo" is not in $FEATURES
444 +tf() { "$@" && echo true || echo false ; }
445 +exp_tf() {
446 + local flag var=$1
447 + shift
448 + for flag in "$@" ; do
449 + eval ${var}_${flag}=$(tf has ${flag} ${!var})
450 + done
451 +}
452 +exp_tf FEATURES compressdebug installsources nostrip splitdebug xattr
453 +exp_tf RESTRICT binchecks installsources splitdebug strip
454 +
455 +if ! ___eapi_has_prefix_variables; then
456 + EPREFIX= ED=${D}
457 +fi
458 +
459 +banner=false
460 +SKIP_STRIP=false
461 +if ${RESTRICT_strip} || ${FEATURES_nostrip} ; then
462 + SKIP_STRIP=true
463 + banner=true
464 + ${FEATURES_installsources} || exit 0
465 +fi
466 +
467 +PRESERVE_XATTR=false
468 +if [[ ${KERNEL} == linux ]] && ${FEATURES_xattr} ; then
469 + PRESERVE_XATTR=true
470 + if type -P getfattr >/dev/null && type -P setfattr >/dev/null ; then
471 + dump_xattrs() {
472 + getfattr -d -m - --absolute-names "$1"
473 + }
474 + restore_xattrs() {
475 + setfattr --restore=-
476 + }
477 + else
478 + dump_xattrs() {
479 + PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
480 + "${PORTAGE_PYTHON:-/usr/bin/python}" \
481 + "${PORTAGE_BIN_PATH}/xattr-helper.py" --dump < <(echo -n "$1")
482 + }
483 + restore_xattrs() {
484 + PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
485 + "${PORTAGE_PYTHON:-/usr/bin/python}" \
486 + "${PORTAGE_BIN_PATH}/xattr-helper.py" --restore
487 + }
488 + fi
489 +fi
490 +
491 +# look up the tools we might be using
492 +for t in STRIP:strip OBJCOPY:objcopy READELF:readelf ; do
493 + v=${t%:*} # STRIP
494 + t=${t#*:} # strip
495 + eval ${v}=\"${!v:-${CHOST}-${t}}\"
496 + type -P -- ${!v} >/dev/null || eval ${v}=${t}
497 +done
498 +
499 +# Figure out what tool set we're using to strip stuff
500 +unset SAFE_STRIP_FLAGS DEF_STRIP_FLAGS SPLIT_STRIP_FLAGS
501 +case $(${STRIP} --version 2>/dev/null) in
502 +*elfutils*) # dev-libs/elfutils
503 + # elfutils default behavior is always safe, so don't need to specify
504 + # any flags at all
505 + SAFE_STRIP_FLAGS=""
506 + DEF_STRIP_FLAGS="--remove-comment"
507 + SPLIT_STRIP_FLAGS="-f"
508 + ;;
509 +*GNU*) # sys-devel/binutils
510 + # We'll leave out -R .note for now until we can check out the relevance
511 + # of the section when it has the ALLOC flag set on it ...
512 + SAFE_STRIP_FLAGS="--strip-unneeded"
513 + DEF_STRIP_FLAGS="-R .comment -R .GCC.command.line -R .note.gnu.gold-version"
514 + SPLIT_STRIP_FLAGS=
515 + ;;
516 +esac
517 +: ${PORTAGE_STRIP_FLAGS=${SAFE_STRIP_FLAGS} ${DEF_STRIP_FLAGS}}
518 +
519 +prepstrip_sources_dir=${EPREFIX}/usr/src/debug/${CATEGORY}/${PF}
520 +
521 +debugedit=$(type -P debugedit)
522 +if [[ -z ${debugedit} ]]; then
523 + debugedit_paths=(
524 + "${EPREFIX}/usr/libexec/rpm/debugedit"
525 + )
526 + for x in "${debugedit_paths[@]}"; do
527 + if [[ -x ${x} ]]; then
528 + debugedit=${x}
529 + break
530 + fi
531 + done
532 +fi
533 +[[ ${debugedit} ]] && debugedit_found=true || debugedit_found=false
534 +debugedit_warned=false
535 +
536 +# Setup $T filesystem layout that we care about.
537 +tmpdir="${T}/prepstrip"
538 +rm -rf "${tmpdir}"
539 +mkdir -p "${tmpdir}"/{inodes,splitdebug,sources}
540 +
541 +# Usage: save_elf_sources <elf>
542 +save_elf_sources() {
543 + ${FEATURES_installsources} || return 0
544 + ${RESTRICT_installsources} && return 0
545 + if ! ${debugedit_found} ; then
546 + if ! ${debugedit_warned} ; then
547 + debugedit_warned=true
548 + ewarn "FEATURES=installsources is enabled but the debugedit binary could not be"
549 + ewarn "found. This feature will not work unless debugedit or rpm is installed!"
550 + fi
551 + return 0
552 + fi
553 +
554 + local x=$1
555 +
556 + # since we're editing the ELF here, we should recompute the build-id
557 + # (the -i flag below). save that output so we don't need to recompute
558 + # it later on in the save_elf_debug step.
559 + buildid=$("${debugedit}" -i \
560 + -b "${WORKDIR}" \
561 + -d "${prepstrip_sources_dir}" \
562 + -l "${tmpdir}/sources/${x##*/}.${BASHPID:-$(__bashpid)}" \
563 + "${x}")
564 +}
565 +
566 +# Usage: save_elf_debug <elf> [splitdebug file]
567 +save_elf_debug() {
568 + ${FEATURES_splitdebug} || return 0
569 + ${RESTRICT_splitdebug} && return 0
570 +
571 + # NOTE: Debug files must be installed in
572 + # ${EPREFIX}/usr/lib/debug/${EPREFIX} (note that ${EPREFIX} occurs
573 + # twice in this path) in order for gdb's debug-file-directory
574 + # lookup to work correctly.
575 + local x=$1
576 + local inode_debug=$2
577 + local splitdebug=$3
578 + local d_noslash=${D%/}
579 + local y=${ED%/}/usr/lib/debug/${x:${#d_noslash}}.debug
580 +
581 + # dont save debug info twice
582 + [[ ${x} == *".debug" ]] && return 0
583 +
584 + mkdir -p "${y%/*}"
585 +
586 + if [ -f "${inode_debug}" ] ; then
587 + ln "${inode_debug}" "${y}" || die "ln failed unexpectedly"
588 + else
589 + if [[ -n ${splitdebug} ]] ; then
590 + mv "${splitdebug}" "${y}"
591 + else
592 + local objcopy_flags="--only-keep-debug"
593 + ${FEATURES_compressdebug} && objcopy_flags+=" --compress-debug-sections"
594 + ${OBJCOPY} ${objcopy_flags} "${x}" "${y}"
595 + ${OBJCOPY} --add-gnu-debuglink="${y}" "${x}"
596 + fi
597 + # Only do the following if the debug file was
598 + # successfully created (see bug #446774).
599 + if [ $? -eq 0 ] ; then
600 + local args="a-x,o-w"
601 + [[ -g ${x} || -u ${x} ]] && args+=",go-r"
602 + chmod ${args} "${y}"
603 + ln "${y}" "${inode_debug}" || die "ln failed unexpectedly"
604 + fi
605 + fi
606 +
607 + # if we don't already have build-id from debugedit, look it up
608 + if [[ -z ${buildid} ]] ; then
609 + # convert the readelf output to something useful
610 + buildid=$(${READELF} -n "${x}" 2>/dev/null | awk '/Build ID:/{ print $NF; exit }')
611 + fi
612 + if [[ -n ${buildid} ]] ; then
613 + local buildid_dir="${ED%/}/usr/lib/debug/.build-id/${buildid:0:2}"
614 + local buildid_file="${buildid_dir}/${buildid:2}"
615 + mkdir -p "${buildid_dir}"
616 + [ -L "${buildid_file}".debug ] || ln -s "../../${x:${#D}}.debug" "${buildid_file}.debug"
617 + [ -L "${buildid_file}" ] || ln -s "/${x:${#D}}" "${buildid_file}"
618 + fi
619 +}
620 +
621 +# Usage: process_elf <elf>
622 +process_elf() {
623 + local x=$1 inode_link=$2 strip_flags=${*:3}
624 + local already_stripped lockfile xt_data
625 +
626 + __vecho " ${x:${#ED}}"
627 +
628 + # If two processes try to debugedit or strip the same hardlink at the
629 + # same time, it may corrupt files or cause loss of splitdebug info.
630 + # So, use a lockfile to prevent interference (easily observed with
631 + # dev-vcs/git which creates ~111 hardlinks to one file in
632 + # /usr/libexec/git-core).
633 + lockfile=${inode_link}_lockfile
634 + if ! ln "${inode_link}" "${lockfile}" 2>/dev/null ; then
635 + while [[ -f ${lockfile} ]] ; do
636 + sleep 1
637 + done
638 + unset lockfile
639 + fi
640 +
641 + [ -f "${inode_link}_stripped" ] && already_stripped=true || already_stripped=false
642 +
643 + if ! ${already_stripped} ; then
644 + if ${PRESERVE_XATTR} ; then
645 + xt_data=$(dump_xattrs "${x}")
646 + fi
647 + save_elf_sources "${x}"
648 + fi
649 +
650 + if ${strip_this} ; then
651 +
652 + # see if we can split & strip at the same time
653 + if [[ -n ${SPLIT_STRIP_FLAGS} ]] ; then
654 + local shortname="${x##*/}.debug"
655 + local splitdebug="${tmpdir}/splitdebug/${shortname}.${BASHPID:-$(__bashpid)}"
656 + ${already_stripped} || \
657 + ${STRIP} ${strip_flags} \
658 + -f "${splitdebug}" \
659 + -F "${shortname}" \
660 + "${x}"
661 + save_elf_debug "${x}" "${inode_link}_debug" "${splitdebug}"
662 + else
663 + save_elf_debug "${x}" "${inode_link}_debug"
664 + ${already_stripped} || \
665 + ${STRIP} ${strip_flags} "${x}"
666 + fi
667 + fi
668 +
669 + if ${already_stripped} ; then
670 + rm -f "${x}" || die "rm failed unexpectedly"
671 + ln "${inode_link}_stripped" "${x}" || die "ln failed unexpectedly"
672 + else
673 + ln "${x}" "${inode_link}_stripped" || die "ln failed unexpectedly"
674 + if [[ ${xt_data} ]] ; then
675 + restore_xattrs <<< "${xt_data}"
676 + fi
677 + fi
678 +
679 + [[ -n ${lockfile} ]] && rm -f "${lockfile}"
680 +}
681 +
682 +# The existance of the section .symtab tells us that a binary is stripped.
683 +# We want to log already stripped binaries, as this may be a QA violation.
684 +# They prevent us from getting the splitdebug data.
685 +if ! ${RESTRICT_binchecks} && ! ${RESTRICT_strip} ; then
686 + # We need to do the non-stripped scan serially first before we turn around
687 + # and start stripping the files ourselves. The log parsing can be done in
688 + # parallel though.
689 + log=${tmpdir}/scanelf-already-stripped.log
690 + scanelf -yqRBF '#k%F' -k '!.symtab' "$@" | sed -e "s#^${ED%/}/##" > "${log}"
691 + qa_var="QA_PRESTRIPPED_${ARCH/-/_}"
692 + [[ -n ${!qa_var} ]] && QA_PRESTRIPPED="${!qa_var}"
693 + if [[ -n ${QA_PRESTRIPPED} && -s ${log} && \
694 + ${QA_STRICT_PRESTRIPPED-unset} = unset ]] ; then
695 + shopts=$-
696 + set -o noglob
697 + for x in ${QA_PRESTRIPPED} ; do
698 + sed -e "s#^${x#/}\$##" -i "${log}"
699 + done
700 + set +o noglob
701 + set -${shopts}
702 + fi
703 + sed -e "/^\$/d" -e "s#^#/#" -i "${log}"
704 + if [[ -s ${log} ]] ; then
705 + __vecho -e "\n"
706 + eqawarn "QA Notice: Pre-stripped files found:"
707 + eqawarn "$(<"${log}")"
708 + else
709 + rm -f "${log}"
710 + fi
711 +fi
712 +
713 +# Since strip creates a new inode, we need to know the initial set of
714 +# inodes in advance, so that we can avoid interference due to trying
715 +# to strip the same (hardlinked) file multiple times in parallel.
716 +# See bug #421099.
717 +if [[ ${USERLAND} == BSD ]] ; then
718 + get_inode_number() { stat -f '%i' "$1"; }
719 +else
720 + get_inode_number() { stat -c '%i' "$1"; }
721 +fi
722 +cd "${tmpdir}/inodes" || die "cd failed unexpectedly"
723 +while read -r x ; do
724 + inode_link=$(get_inode_number "${x}") || die "stat failed unexpectedly"
725 + echo "${x}" >> "${inode_link}" || die "echo failed unexpectedly"
726 +done < <(
727 + # Use sort -u to eliminate duplicates for bug #445336.
728 + (
729 + scanelf -yqRBF '#k%F' -k '.symtab' "$@"
730 + find "$@" -type f ! -type l -name '*.a'
731 + ) | LC_ALL=C sort -u
732 +)
733 +
734 +# Now we look for unstripped binaries.
735 +for inode_link in $(shopt -s nullglob; echo *) ; do
736 +while read -r x
737 +do
738 +
739 + if ! ${banner} ; then
740 + __vecho "strip: ${STRIP} ${PORTAGE_STRIP_FLAGS}"
741 + banner=true
742 + fi
743 +
744 + f=$(file "${x}") || continue
745 + [[ -z ${f} ]] && continue
746 +
747 + if ! ${SKIP_STRIP} ; then
748 + # The noglob funk is to support STRIP_MASK="/*/booga" and to keep
749 + # the for loop from expanding the globs.
750 + # The eval echo is to support STRIP_MASK="/*/{booga,bar}" sex.
751 + set -o noglob
752 + strip_this=true
753 + for m in $(eval echo ${STRIP_MASK}) ; do
754 + [[ /${x#${ED%/}} == ${m} ]] && strip_this=false && break
755 + done
756 + set +o noglob
757 + else
758 + strip_this=false
759 + fi
760 +
761 + # In Prefix we are usually an unprivileged user, so we can't strip
762 + # unwritable objects. Make them temporarily writable for the
763 + # stripping.
764 + was_not_writable=false
765 + if [[ ! -w ${x} ]] ; then
766 + was_not_writable=true
767 + chmod u+w "${x}"
768 + fi
769 +
770 + # only split debug info for final linked objects
771 + # or kernel modules as debuginfo for intermediatary
772 + # files (think crt*.o from gcc/glibc) is useless and
773 + # actually causes problems. install sources for all
774 + # elf types though cause that stuff is good.
775 +
776 + buildid=
777 + if [[ ${f} == *"current ar archive"* ]] ; then
778 + __vecho " ${x:${#ED}}"
779 + if ${strip_this} ; then
780 + # If we have split debug enabled, then do not strip this.
781 + # There is no concept of splitdebug for objects not yet
782 + # linked in (only for finally linked ELFs), so we have to
783 + # retain the debug info in the archive itself.
784 + if ! ${FEATURES_splitdebug} || ${RESTRICT_splitdebug} ; then
785 + ${STRIP} -g "${x}"
786 + fi
787 + fi
788 + elif [[ ${f} == *"SB executable"* || ${f} == *"SB shared object"* ]] ; then
789 + process_elf "${x}" "${inode_link}" ${PORTAGE_STRIP_FLAGS}
790 + elif [[ ${f} == *"SB relocatable"* ]] ; then
791 + process_elf "${x}" "${inode_link}" ${SAFE_STRIP_FLAGS}
792 + fi
793 +
794 + if ${was_not_writable} ; then
795 + chmod u-w "${x}"
796 + fi
797 +
798 +done < "${inode_link}"
799 +done
800 +
801 +cd "${tmpdir}"/sources/ && cat * > "${tmpdir}/debug.sources" 2>/dev/null
802 +if [[ -s ${tmpdir}/debug.sources ]] && \
803 + ${FEATURES_installsources} && \
804 + ! ${RESTRICT_installsources} && \
805 + ${debugedit_found}
806 +then
807 + __vecho "installsources: rsyncing source files"
808 + [[ -d ${D%/}/${prepstrip_sources_dir#/} ]] || mkdir -p "${D%/}/${prepstrip_sources_dir#/}"
809 + grep -zv '/<[^/>]*>$' "${tmpdir}"/debug.sources | \
810 + (cd "${WORKDIR}"; LANG=C sort -z -u | \
811 + rsync -tL0 --chmod=ugo-st,a+r,go-w,Da+x,Fa-x --files-from=- "${WORKDIR}/" "${D%/}/${prepstrip_sources_dir#/}/" )
812 +
813 + # Preserve directory structure.
814 + # Needed after running save_elf_sources.
815 + # https://bugzilla.redhat.com/show_bug.cgi?id=444310
816 + while read -r -d $'\0' emptydir
817 + do
818 + >> "${emptydir}"/.keepdir
819 + done < <(find "${D%/}/${prepstrip_sources_dir#/}/" -type d -empty -print0)
820 +fi
821 +
822 +cd "${T}"
823 +rm -rf "${tmpdir}"
824 +
825 diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
826 index 7643af7b5..199e09fe9 100755
827 --- a/bin/misc-functions.sh
828 +++ b/bin/misc-functions.sh
829 @@ -218,12 +218,14 @@ install_qa_check() {
830 )
831 done < <(printf "%s\0" "${qa_checks[@]}" | LC_ALL=C sort -u -z)
832
833 - export STRIP_MASK
834 + export STRIP
835 prepall
836 ___eapi_has_docompress && prepcompress
837 ecompressdir --dequeue
838 ecompress --dequeue
839
840 + "${PORTAGE_BIN_PATH}"/estrip "${ED}"
841 +
842 # Create NEEDED.ELF.2 regardless of RESTRICT=binchecks, since this info is
843 # too useful not to have (it's required for things like preserve-libs), and
844 # it's tempting for ebuild authors to set RESTRICT=binchecks for packages
845 --
846 2.13.6