[Rpm-maint] [PATCH] Make it possible to have unique build-ids across build versions/releases.

Mark Wielaard mjw at redhat.com
Thu Jun 9 11:14:03 UTC 2016


Introduce a new macro _unique_build_ids that when set will pass the
version and release to find-debuginfo.sh and debugedit to recalculate
the build-id of ELF files.

Includes two new testcases to make sure the new setting works as expected
both when set and unset.

Signed-off-by: Mark Wielaard <mjw at redhat.com>
---
 macros.in                      |  8 +++-
 scripts/find-debuginfo.sh      | 20 ++++++++-
 tests/data/SPECS/hello-r2.spec | 58 +++++++++++++++++++++++++
 tests/rpmbuildid.at            | 96 +++++++++++++++++++++++++++++++++++++++++-
 tools/debugedit.c              | 24 ++++++++++-
 5 files changed, 201 insertions(+), 5 deletions(-)
 create mode 100644 tests/data/SPECS/hello-r2.spec

diff --git a/macros.in b/macros.in
index 508c50f..c79cfcc 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_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
+   %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\
 %{nil}
 
 #	Template for debug information sub-package.
@@ -481,6 +481,12 @@ package or when debugging this package.\
 #   ELF /usr/lib/debug/.build-id/xx/yyy -> /usr/lib/.build-id/xx/yyy
 %_build_id_links compat
 
+# Whether build-ids should be made unique between package version/releases
+# when generating debuginfo packages. If set to 1 this will pass
+# --ver-rel "%{version}-%{release}" to find-debuginfo.sh which will pass it
+# onto debugedit --build-id-seed to be used to prime the build-id note hash.
+%_unique_build_ids	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 c93b246..9783715 100644
--- a/scripts/find-debuginfo.sh
+++ b/scripts/find-debuginfo.sh
@@ -6,6 +6,7 @@
 #	 		   [-o debugfiles.list]
 #			   [--run-dwz] [--dwz-low-mem-die-limit N]
 #			   [--dwz-max-die-limit N]
+#			   [--ver-rel VERSION-RELEASE]
 #			   [[-l filelist]... [-p 'pattern'] -o debuginfo.list]
 #			   [builddir]
 #
@@ -26,6 +27,12 @@
 # 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.
 #
+# If --ver-rel VERSION-RELEASE is given then debugedit is called to
+# update the build-ids it finds adding the VERSION-RELEASE string as
+# seed to recalculate the build-id hash.  This makes sure the
+# build-ids in the ELF files are unique between versions and releases
+# of the same package.
+#
 # All file names in switches are relative to builddir (. if not given).
 #
 
@@ -49,6 +56,9 @@ run_dwz=false
 dwz_low_mem_die_limit=
 dwz_max_die_limit=
 
+# Version and release of the spec. Given by --ver-rel
+ver_rel=
+
 BUILDDIR=.
 out=debugfiles.list
 nout=0
@@ -68,6 +78,10 @@ while [ $# -gt 0 ]; do
     dwz_max_die_limit=$2
     shift
     ;;
+  --ver-rel)
+    ver_rel=$2
+    shift
+    ;;
   -g)
     strip_g=true
     ;;
@@ -238,8 +252,12 @@ while read nlinks inum f; do
   fi
 
   echo "extracting debug info from $f"
+  build_id_seed=
+  if [ ! -z "$ver_rel" ]; then
+    build_id_seed="--build-id-seed=$ver_rel"
+  fi
   id=$(${lib_rpm_dir}/debugedit -b "$RPM_BUILD_DIR" -d /usr/src/debug \
-			      -i -l "$SOURCEFILE" "$f") || exit
+			      -i $build_id_seed -l "$SOURCEFILE" "$f") || exit
   if [ $nlinks -gt 1 ]; then
     eval linkedid_$inum=\$id
   fi
diff --git a/tests/data/SPECS/hello-r2.spec b/tests/data/SPECS/hello-r2.spec
new file mode 100644
index 0000000..ca5091d
--- /dev/null
+++ b/tests/data/SPECS/hello-r2.spec
@@ -0,0 +1,58 @@
+Summary: hello -- hello, world rpm
+Name: hello
+Version: 1.0
+Release: 2
+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
+%patch0 -p1 -b .modernize
+
+%build
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/local/bin
+make DESTDIR=$RPM_BUILD_ROOT install
+
+%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
+
+%changelog
+* Wed Jun  8 2016 Mark Wielaard <mjw at redhat.com>
+- Update release for unique build-id generation tests.
+
+* Tue Oct 20 1998 Jeff Johnson <jbj at redhat.com>
+- create.
diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at
index eddca96..1da6302 100644
--- a/tests/rpmbuildid.at
+++ b/tests/rpmbuildid.at
@@ -758,4 +758,98 @@ debug id in debug package
 debug dup id in debug package
 ],
 [])
-AT_CLEANUP
\ No newline at end of file
+AT_CLEANUP
+
+# ------------------------------
+# Check build-ids are unique between versions/releases
+# with _unique_build_ids defined.
+AT_SETUP([rpmbuild buildid unique r1 r2])
+AT_KEYWORDS([build] [debuginfo] [buildid])
+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
+
+# No warnings for hard links
+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 \
+  --define="_unique_build_ids 1" \
+  -ba "${abs_srcdir}"/data/SPECS/hello.spec
+
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \
+  | cpio -diu --quiet
+
+hello_file=./usr/local/bin/hello
+
+# Extract the build-id from the main file
+id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+
+# Build the "next" release, which has no changes except for the release update.
+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 \
+  --define="_unique_build_ids 1" \
+  -ba "${abs_srcdir}"/data/SPECS/hello-r2.spec
+
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \
+  | cpio -diu --quiet
+
+# Extract the build-id from the main file
+id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+
+if test "$id1" == "$id2"; then echo "equal $id1"; else echo "unequal"; fi
+],
+[0],
+[unequal
+],
+[ignore])
+AT_CLEANUP
+
+# ------------------------------
+# Check build-ids are non-unique between versions/releases
+# with _unique_build_ids undefined (and exact same sources).
+AT_SETUP([rpmbuild buildid non-unique r1 r2])
+AT_KEYWORDS([build] [debuginfo] [buildid])
+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
+
+# No warnings for hard links
+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 \
+  --undefine="_unique_build_ids" \
+  -ba "${abs_srcdir}"/data/SPECS/hello.spec
+
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \
+  | cpio -diu --quiet
+
+hello_file=./usr/local/bin/hello
+
+# Extract the build-id from the main file
+id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+
+# Build the "next" release, which has no changes except for the release update.
+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 \
+  --undefine="_unique_build_ids" \
+  -ba "${abs_srcdir}"/data/SPECS/hello-r2.spec
+
+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \
+  | cpio -diu --quiet
+
+# Extract the build-id from the main file
+id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
+
+if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi
+],
+[0],
+[equal
+],
+[ignore])
+AT_CLEANUP
diff --git a/tools/debugedit.c b/tools/debugedit.c
index cf89312..c0147f0 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009, 2010, 2011 Red Hat, Inc.
+/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016 Red Hat, Inc.
    Written by Alexander Larsson <alexl at redhat.com>, 2002
    Based on code by Jakub Jelinek <jakub at redhat.com>, 2001.
 
@@ -54,6 +54,7 @@ char *dest_dir = NULL;
 char *list_file = NULL;
 int list_file_fd = -1;
 int do_build_id = 0;
+char *build_id_seed = NULL;
 
 typedef struct
 {
@@ -1296,6 +1297,8 @@ static struct poptOption optionsTable[] = {
       "file where to put list of source and header file names", NULL },
     { "build-id",  'i', POPT_ARG_NONE, &do_build_id, 0,
       "recompute build ID note and print ID on stdout", NULL },
+    { "build-id-seed", 's', POPT_ARG_STRING, &build_id_seed, 0,
+      "if recomputing the build ID note use this string as hash seed", NULL },
       POPT_AUTOHELP
     { NULL, 0, 0, NULL, 0, NULL, NULL }
 };
@@ -1400,7 +1403,7 @@ handle_build_id (DSO *dso, Elf_Data *build_id,
       exit (1);
     }
 
-  if (!dirty_elf)
+  if (!dirty_elf && build_id_seed == NULL)
     goto print;
 
   if (elf_update (dso->elf, ELF_C_NULL) < 0)
@@ -1415,6 +1418,10 @@ handle_build_id (DSO *dso, Elf_Data *build_id,
 
   ctx = rpmDigestInit(algorithm, 0);
 
+  /* If a seed string was given use it to prime the hash.  */
+  if (build_id_seed != NULL)
+    rpmDigestUpdate(ctx, build_id_seed, strlen (build_id_seed));
+
   /* Slurp the relevant header bits and section contents and feed them
      into the hash function.  The only bits we ignore are the offset
      fields in ehdr and shdrs, since the semantically identical ELF file
@@ -1541,6 +1548,19 @@ main (int argc, char *argv[])
 	}
     }
 
+  if (build_id_seed != NULL && do_build_id == 0)
+    {
+      fprintf (stderr, "--build-id-seed (-s) needs --build-id (-i)\n");
+      exit (1);
+    }
+
+  if (build_id_seed != NULL && strlen (build_id_seed) < 1)
+    {
+      fprintf (stderr,
+	       "--build-id-seed (-s) string should be at least 1 char\n");
+      exit (1);
+    }
+
   /* Ensure clean paths, users can muck with these */
   if (base_dir)
     canonicalize_path(base_dir, base_dir);
-- 
2.5.5



More information about the Rpm-maint mailing list