[Rpm-maint] [PATCH 1/7] Add find-debuginfo.sh -m minisymtab support.

Mark Wielaard mjw at redhat.com
Tue Jun 14 15:07:08 UTC 2016


Support for minisymtab (a minimal function symbol table in a compressed
section in the main binary) has been in gdb and elfutils based tools
since some years. Fedora has had this as rpm-4.10.0-minidebuginfo.patch
since 2012.

The patch adjusts macros to pass -m to find-debuginfo.sh when
_include_minidebuginfo has been set. find-debuginfo.sh now takes -m
as argument to generate the .gnu_debugdata ELF section to be added
to the main executable.

To support the testcases a new macros.debug is added that is used to
generate debuginfo packages in the rpmbuild.at testsuite.

The original support was added to Fedora rpm by Alexander Larsson.
Lubos Kardos fixed a bug in it when strip -g was used. I added some
configuration macros and two testcases to check the basic support works
and for the strip -g bug.

Signed-off-by: Mark Wielaard <mjw at redhat.com>
---
 Makefile.am               |  3 ++
 macros.debug              | 30 ++++++++++++++++++
 macros.in                 |  8 ++++-
 scripts/find-debuginfo.sh | 37 ++++++++++++++++++++++-
 tests/rpmbuild.at         | 77 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 153 insertions(+), 2 deletions(-)
 create mode 100644 macros.debug

diff --git a/Makefile.am b/Makefile.am
index 939a6a0..157e79d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -198,6 +198,9 @@ macros: $(top_srcdir)/macros.in
 CLEANFILES += macros
 EXTRA_DIST += macros.in
 
+# Used for the testsuite to test creating debuginfo packages
+EXTRA_DIST += macros.debug
+
 noinst_DATA += platform
 platform: $(top_srcdir)/platform.in
 	@$(SED) \
diff --git a/macros.debug b/macros.debug
new file mode 100644
index 0000000..bb2c02f
--- /dev/null
+++ b/macros.debug
@@ -0,0 +1,30 @@
+# macros to include to generate debuginfo
+
+%_enable_debug_packages 1
+%_include_minidebuginfo 1
+
+# Expanded at end of %install scriptlet
+
+%__arch_install_post %{nil}
+
+%__os_install_post \
+    %{_rpmconfigdir}/brp-compress \
+    %{!?__debug_package:\
+    %{_rpmconfigdir}/brp-strip %{__strip} \
+    %{_rpmconfigdir}/brp-strip-comment-note %{__strip} %{__objdump} \
+    } \
+    %{_rpmconfigdir}/brp-strip-static-archive %{__strip} \
+%{nil}
+
+%__spec_install_post\
+    %{?__debug_package:%{__debug_install_post}}\
+    %{__arch_install_post}\
+    %{__os_install_post}\
+%{nil}
+
+%install %{?_enable_debug_packages:%{?buildsubdir:%{debug_package}}}\
+%%install\
+%{nil}
+
+# Should missing buildids terminate a build?
+%_missing_build_ids_terminate_build    1
diff --git a/macros.in b/macros.in
index 9e0cdea..94d0aa8 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} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
+   %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
 %{nil}
 
 #	Template for debug information sub-package.
@@ -448,6 +448,12 @@ package or when debugging this package.\
 #%_missing_build_ids_terminate_build	1
 
 #
+# Include minimal debug information in build binaries.
+# Requires _enable_debug_packages.
+#
+#%_include_minidebuginfo	1
+
+#
 # Use internal dependency generator rather than external helpers?
 %_use_internal_dependency_generator	1
 
diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh
index 17522e0..5c2c381 100644
--- a/scripts/find-debuginfo.sh
+++ b/scripts/find-debuginfo.sh
@@ -2,7 +2,7 @@
 #find-debuginfo.sh - automagically generate debug info and file list
 #for inclusion in an rpm spec file.
 #
-# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r]
+# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m]
 #	 		   [-o debugfiles.list]
 #			   [[-l filelist]... [-p 'pattern'] -o debuginfo.list]
 #			   [builddir]
@@ -29,6 +29,9 @@ strip_g=false
 # with -r arg, pass --reloc-debug-sections to eu-strip.
 strip_r=false
 
+# with -m arg, add minimal debuginfo to binary.
+include_minidebug=false
+
 # Barf on missing build IDs.
 strict=false
 
@@ -43,6 +46,9 @@ while [ $# -gt 0 ]; do
   -g)
     strip_g=true
     ;;
+  -m)
+    include_minidebug=true
+    ;;
   -o)
     if [ -z "${lists[$nout]}" -a -z "${ptns[$nout]}" ]; then
       out=$2
@@ -106,6 +112,32 @@ strip_to_debug()
   chmod 444 "$1" || exit
 }
 
+add_minidebug()
+{
+  local debuginfo="$1"
+  local binary="$2"
+
+  local dynsyms=`mktemp`
+  local funcsyms=`mktemp`
+  local keep_symbols=`mktemp`
+  local mini_debuginfo=`mktemp`
+
+  # Extract the dynamic symbols from the main binary, there is no need to also have these
+  # in the normal symbol table
+  nm -D "$binary" --format=posix --defined-only | awk '{ print $1 }' | sort > "$dynsyms"
+  # Extract all the text (i.e. function) symbols from the debuginfo
+  nm "$debuginfo" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > "$funcsyms"
+  # Keep all the function symbols not already in the dynamic symbol table
+  comm -13 "$dynsyms" "$funcsyms" > "$keep_symbols"
+  # Copy the full debuginfo, keeping only a minumal set of symbols and removing some unnecessary sections
+  objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols="$keep_symbols" "$debuginfo" "$mini_debuginfo" &> /dev/null
+  #Inject the compressed data into the .gnu_debugdata section of the original binary
+  xz "$mini_debuginfo"
+  mini_debuginfo="${mini_debuginfo}.xz"
+  objcopy --add-section .gnu_debugdata="$mini_debuginfo" "$binary"
+  rm -f "$dynsyms" "$funcsyms" "$keep_symbols" "$mini_debuginfo"
+}
+
 # Make a relative symlink to $1 called $3$2
 shopt -s extglob
 link_relative()
@@ -261,6 +293,9 @@ while read nlinks inum f; do
     chmod u-w "$f"
   fi
 
+  # strip -g implies we have full symtab, don't add mini symtab in that case.
+  $strip_g || ($include_minidebug && add_minidebug "${debugfn}" "$f")
+
   if [ -n "$id" ]; then
     make_id_link "$id" "$dn/$(basename $f)"
     make_id_link "$id" "/usr/lib/debug$dn/$bn" .debug
diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at
index a70d420..3c32842 100644
--- a/tests/rpmbuild.at
+++ b/tests/rpmbuild.at
@@ -304,3 +304,80 @@ runroot rpm2cpio \
 [],
 [])
 AT_CLEANUP
+
+# ------------------------------
+# Check if rpmbuild creates the minisymtab section in the main hello binary
+AT_SETUP([rpmbuild debuginfo minisymtab])
+AT_KEYWORDS([build] [debuginfo])
+AT_CHECK([
+rm -rf ${TOPDIR}
+
+# Use macros.debug to generate a debuginfo package.
+export CFLAGS="-g"
+run rpmbuild --quiet \
+  --macros=${abs_top_builddir}/macros:${top_srcdir}/macros.debug \
+  --rcfile=${abs_top_builddir}/rpmrc \
+  --rebuild "${abs_srcdir}"/data/SRPMS/hello-1.0-1.src.rpm
+
+# Extract the main package and inspect the hello binary
+# It should contain .gnu_debugdata, but not the full .symtab
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm | cpio -diu
+test -f ./usr/local/bin/hello || exit 1
+readelf -S ./usr/local/bin/hello |\
+   grep -q .gnu_debugdata; test $? == 0 || exit 1
+readelf -S ./usr/local/bin/hello \
+  | grep -q .symtab; test $? == 1 || exit 1
+
+# And the opposite for the debuginfo package
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \
+  | cpio -diu
+test -f ./usr/lib/debug/usr/local/bin/hello*.debug || exit 1
+readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
+  | grep -q .gnu_debugdata; test $? == 1 || exit 1
+readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
+  | grep -q .symtab; test $? == 0 || exit 1
+],
+[0],
+[],
+[ignore])
+AT_CLEANUP
+
+# ------------------------------
+# Check if rpmbuild doesn't create the minisymtab section if we keep symtab
+# Some package might want to use strip -g to keep the symbol table and only
+# but the debug symbols/info in the debuginfo package.
+AT_SETUP([rpmbuild debuginfo minisymtab strip -g])
+AT_KEYWORDS([build] [debuginfo])
+AT_CHECK([
+rm -rf ${TOPDIR}
+
+# Use macros.debug to generate a debuginfo package.
+export CFLAGS="-g"
+run rpmbuild --quiet \
+  --macros=${abs_top_builddir}/macros:${top_srcdir}/macros.debug \
+  --rcfile=${abs_top_builddir}/rpmrc \
+  --define="_find_debuginfo_opts -g" \
+  --rebuild "${abs_srcdir}"/data/SRPMS/hello-1.0-1.src.rpm
+
+# Extract the main package and inspect the hello binary
+# It should contain .symtab (because of strip -g), so doesn't .gnu_debugdata.
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm | cpio -diu
+test -f ./usr/local/bin/hello || exit 1
+readelf -S ./usr/local/bin/hello \
+  | grep -q .gnu_debugdata; test $? == 1 || exit 1
+readelf -S ./usr/local/bin/hello \
+  | grep -q .symtab; test $? == 0 || exit 1
+
+# The debuginfo package should contain neither. The .symtab is NOBITS.
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \
+  | cpio -diu
+test -f ./usr/lib/debug/usr/local/bin/hello*.debug || exit 1
+readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
+  | grep -q .gnu_debugdata; test $? == 1 || exit 1
+readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
+  | grep .symtab | grep -q NOBITS; test $? == 0 || exit 1
+],
+[0],
+[],
+[ignore])
+AT_CLEANUP
-- 
2.5.5



More information about the Rpm-maint mailing list