0b26f7
#!/bin/bash
0b26f7
# Wrapper script for find-debuginfo.sh
0b26f7
#
0b26f7
# Usage:
0b26f7
#  wrap-find-debuginfo.sh SYSROOT-PATH SCRIPT-PATH SCRIPT-ARGS...
0b26f7
#
0b26f7
# The wrapper saves the original version of ld.so found in SYSROOT-PATH,
0b26f7
# invokes SCRIPT-PATH with SCRIPT-ARGS, and then restores the
0b26f7
# LDSO-PATH file, followed by note merging and DWZ compression.
0b26f7
# As a result, ld.so has (mostly) unchanged debuginfo even
0b26f7
# after debuginfo extraction.
0b26f7
#
0b26f7
# For libc.so.6, a set of strategic symbols is preserved in .symtab
0b26f7
# that are frequently used in valgrind suppressions and elsewhere.
0b26f7
0b26f7
set -ex
0b26f7
6ca6e8
workdir="$(mktemp -d -t find_debuginfo.XXXXXX)"
6ca6e8
6ca6e8
ldso_tmp="$workdir/ld.so"
6ca6e8
libc_tmp_dir="$workdir/"
6ca6e8
6ca6e8
# Return the path where a libc should be saved temporarily. This path is
6ca6e8
# based on its original path received in $1.
6ca6e8
libc_tmp_path() {
6ca6e8
    echo "$libc_tmp_dir"`dirname "$1"`"/libc.so"
6ca6e8
}
0b26f7
0b26f7
# Prefer a separately installed debugedit over the RPM-integrated one.
0b26f7
if command -v debugedit >/dev/null ; then
0b26f7
    debugedit=debugedit
0b26f7
else
0b26f7
    debugedit=/usr/lib/rpm/debugedit
0b26f7
fi
0b26f7
0b26f7
cleanup () {
6ca6e8
    rm -rf "$workdir"
0b26f7
}
0b26f7
trap cleanup 0
0b26f7
0b26f7
sysroot_path="$1"
0b26f7
shift
0b26f7
script_path="$1"
0b26f7
shift
0b26f7
0b26f7
# See ldso_path setting in glibc.spec.
0b26f7
ldso_path=
6ca6e8
for ldso_candidate in `find "$sysroot_path" -maxdepth 2 \
6ca6e8
  -regextype posix-extended -regex '.*/ld(-.*|64|)\.so\.[0-9]+$' -type f` ; do
0b26f7
    if test -z "$ldso_path" ; then
0b26f7
	ldso_path="$ldso_candidate"
0b26f7
    else
0b26f7
	echo "error: multiple ld.so candidates: $ldso_path, $ldso_candidate"
0b26f7
	exit 1
0b26f7
    fi
0b26f7
done
0b26f7
0b26f7
# libc.so.6 always uses this name, so it is simpler to locate.
6ca6e8
libc_path=`find "$sysroot_path" -name libc.so.6`
0b26f7
0b26f7
0b26f7
# Preserve the original files.
0b26f7
cp "$ldso_path" "$ldso_tmp"
6ca6e8
for lib in $libc_path ; do
6ca6e8
    libtmp=`libc_tmp_path $lib`
6ca6e8
    mkdir -p `dirname "$libtmp"`
6ca6e8
    cp "$lib" "$libtmp"
6ca6e8
done
0b26f7
0b26f7
# Run the debuginfo extraction.
0b26f7
"$script_path" "$@"
0b26f7
6ca6e8
for lib in $libc_path ; do
6ca6e8
    libtmp=`libc_tmp_path "$lib"`
6ca6e8
    # libc.so.6: Extract the .gnu_debuglink section
6ca6e8
    objcopy -j.gnu_debuglink --set-section-flags .gnu_debuglink=alloc \
6ca6e8
        -O binary "$lib" "$libtmp.debuglink"
6ca6e8
    # Restore the original files.
6ca6e8
    cp "$libtmp" "$lib"
6ca6e8
6ca6e8
    # Reduce the size of libc notes.  Primarily for annobin.
6ca6e8
    objcopy --merge-notes "$lib"
6ca6e8
6ca6e8
    # libc.so.6: Restore the .gnu_debuglink section
6ca6e8
    objcopy --add-section .gnu_debuglink="$libtmp.debuglink" "$lib"
6ca6e8
6ca6e8
    # libc.so.6: Reduce to valuable symbols.  Eliminate file symbols,
6ca6e8
    # annobin symbols, and symbols used by the glibc build to implement
6ca6e8
    # hidden aliases (__EI_*).  We would also like to remove __GI_*
6ca6e8
    # symbols, but even listing them explicitly (as in -K __GI_strlen)
6ca6e8
    # still causes strip to remove them, so there is no filtering of
6ca6e8
    # __GI_* here.  (Debuginfo is gone after this, so no need to optimize
6ca6e8
    # it.)
6ca6e8
    strip -w \
6ca6e8
          -K '*' \
6ca6e8
          -K '!*.c' \
6ca6e8
          -K '!*.os' \
6ca6e8
          -K '!.annobin_*' \
6ca6e8
          -K '!__EI_*' \
6ca6e8
          -K '!__PRETTY_FUNCTION__*' \
6ca6e8
          "$lib"
6ca6e8
done
6ca6e8
6ca6e8
# Restore the original ld.so.
0b26f7
cp "$ldso_tmp" "$ldso_path"
0b26f7
0b26f7
# Reduce the size of notes.  Primarily for annobin.
0b26f7
objcopy --merge-notes "$ldso_path"
6ca6e8
6ca6e8
# ld.so does not have separated debuginfo and so the debuginfo file
6ca6e8
# generated by find-debuginfo is redundant.  Therefore, remove it.
6ca6e8
ldso_debug=
6ca6e8
for ldso_debug_candidate in `find "$sysroot_path" -maxdepth 2 \
6ca6e8
    -regextype posix-extended \
6ca6e8
  -regex '.*/ld(-.*|64|)\.so\.[0-9]+.*debug$' -type f` ; do
6ca6e8
    if test -z "$ldso_debug" ; then
6ca6e8
	ldso_debug="$ldso_debug_candidate"
6ca6e8
    else
6ca6e8
	echo "error: multiple ld.so debug candidates: $ldso_debug, $ldso_debug_candidate"
6ca6e8
	exit 1
6ca6e8
    fi
6ca6e8
done
6ca6e8
rm -f "$ldso_debug"
0b26f7
0b26f7
# ld.so: Rewrite the source file paths to match the extracted
0b26f7
# locations.  First compute the arguments for invoking debugedit.
0b26f7
# See find-debuginfo.sh.
0b26f7
debug_dest_name="/usr/src/debug"
0b26f7
last_arg=
0b26f7
while true ; do
0b26f7
    arg="$1"
0b26f7
    shift || break
0b26f7
    case "$arg" in
0b26f7
	(--unique-debug-src-base)
0b26f7
	    debug_dest_name="/usr/src/debug/$1"
0b26f7
	    shift
0b26f7
	    ;;
0b26f7
	(-*)
0b26f7
	    ;;
0b26f7
	(*)
0b26f7
	    last_arg="$arg"
0b26f7
	    ;;
0b26f7
    esac
0b26f7
done
0b26f7
debug_base_name=${last_arg:-$RPM_BUILD_ROOT}
0b26f7
$debugedit -b "$debug_base_name" -d "$debug_dest_name" -n $ldso_path
6ca6e8
# Remove the .annobin* symbols (and only them).
6ca6e8
if nm --format=posix "$ldso_path" | cut -d' ' -f1 \
6ca6e8
	| grep '^\.annobin' > "$ldso_tmp.annobin-symbols"; then
6ca6e8
    objcopy --strip-symbols="$ldso_tmp.annobin-symbols" "$ldso_path"
6ca6e8
fi
0b26f7
0b26f7
# Apply single-file DWARF optimization.
0b26f7
dwz $ldso_path