[Rpm-maint] [PATCH 2/4] Add dwz debuginfo compression support.

Mark Wielaard mjw at redhat.com
Mon Jun 6 21:00:06 UTC 2016


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 at redhat.com>
---
 macros.debug                 | 13 ++++++++
 macros.in                    |  2 +-
 scripts/find-debuginfo.sh    | 53 ++++++++++++++++++++++++++++++
 tests/data/SPECS/hello2.spec | 62 +++++++++++++++++++++++++++++++++++
 tests/rpmbuild.at            | 78 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 tests/data/SPECS/hello2.spec

diff --git a/macros.debug b/macros.debug
index bb2c02f..6a8432e 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 58b122f..8e831c5 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 5c2c381..8de7bad 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 0000000..01777af
--- /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 at 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 at redhat.com>
+- Add hello2 for dwz testing support.
+
+* Tue Oct 20 1998 Jeff Johnson <jbj at redhat.com>
+- create.
diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at
index 3c32842..2fea1b6 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
-- 
2.5.5



More information about the Rpm-maint mailing list