summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2016-06-14 17:07:09 +0200
committerFlorian Festi <ffesti@redhat.com>2016-07-29 18:28:53 +0200
commit6b3b435fa644522197003460a96cd11253b1494d (patch)
tree641c29a4f8ae48967a04c933baadcff29aa52f0d
parentb33a41da3689c4a803986eb95e5875e0dff36259 (diff)
downloadrpm-6b3b435fa644522197003460a96cd11253b1494d.tar.gz
Add dwz debuginfo compression support.
Support for dwz compression has been in Fedora since a couple of years. https://fedoraproject.org/wiki/Features/DwarfCompressor The original find-debuginfo.sh patch was written by Jakub Jelinek. https://bugzilla.redhat.com/show_bug.cgi?id=833311 The new testcase using the macros.debug was added by me. Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r--macros.debug13
-rw-r--r--macros.in2
-rw-r--r--scripts/find-debuginfo.sh53
-rw-r--r--tests/data/SPECS/hello2.spec62
-rw-r--r--tests/rpmbuild.at78
5 files changed, 207 insertions, 1 deletions
diff --git a/macros.debug b/macros.debug
index bb2c02f0b..6a8432eb7 100644
--- a/macros.debug
+++ b/macros.debug
@@ -28,3 +28,16 @@
# Should missing buildids terminate a build?
%_missing_build_ids_terminate_build 1
+
+# Number of debugging information entries (DIEs) above which
+# dwz will stop considering file for multifile optimizations
+# and enter a low memory mode, in which it will optimize
+# in about half the memory needed otherwise.
+%_dwz_low_mem_die_limit 10000000
+# Number of DIEs above which dwz will stop processing
+# a file altogether.
+%_dwz_max_die_limit 50000000
+
+%_find_debuginfo_dwz_opts --run-dwz\\\
+ --dwz-low-mem-die-limit %{_dwz_low_mem_die_limit}\\\
+ --dwz-max-die-limit %{_dwz_max_die_limit}
diff --git a/macros.in b/macros.in
index 94d0aa84a..e94f47616 100644
--- a/macros.in
+++ b/macros.in
@@ -178,7 +178,7 @@
# the script. See the script for details.
#
%__debug_install_post \
- %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
+ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
%{nil}
# Template for debug information sub-package.
diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
index 5c2c381ad..8de7badbf 100644
--- a/scripts/find-debuginfo.sh
+++ b/scripts/find-debuginfo.sh
@@ -4,6 +4,8 @@
#
# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m]
# [-o debugfiles.list]
+# [--run-dwz] [--dwz-low-mem-die-limit N]
+# [--dwz-max-die-limit N]
# [[-l filelist]... [-p 'pattern'] -o debuginfo.list]
# [builddir]
#
@@ -20,6 +22,10 @@
# The -p argument is an grep -E -style regexp matching the a file name,
# and must not use anchors (^ or $).
#
+# The --run-dwz flag instructs find-debuginfo.sh to run the dwz utility
+# if available, and --dwz-low-mem-die-limit and --dwz-max-die-limit
+# provide detailed limits. See dwz(1) -l and -L option for details.
+#
# All file names in switches are relative to builddir (. if not given).
#
@@ -35,6 +41,11 @@ include_minidebug=false
# Barf on missing build IDs.
strict=false
+# DWZ parameters.
+run_dwz=false
+dwz_low_mem_die_limit=
+dwz_max_die_limit=
+
BUILDDIR=.
out=debugfiles.list
nout=0
@@ -43,6 +54,17 @@ while [ $# -gt 0 ]; do
--strict-build-id)
strict=true
;;
+ --run-dwz)
+ run_dwz=true
+ ;;
+ --dwz-low-mem-die-limit)
+ dwz_low_mem_die_limit=$2
+ shift
+ ;;
+ --dwz-max-die-limit)
+ dwz_max_die_limit=$2
+ shift
+ ;;
-g)
strip_g=true
;;
@@ -302,6 +324,37 @@ while read nlinks inum f; do
fi
done || exit
+# Invoke the DWARF Compressor utility.
+if $run_dwz && type dwz >/dev/null 2>&1 \
+ && [ -d "${RPM_BUILD_ROOT}/usr/lib/debug" ]; then
+ dwz_files="`cd "${RPM_BUILD_ROOT}/usr/lib/debug"; find -type f -name \*.debug`"
+ if [ -n "${dwz_files}" ]; then
+ dwz_multifile_name="${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}-${RPM_PACKAGE_RELEASE}.${RPM_ARCH}"
+ dwz_multifile_suffix=
+ dwz_multifile_idx=0
+ while [ -f "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz/${dwz_multifile_name}${dwz_multifile_suffix}" ]; do
+ let ++dwz_multifile_idx
+ dwz_multifile_suffix=".${dwz_multifile_idx}"
+ done
+ dwz_multfile_name="${dwz_multifile_name}${dwz_multifile_suffix}"
+ dwz_opts="-h -q -r -m .dwz/${dwz_multifile_name}"
+ mkdir -p "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz"
+ [ -n "${dwz_low_mem_die_limit}" ] \
+ && dwz_opts="${dwz_opts} -l ${dwz_low_mem_die_limit}"
+ [ -n "${dwz_max_die_limit}" ] \
+ && dwz_opts="${dwz_opts} -L ${dwz_max_die_limit}"
+ ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts $dwz_files )
+ # Remove .dwz directory if empty
+ rmdir "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz" 2>/dev/null
+ if [ -f "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz/${dwz_multifile_name}" ]; then
+ id="`readelf -Wn "${RPM_BUILD_ROOT}/usr/lib/debug/.dwz/${dwz_multifile_name}" \
+ 2>/dev/null | sed -n 's/^ Build ID: \([0-9a-f]\+\)/\1/p'`"
+ [ -n "$id" ] \
+ && make_id_link "$id" "/usr/lib/debug/.dwz/${dwz_multifile_name}" .debug
+ fi
+ fi
+fi
+
# For each symlink whose target has a .debug file,
# make a .debug symlink to that file.
find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*" -type l -print |
diff --git a/tests/data/SPECS/hello2.spec b/tests/data/SPECS/hello2.spec
new file mode 100644
index 000000000..01777af5b
--- /dev/null
+++ b/tests/data/SPECS/hello2.spec
@@ -0,0 +1,62 @@
+Summary: hello2 -- double hello, world rpm
+Name: hello2
+Version: 1.0
+Release: 1
+Group: Utilities
+License: GPL
+Distribution: RPM test suite.
+Vendor: Red Hat Software
+Packager: Red Hat Software <bugs@redhat.com>
+URL: http://www.redhat.com
+Source0: hello-1.0.tar.gz
+Patch0: hello-1.0-modernize.patch
+Excludearch: lsi
+Excludeos: cpm
+Provides: hi
+Conflicts: goodbye
+Obsoletes: howdy
+Prefix: /usr
+
+%description
+Simple rpm demonstration.
+
+%prep
+%setup -q -n hello-1.0
+%patch0 -p1 -b .modernize
+
+%build
+make CFLAGS="-g -O1"
+mv hello hello2
+make CFLAGS="-g -O2 -D_FORTIFY_SOURCE=2"
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/local/bin
+make DESTDIR=$RPM_BUILD_ROOT install
+cp hello2 $RPM_BUILD_ROOT/usr/local/bin/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%pre
+
+%post
+
+%preun
+
+%postun
+
+%files
+%defattr(-,root,root)
+%doc FAQ
+#%readme README
+#%license COPYING
+%attr(0751,root,root) /usr/local/bin/hello
+%attr(0751,root,root) /usr/local/bin/hello2
+
+%changelog
+* Wed May 18 2016 Mark Wielaard <mjw@redhat.com>
+- Add hello2 for dwz testing support.
+
+* Tue Oct 20 1998 Jeff Johnson <jbj@redhat.com>
+- create.
diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at
index 3c32842ab..2fea1b621 100644
--- a/tests/rpmbuild.at
+++ b/tests/rpmbuild.at
@@ -381,3 +381,81 @@ readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
[],
[ignore])
AT_CLEANUP
+
+# ------------------------------
+# Check if rpmbuild runs dwz and generates a multi file that with shared
+# debuginfo. This is simply the hello example with one binary build twice
+# so dwz has enough slightly similar debug data.
+AT_SETUP([rpmbuild debuginfo dwz])
+AT_KEYWORDS([build] [debuginfo])
+AT_CHECK([
+rm -rf ${TOPDIR}
+AS_MKDIR_P(${TOPDIR}/SOURCES)
+
+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES
+
+run rpmbuild --quiet \
+ --macros=${abs_top_builddir}/macros:${abs_top_builddir}/tests/testing/usr/local/lib/rpm/platform/%{_target_cpu}-%{_target_os}/macros:${top_srcdir}/macros.debug \
+ --rcfile=${abs_top_builddir}/rpmrc \
+ -ba "${abs_srcdir}"/data/SPECS/hello2.spec
+
+# The debuginfo package should contain a .debug file for each binary
+# and a dwz multi file that contains the shared debuginfo between them.
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \
+ | cpio -diu
+test -f ./usr/lib/debug/usr/local/bin/hello.debug || exit 1
+test -f ./usr/lib/debug/usr/local/bin/hello2.debug || exit 1
+test -f ./usr/lib/debug/.dwz/hello2-1.0-1.* || exit 1
+
+# Make sure the main package binaries contain the correct build-ids
+# linking them to the debug packages.
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \
+ | cpio -diu
+id1=$(file ./usr/local/bin/hello | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+id2=$(file ./usr/local/bin/hello2 | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+id1debug=$(file ./usr/lib/debug/usr/local/bin/hello.debug \
+ | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+id2debug=$(file ./usr/lib/debug/usr/local/bin/hello2.debug \
+ | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+idmulti=$(file ./usr/lib/debug/.dwz/hello2-1.0-1.* \
+ | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+
+test "$id1" = "$id1debug" || exit 1
+test "$id2" = "$id2debug" || exit 1
+
+# The build-id files should link to the .debug files.
+id1file="./usr/lib/debug/.build-id/${id1:0:2}/${id1:2}"
+canonid1file=$(readlink -f ${id1file})
+canonfile1=$(readlink -f ./usr/local/bin/hello)
+canonid1debug=$(readlink -f ${id1file}.debug)
+canondebug1=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug)
+
+test "$canonid1file" = "$canonfile1" || exit 1
+test "$canonid1debug" = "$canondebug1" || exit 1
+
+id2file="./usr/lib/debug/.build-id/${id2:0:2}/${id2:2}"
+canonid2file=$(readlink -f ${id1file})
+canonfile2=$(readlink -f ./usr/local/bin/hello)
+canonid2debug=$(readlink -f ${id1file}.debug)
+canondebug2=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug)
+
+test "$canonid2file" = "$canonfile2" || exit 1
+test "$canonid2debug" = "$canondebug2" || exit 1
+
+# Both .debug files should point to the dwz multi file.
+# It would be nice to also test that they contain the correct dwz build-id
+# but that is a bit hard to grep out of the section data.
+multiref1=$(readelf --string-dump=.gnu_debugaltlink ./usr/lib/debug/usr/local/bin/hello.debug | grep '[ 0]' | cut -c13-)
+multiref2=$(readelf --string-dump=.gnu_debugaltlink ./usr/lib/debug/usr/local/bin/hello2.debug | grep '[ 0]' | cut -c13-)
+
+test "$multiref1" = "$multiref2" || exit 1
+
+canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1)
+canonmultifile=$(readlink -f ./usr/lib/debug/.dwz/hello2-1.0-1.*)
+
+test "$canonmultiref" = "$canonmultifile" || exit 1
+],
+[0],
+[],
+[ignore])
+AT_CLEANUP