]> git.ipfire.org Git - people/stevee/pakfire.git/blame - src/scripts/extract-debuginfo.in
Remove shipped version of debugedit
[people/stevee/pakfire.git] / src / scripts / extract-debuginfo.in
CommitLineData
3ce6a8ad
MT
1#!/bin/bash
2# extract-debuginfo.sh - automagically generate debug info
3#
4# Usage: extract-debuginfo.sh [--strict-build-id] [-g] [-r]
5# [builddir]
6#
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.
11#
12# All file names in switches are relative to builddir (. if not given).
13#
14
15echo "Extracting debuginfo to /usr/lib/debug..."
16
17export LC_ALL=C
18
19# With -g arg, pass it to strip on libraries.
20strip_g=false
21
22# with -r arg, pass --reloc-debug-sections to eu-strip.
23strip_r=false
24
25# Barf on missing build IDs.
26strict=false
27
28BUILDDIR=.
29while [ $# -gt 0 ]; do
30 case "${1}" in
31 --sourcedir=*)
32 SOURCEDIR=${1#--sourcedir=}
33 ;;
34 --buildroot=*)
35 BUILDROOT=${1#--buildroot=}
36 ;;
37 --strict-build-id)
38 strict=true
39 ;;
40 -g)
41 strip_g=true
42 ;;
43 -r)
44 strip_r=true
45 ;;
46 *)
47 BUILDDIR=${1}
48 shift
49 break
50 ;;
51 esac
52 shift
53done
54
55debugdir="${BUILDROOT}/usr/lib/debug"
56
57# A list of source files that are included in the -debuginfo packages.
58SOURCEFILE="$(mktemp)"
59
60strip_to_debug() {
61 local g=
62 local r=
63 ${strip_r} && r=--reloc-debug-sections
64 ${strip_g} && \
65 case "$(file -bi "${2}")" in
66 application/x-sharedlib*)
67 g=-g
68 ;;
69 esac
70
71 eu-strip --remove-comment ${r} ${g} -f "${1}" "${2}" || exit
72 chmod 444 "${1}" || exit
73}
74
75# Make a relative symlink to $1 called $3$2
76shopt -s extglob
77link_relative() {
78 local t="$1" f="$2" pfx="$3"
79 local fn="${f#/}" tn="${t#/}"
80 local fd td d
81
82 while fd="${fn%%/*}"; td="${tn%%/*}"; [ "$fd" = "$td" ]; do
83 fn="${fn#*/}"
84 tn="${tn#*/}"
85 done
86
87 d="${fn%/*}"
88 if [ "$d" != "$fn" ]; then
89 d="${d//+([!\/])/..}"
90 tn="${d}/${tn}"
91 fi
92
93 mkdir -p "$(dirname "$pfx$f")" && ln -snf "$tn" "$pfx$f"
94}
95
96# Make a symlink in /usr/lib/debug/$2 to $1
97debug_link() {
98 local l="/usr/lib/debug$2"
99 local t="$1"
100 link_relative "$t" "$l" "$BUILDROOT"
101}
102
103# Provide .2, .3, ... symlinks to all filename instances of this build-id.
104make_id_dup_link() {
105 local id="${1}" file="${2}" idfile
106
107 local n=1
108 while true; do
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
112 break
113 fi
114 n=$[${n}+1]
115 done
116 debug_link "${file}" "/${idfile}"
117}
118
119# Make a build-id symlink for id $1 with suffix $3 to file $2.
120make_id_link() {
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}"
125
126 if [ ! -L "${root_idfile}" ]; then
127 debug_link "${file}" "/${idfile}"
128 return
129 fi
130
131 make_id_dup_link "$@"
132
133 [ $# -eq 3 ] && return 0
134
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:"
141 echo >&2 " ${file}"
142 echo >&2 " and ${other}"
143 else
144 # This is pathological, break the build.
145 echo >&2 "*** ERROR: same build ID in nonidentical files!"
146 echo >&2 " ${file}"
147 echo >&2 " and ${other}"
148 exit 2
149 fi
150}
151
152get_debugfn() {
153 dn=$(dirname "${1#$BUILDROOT}")
154 bn=$(basename "$1" .debug).debug
155
156 debugdn=${debugdir}${dn}
157 debugfn=${debugdn}/${bn}
158}
159
160set -o pipefail
161
162strict_error=ERROR
163${strict} || strict_error=WARNING
164
165
166# Strip ELF binaries
167find "$BUILDROOT" ! -path "${debugdir}/*.debug" -type f \
168 \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
169 -print |
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
173 get_debugfn "${f}"
174 [ -f "${debugfn}" ] && continue
175
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
184 link=${debugfn}
185 get_debugfn "${linked}"
186 echo " hard linked ${link} to ${debugfn}"
187 mkdir -p "$(dirname "$link")" && ln -nf "$debugfn" "$link"
188 continue
189 else
190 eval linked_${inum}=\${f}
191 echo " file ${f} has $[${nlinks} - 1] other hard links"
192 fi
193 fi
194
195 echo " Extracting debug info from ${f#${BUILDROOT}}"
559d80aa 196 id=$(debugedit -i \
3ce6a8ad
MT
197 -b "${SOURCEDIR}" \
198 -d /usr/src/debug \
199 -l "${SOURCEFILE}" \
200 "${f}") || exit
201
202 if [ ${nlinks} -gt 1 ]; then
203 eval linkedid_${inum}=\${id}
204 fi
205
206 if [ -z "$id" ]; then
207 echo >&2 "*** ${strict_error}: No build ID note found in ${f#${BUILDROOT}}"
208 ${strict} && exit 2
209 fi
210
211 [ -x /usr/bin/gdb-add-index ] && /usr/bin/gdb-add-index "${f}" > /dev/null 2>&1
212
213 # A binary already copied into /usr/lib/debug doesn't get stripped,
214 # just has its file names collected and adjusted.
215 case "${dn}" in
216 /usr/lib/debug/*)
217 [ -z "${id}" ] || make_id_link "${id}" "${dn}/$(basename ${f})"
218 continue
219 ;;
220 esac
221
222 mkdir -p "${debugdn}"
223 if test -w "${f}"; then
224 strip_to_debug "${debugfn}" "${f}"
225 else
226 chmod u+w "${f}"
227 strip_to_debug "${debugfn}" "${f}"
228 chmod u-w "${f}"
229 fi
230
231 if [ -n "${id}" ]; then
232 make_id_link "${id}" "${dn}/$(basename ${f})"
233 make_id_link "${id}" "/usr/lib/debug${dn}/${bn}" .debug
234 fi
235 done || exit
236
237# For each symlink whose target has a .debug file,
238# make a .debug symlink to that file.
239find $BUILDROOT ! -path "${debugdir}/*" -type l -print |
240 while read f; do
241 t=$(readlink -m "$f").debug
242 f=${f#$BUILDROOT}
243 t=${t#$BUILDROOT}
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"
247 fi
248 done
249
250if [ -s "${SOURCEFILE}" ]; then
251 mkdir -p "${BUILDROOT}/usr/src/debug"
252
253 sort -z -u "${SOURCEFILE}" | grep -E -v -z '(<internal>|<built-in>)$' | \
254 (cd "${SOURCEDIR}"; cpio -pd0mL "${BUILDROOT}/usr/src/debug" 2>/dev/null)
255
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
259
260 # Fix ownership.
261 chown root:root -R ${BUILDROOT}/usr/src/debug
262fi
263
264rm -f ${SOURCEFILE}
265
266exit 0