+++ /dev/null
-#!/bin/bash
-# extract-debuginfo.sh - automagically generate debug info
-#
-# Usage: extract-debuginfo.sh [--strict-build-id] [-g] [-r]
-# [builddir]
-#
-# The -g flag says to use strip -g instead of full strip on DSOs.
-# The --strict-build-id flag says to exit with failure status if
-# any ELF binary processed fails to contain a build-id note.
-# The -r flag says to use eu-strip --reloc-debug-sections.
-#
-# All file names in switches are relative to builddir (. if not given).
-#
-
-echo "Extracting debuginfo to /usr/lib/debug..."
-
-export LC_ALL=C
-
-# With -g arg, pass it to strip on libraries.
-strip_g=false
-
-# with -r arg, pass --reloc-debug-sections to eu-strip.
-strip_r=false
-
-# Barf on missing build IDs.
-strict=false
-
-BUILDDIR=.
-while [ $# -gt 0 ]; do
- case "${1}" in
- --sourcedir=*)
- SOURCEDIR=${1#--sourcedir=}
- ;;
- --buildroot=*)
- BUILDROOT=${1#--buildroot=}
- ;;
- --strict-build-id)
- strict=true
- ;;
- -g)
- strip_g=true
- ;;
- -r)
- strip_r=true
- ;;
- *)
- BUILDDIR=${1}
- shift
- break
- ;;
- esac
- shift
-done
-
-debugdir="${BUILDROOT}/usr/lib/debug"
-
-# A list of source files that are included in the -debuginfo packages.
-SOURCEFILE="$(mktemp)"
-
-strip_to_debug() {
- local g=
- local r=
- ${strip_r} && r=--reloc-debug-sections
- ${strip_g} && \
- case "$(file -bi "${2}")" in
- application/x-sharedlib*)
- g=-g
- ;;
- esac
-
- eu-strip --remove-comment ${r} ${g} -f "${1}" "${2}" || exit
- chmod 444 "${1}" || exit
-}
-
-# Make a relative symlink to $1 called $3$2
-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"
-}
-
-# Make a symlink in /usr/lib/debug/$2 to $1
-debug_link() {
- local l="/usr/lib/debug$2"
- local t="$1"
- link_relative "$t" "$l" "$BUILDROOT"
-}
-
-# Provide .2, .3, ... symlinks to all filename instances of this build-id.
-make_id_dup_link() {
- local id="${1}" file="${2}" idfile
-
- local n=1
- while true; do
- idfile=".build-id/${id:0:2}/${id:2}.${n}"
- [ $# -eq 3 ] && idfile="${idfile}$3"
- if [ ! -L "${BUILDROOT}/usr/lib/debug/${idfile}" ]; then
- break
- fi
- n=$[${n}+1]
- done
- debug_link "${file}" "/${idfile}"
-}
-
-# Make a build-id symlink for id $1 with suffix $3 to file $2.
-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="${BUILDROOT}/usr/lib/debug/${idfile}"
-
- if [ ! -L "${root_idfile}" ]; then
- debug_link "${file}" "/${idfile}"
- return
- fi
-
- make_id_dup_link "$@"
-
- [ $# -eq 3 ] && return 0
-
- local other=$(readlink -m "${root_idfile}")
- other=${other#$BUILDROOT}
- if cmp -s "${root_idfile}" "${BUILDROOT}${file}" ||
- eu-elfcmp -q "${root_idfile}" "${BUILDROOT}${file}" 2> /dev/null; then
- # Two copies. Maybe one has to be setuid or something.
- echo >&2 "*** WARNING: identical binaries are copied, not linked:"
- echo >&2 " ${file}"
- echo >&2 " and ${other}"
- else
- # This is pathological, break the build.
- echo >&2 "*** ERROR: same build ID in nonidentical files!"
- echo >&2 " ${file}"
- echo >&2 " and ${other}"
- exit 2
- fi
-}
-
-get_debugfn() {
- dn=$(dirname "${1#$BUILDROOT}")
- bn=$(basename "$1" .debug).debug
-
- debugdn=${debugdir}${dn}
- debugfn=${debugdn}/${bn}
-}
-
-set -o pipefail
-
-strict_error=ERROR
-${strict} || strict_error=WARNING
-
-
-# Strip ELF binaries
-find "$BUILDROOT" ! -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 --no-run-if-empty stat -c '%h %D_%i %n' |
- while read nlinks inum f; do
- get_debugfn "${f}"
- [ -f "${debugfn}" ] && continue
-
- # If this file has multiple links, keep track and make
- # the corresponding .debug files all links to one file too.
- if [ ${nlinks} -gt 1 ]; then
- eval linked=\$linked_${inum}
- if [ -n "${linked}" ]; then
- eval id=\${linkedid_${inum}}
- make_id_dup_link "${id}" "${dn}/$(basename ${f})"
- make_id_dup_link "${id}" "/usr/lib/debug${dn}/${bn}" .debug
- link=${debugfn}
- get_debugfn "${linked}"
- echo " hard linked ${link} to ${debugfn}"
- mkdir -p "$(dirname "$link")" && 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#${BUILDROOT}}"
- id=$(debugedit -i \
- -b "${SOURCEDIR}" \
- -d /usr/src/debug \
- -l "${SOURCEFILE}" \
- "${f}") || exit
-
- if [ ${nlinks} -gt 1 ]; then
- eval linkedid_${inum}=\${id}
- fi
-
- if [ -z "$id" ]; then
- echo >&2 "*** ${strict_error}: No build ID note found in ${f#${BUILDROOT}}"
- ${strict} && exit 2
- fi
-
- [ -x /usr/bin/gdb-add-index ] && /usr/bin/gdb-add-index "${f}" > /dev/null 2>&1
-
- # A binary already copied into /usr/lib/debug doesn't get stripped,
- # just has its file names collected and adjusted.
- 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
-
-# For each symlink whose target has a .debug file,
-# make a .debug symlink to that file.
-find $BUILDROOT ! -path "${debugdir}/*" -type l -print |
- while read f; do
- t=$(readlink -m "$f").debug
- f=${f#$BUILDROOT}
- t=${t#$BUILDROOT}
- 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
-
-if [ -s "${SOURCEFILE}" ]; then
- mkdir -p "${BUILDROOT}/usr/src/debug"
-
- sort -z -u "${SOURCEFILE}" | grep -E -v -z '(<internal>|<built-in>)$' | \
- (cd "${SOURCEDIR}"; cpio -pd0mL "${BUILDROOT}/usr/src/debug" 2>/dev/null)
-
- # stupid cpio creates new directories in mode 0700, fixup
- find "${BUILDROOT}/usr/src/debug" -type d -print0 | \
- xargs --no-run-if-empty -0 chmod a+rx
-
- # Fix ownership.
- chown root:root -R ${BUILDROOT}/usr/src/debug
-fi
-
-rm -f ${SOURCEFILE}
-
-exit 0