2 # extract-debuginfo.sh - automagically generate debug info
4 # Usage: extract-debuginfo.sh [--strict-build-id] [-g] [-r]
7 # The -g flag says to use strip -g instead of full strip on DSOs.
8 # The --strict-build-id flag says to exit with failure status if
9 # any ELF binary processed fails to contain a build-id note.
10 # The -r flag says to use eu-strip --reloc-debug-sections.
12 # All file names in switches are relative to builddir (. if not given).
15 echo "Extracting debuginfo to /usr/lib/debug..."
19 # With -g arg, pass it to strip on libraries.
22 # with -r arg, pass --reloc-debug-sections to eu-strip.
25 # Barf on missing build IDs.
29 while [ $# -gt 0 ]; do
32 SOURCEDIR
=${1#--sourcedir=}
35 BUILDROOT
=${1#--buildroot=}
55 debugdir
="${BUILDROOT}/usr/lib/debug"
57 # A list of source files that are included in the -debuginfo packages.
58 SOURCEFILE
="$(mktemp)"
63 ${strip_r} && r
=--reloc-debug-sections
65 case "$(file -bi "${2}")" in
66 application
/x-sharedlib
*)
71 eu-strip
--remove-comment ${r} ${g} -f "${1}" "${2}" || exit
72 chmod 444 "${1}" || exit
75 # Make a relative symlink to $1 called $3$2
78 local t="$1" f="$2" pfx="$3"
79 local fn="${f#/}" tn="${t#/}"
82 while fd="${fn%%/*}"; td="${tn%%/*}"; [ "$fd" = "$td" ]; do
88 if [ "$d" != "$fn" ]; then
93 mkdir -p "$
(dirname "$pfx$f")" && ln -snf "$tn" "$pfx$f"
96 # Make a symlink in /usr/lib/debug/$2 to $1
98 local l="/usr
/lib
/debug
$2"
100 link_relative "$t" "$l" "$BUILDROOT"
103 # Provide .2, .3, ... symlinks to all filename instances of this build-id.
105 local id="${1}" file="${2}" idfile
109 idfile=".build-id
/${id:0:2}/${id:2}.${n}"
110 [ $# -eq 3 ] && idfile="${idfile}$3"
111 if [ ! -L "${BUILDROOT}/usr
/lib
/debug
/${idfile}" ]; then
116 debug_link "${file}" "/${idfile}"
119 # Make a build-id symlink for id $1 with suffix $3 to file $2.
121 local id="${1}" file="${2}"
122 local idfile=".build-id
/${id:0:2}/${id:2}"
123 [ $# -eq 3 ] && idfile="${idfile}${3}"
124 local root_idfile="${BUILDROOT}/usr
/lib
/debug
/${idfile}"
126 if [ ! -L "${root_idfile}" ]; then
127 debug_link "${file}" "/${idfile}"
131 make_id_dup_link "$@
"
133 [ $# -eq 3 ] && return 0
135 local other=$(readlink -m "${root_idfile}")
136 other=${other#$BUILDROOT}
137 if cmp -s "${root_idfile}" "${BUILDROOT}${file}" ||
138 eu-elfcmp -q "${root_idfile}" "${BUILDROOT}${file}" 2> /dev/null; then
139 # Two copies. Maybe one has to be setuid or something.
140 echo >&2 "*** WARNING
: identical binaries are copied
, not linked
:"
142 echo >&2 " and
${other}"
144 # This is pathological, break the build.
145 echo >&2 "*** ERROR
: same build ID
in nonidentical files
!"
147 echo >&2 " and
${other}"
153 dn=$(dirname "${1#$BUILDROOT}")
154 bn=$(basename "$1" .debug).debug
156 debugdn=${debugdir}${dn}
157 debugfn=${debugdn}/${bn}
163 ${strict} || strict_error=WARNING
167 find "$BUILDROOT" ! -path "${debugdir}/*.debug
" -type f \
168 \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
170 file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped/\1/p' |
171 xargs --no-run-if-empty stat -c '%h %D_%i %n' |
172 while read nlinks inum f; do
174 [ -f "${debugfn}" ] && continue
176 # If this file has multiple links, keep track and make
177 # the corresponding .debug files all links to one file too.
178 if [ ${nlinks} -gt 1 ]; then
179 eval linked=\$linked_${inum}
180 if [ -n "${linked}" ]; then
181 eval id=\${linkedid_${inum}}
182 make_id_dup_link "${id}" "${dn}/$(basename ${f})"
183 make_id_dup_link "${id}" "/usr/lib/debug${dn}/${bn}" .debug
185 get_debugfn "${linked}"
186 echo " hard linked
${link} to
${debugfn}"
187 mkdir -p "$
(dirname "$link")" && ln -nf "$debugfn" "$link"
190 eval linked_${inum}=\${f}
191 echo " file ${f} has $
[${nlinks} - 1] other hard links
"
195 echo " Extracting debug info from
${f#${BUILDROOT}}"
196 id=$(@libexecdir@/debugedit -i \
202 if [ ${nlinks} -gt 1 ]; then
203 eval linkedid_${inum}=\${id}
206 if [ -z "$id" ]; then
207 echo >&2 "*** ${strict_error}: No build ID note found
in ${f#${BUILDROOT}}"
211 [ -x /usr/bin/gdb-add-index ] && /usr/bin/gdb-add-index "${f}" > /dev/null 2>&1
213 # A binary already copied into /usr/lib/debug doesn't get stripped,
214 # just has its file names collected and adjusted.
217 [ -z "${id}" ] || make_id_link "${id}" "${dn}/$(basename ${f})"
222 mkdir -p "${debugdn}"
223 if test -w "${f}"; then
224 strip_to_debug "${debugfn}" "${f}"
227 strip_to_debug "${debugfn}" "${f}"
231 if [ -n "${id}" ]; then
232 make_id_link "${id}" "${dn}/$(basename ${f})"
233 make_id_link "${id}" "/usr/lib/debug${dn}/${bn}" .debug
237 # For each symlink whose target has a .debug file,
238 # make a .debug symlink to that file.
239 find $BUILDROOT ! -path "${debugdir}/*" -type l -print |
241 t=$(readlink -m "$f").debug
244 if [ -f "$debugdir$t" ]; then
245 echo "symlinked
/usr
/lib
/debug
$t to
/usr
/lib
/debug
${f}.debug
"
246 debug_link "/usr
/lib
/debug
$t" "${f}.debug
"
250 if [ -s "${SOURCEFILE}" ]; then
251 mkdir -p "${BUILDROOT}/usr
/src
/debug
"
253 sort -z -u "${SOURCEFILE}" | grep -E -v -z '(<internal>|<built-in>)$' | \
254 (cd "${SOURCEDIR}"; cpio -pd0mL "${BUILDROOT}/usr
/src
/debug
" 2>/dev/null)
256 # stupid cpio creates new directories in mode 0700, fixup
257 find "${BUILDROOT}/usr
/src
/debug
" -type d -print0 | \
258 xargs --no-run-if-empty -0 chmod a+rx
261 chown root:root -R ${BUILDROOT}/usr/src/debug