| #!/bin/bash |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| strip_g=false |
| |
| |
| |
| strict=true |
| |
| BUILDDIR=. |
| out=debugfiles.list |
| nout=0 |
| while [ $# -gt 0 ]; do |
| case "$1" in |
| --strict-build-id) |
| strict=true |
| ;; |
| -g) |
| strip_g=true |
| ;; |
| -o) |
| if [ -z "${lists[$nout]}" -a -z "${ptns[$nout]}" ]; then |
| out=$2 |
| else |
| outs[$nout]=$2 |
| ((nout++)) |
| fi |
| shift |
| ;; |
| -l) |
| lists[$nout]="${lists[$nout]} $2" |
| shift |
| ;; |
| -p) |
| ptns[$nout]=$2 |
| shift |
| ;; |
| *) |
| BUILDDIR=$1 |
| shift |
| break |
| ;; |
| esac |
| shift |
| done |
| |
| i=0 |
| while ((i < nout)); do |
| outs[$i]="$BUILDDIR/${outs[$i]}" |
| l='' |
| for f in ${lists[$i]}; do |
| l="$l $BUILDDIR/$f" |
| done |
| lists[$i]=$l |
| ((++i)) |
| done |
| |
| LISTFILE=$BUILDDIR/$out |
| SOURCEFILE=$BUILDDIR/debugsources.list |
| LINKSFILE=$BUILDDIR/debuglinks.list |
| |
| > $SOURCEFILE |
| > $LISTFILE |
| > $LINKSFILE |
| |
| debugdir="${RPM_BUILD_ROOT}/usr/lib/debug" |
| |
| strip_to_debug() |
| { |
| local g= |
| $strip_g && case "$(file -bi "$2")" in |
| application/x-sharedlib,*) g=-g ;; |
| esac |
| eu-strip --remove-comment -f "$1" "$2" || exit |
| } |
| |
| |
| shopt -s extglob |
| link_relative() |
| { |
| local t="$1" f="$2" pfx="$3" |
| local fn="${f#/}" tn="${t#/}" |
| local fd td d |
| |
| while fd="${fn%%/*}"; td="${tn%%/*}"; [ "$fd" = "$td" ]; do |
| fn="${fn#*/}" |
| tn="${tn#*/}" |
| done |
| |
| d="${fn%/*}" |
| if [ "$d" != "$fn" ]; then |
| d="${d//+([!\/])/..}" |
| tn="${d}/${tn}" |
| fi |
| |
| mkdir -p "$(dirname "$pfx$f")" && ln -snf "$tn" "$pfx$f" |
| } |
| |
| |
| debug_link() |
| { |
| local l="/usr/lib/debug$2" |
| local t="$1" |
| echo >> $LINKSFILE "$l $t" |
| link_relative "$t" "$l" "$RPM_BUILD_ROOT" |
| } |
| |
| |
| make_id_link() |
| { |
| local id="$1" file="$2" |
| local idfile=".build-id/${id:0:2}/${id:2}" |
| [ $# -eq 3 ] && idfile="${idfile}$3" |
| local root_idfile="$RPM_BUILD_ROOT/usr/lib/debug/$idfile" |
| |
| if [ ! -L "$root_idfile" ]; then |
| debug_link "$file" "/$idfile" |
| return |
| fi |
| |
| [ $# -eq 3 ] && return 0 |
| |
| local other=$(readlink -m "$root_idfile") |
| other=${other#$RPM_BUILD_ROOT} |
| if cmp -s "$root_idfile" "$RPM_BUILD_ROOT$file" || |
| eu-elfcmp -q "$root_idfile" "$RPM_BUILD_ROOT$file" 2> /dev/null; then |
| |
| echo >&2 "*** WARNING: identical binaries are copied, not linked:" |
| echo >&2 " $file" |
| echo >&2 " and $other" |
| else |
| |
| echo >&2 "*** ERROR: same build ID in nonidentical files!" |
| echo >&2 " $file" |
| echo >&2 " and $other" |
| exit 2 |
| fi |
| } |
| |
| get_debugfn() |
| { |
| dn=$(dirname "${1#$RPM_BUILD_ROOT}") |
| bn=$(basename "$1" .debug).debug |
| |
| debugdn=${debugdir}${dn} |
| debugfn=${debugdn}/${bn} |
| } |
| |
| set -o pipefail |
| |
| strict_error=ERROR |
| $strict || strict_error=WARNING |
| |
| |
| find $RPM_BUILD_ROOT ! -path "${debugdir}/*.debug" -type f \ |
| \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \ |
| -print | |
| file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped/\1/p' | |
| xargs stat -c '%h %D_%i %n' | |
| while read nlinks inum f; do |
| get_debugfn "$f" |
| [ -f "${debugfn}" ] && continue |
| |
| |
| |
| if [ $nlinks -gt 1 ]; then |
| eval linked=\$linked_$inum |
| if [ -n "$linked" ]; then |
| link=$debugfn |
| get_debugfn "$linked" |
| echo "hard linked $link to $debugfn" |
| ln -nf "$debugfn" "$link" |
| continue |
| else |
| eval linked_$inum=\$f |
| echo "file $f has $[$nlinks - 1] other hard links" |
| fi |
| fi |
| |
| echo "extracting debug info from $f" |
| id=$(/usr/lib/rpm/debugedit -b "$RPM_BUILD_DIR" -d /usr/src/debug \ |
| -i -l "$SOURCEFILE" "$f") || exit |
| if [ -z "$id" ]; then |
| echo >&2 "*** ${strict_error}: No build ID note found in $f" |
| $strict && exit 2 |
| fi |
| |
| |
| |
| case "$dn" in |
| /usr/lib/debug/*) |
| [ -z "$id" ] || make_id_link "$id" "$dn/$(basename $f)" |
| continue ;; |
| esac |
| |
| mkdir -p "${debugdn}" |
| if test -w "$f"; then |
| strip_to_debug "${debugfn}" "$f" |
| else |
| chmod u+w "$f" |
| strip_to_debug "${debugfn}" "$f" |
| chmod u-w "$f" |
| fi |
| |
| if [ -n "$id" ]; then |
| make_id_link "$id" "$dn/$(basename $f)" |
| make_id_link "$id" "/usr/lib/debug$dn/$bn" .debug |
| fi |
| done || exit |
| |
| |
| |
| find $RPM_BUILD_ROOT ! -path "${debugdir}/*" -type l -print | |
| while read f |
| do |
| t=$(readlink -m "$f").debug |
| f=${f#$RPM_BUILD_ROOT} |
| t=${t#$RPM_BUILD_ROOT} |
| if [ -f "$debugdir$t" ]; then |
| echo "symlinked /usr/lib/debug$t to /usr/lib/debug${f}.debug" |
| debug_link "/usr/lib/debug$t" "${f}.debug" |
| fi |
| done |
| |
| mkdir -p ${RPM_BUILD_ROOT}/usr/src/debug |
| LC_ALL=C sort -z -u $SOURCEFILE | egrep -v -z '(<internal>|<built-in>)$' | |
| (cd $RPM_BUILD_DIR; cpio -pd0mL ${RPM_BUILD_ROOT}/usr/src/debug) |
| |
| find ${RPM_BUILD_ROOT}/usr/src/debug -type d -print0 | xargs -0 chmod a+rx |
| |
| gendirs=src |
| ((nout > 0)) || gendirs='lib src' |
| for d in $gendirs; do |
| (cd ${RPM_BUILD_ROOT}/usr/$d; find debug -type d) | |
| sed "s,^,%dir /usr/$d/," >> $LISTFILE |
| done |
| |
| (cd ${RPM_BUILD_ROOT}/usr |
| find lib/debug ! -type d |
| find src/debug -mindepth 1 -maxdepth 1 |
| ) | sed 's,^,/usr/,' >> $LISTFILE |
| |
| |
| append_uniq() |
| { |
| fgrep -f "$1" -x -v >> "$1" |
| } |
| |
| |
| filelist_debugfiles() |
| { |
| local extra="$1" |
| shift |
| sed 's/^%[a-z0-9_][a-z0-9_]*([^)]*) *// |
| s/^%[a-z0-9_][a-z0-9_]* *// |
| /^$/d |
| '"$extra" "$@" |
| } |
| |
| |
| filtered_list() |
| { |
| local out="$1" |
| shift |
| test $# -gt 0 || return |
| fgrep -f <(filelist_debugfiles 's,^.*$,/usr/lib/debug&.debug,' "$@") \ |
| -x $LISTFILE >> $out |
| sed -n -f <(filelist_debugfiles 's/[\\.*+#]/\\&/g |
| h |
| s,^.*$,s# &$##p,p |
| g |
| s,^.*$,s# /usr/lib/debug&.debug$##p,p |
| ' "$@") $LINKSFILE | append_uniq "$out" |
| } |
| |
| |
| pattern_list() |
| { |
| local out="$1" ptn="$2" |
| test -n "$ptn" || return |
| egrep -x -e "$ptn" $LISTFILE >> $out |
| sed -n -r "\#^$ptn #s/ .*\$//p" $LINKSFILE | append_uniq "$out" |
| } |
| |
| |
| |
| |
| i=0 |
| while ((i < nout)); do |
| > ${outs[$i]} |
| filtered_list ${outs[$i]} ${lists[$i]} |
| pattern_list ${outs[$i]} "${ptns[$i]}" |
| fgrep -vx -f ${outs[$i]} $LISTFILE > ${LISTFILE}.new |
| mv ${LISTFILE}.new $LISTFILE |
| ((++i)) |
| done |
| if ((nout > 0)); then |
| |
| (cd ${RPM_BUILD_ROOT}; find usr/{lib,src}/debug -type d) | |
| sed 's#^.*$#\\@^/&/@{h;s@^.*$@%dir /&@p;g;}#' | |
| LC_ALL=C sort -ur > ${LISTFILE}.dirs.sed |
| i=0 |
| while ((i < nout)); do |
| sed -n -f ${LISTFILE}.dirs.sed ${outs[$i]} | sort -u > ${outs[$i]}.new |
| cat ${outs[$i]} >> ${outs[$i]}.new |
| mv -f ${outs[$i]}.new ${outs[$i]} |
| ((++i)) |
| done |
| sed -n -f ${LISTFILE}.dirs.sed ${LISTFILE} | sort -u > ${LISTFILE}.new |
| cat $LISTFILE >> ${LISTFILE}.new |
| mv ${LISTFILE}.new $LISTFILE |
| fi |