summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2016-06-14 17:07:13 +0200
committerFlorian Festi <ffesti@redhat.com>2016-07-29 18:28:53 +0200
commit5ef1166ad96e3545784fa5420a49e1b2cd481e8e (patch)
treeeb65de6c1723103349384fae2d6e74ccd817a438
parentbbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 (diff)
downloadrpm-5ef1166ad96e3545784fa5420a49e1b2cd481e8e.tar.gz
Make it possible to have unique build-ids across build versions/releases.
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@redhat.com>
-rw-r--r--macros.in8
-rw-r--r--scripts/find-debuginfo.sh20
-rw-r--r--tests/data/SPECS/hello-r2.spec58
-rw-r--r--tests/rpmbuildid.at96
-rw-r--r--tools/debugedit.c24
5 files changed, 201 insertions, 5 deletions
diff --git a/macros.in b/macros.in
index 508c50f43..c79cfccf1 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 c93b246d2..97837157f 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 000000000..ca5091d10
--- /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@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@redhat.com>
+- Update release for unique build-id generation tests.
+
+* Tue Oct 20 1998 Jeff Johnson <jbj@redhat.com>
+- create.
diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at
index eddca969b..1da63022d 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 cf89312fa..c0147f086 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@redhat.com>, 2002
Based on code by Jakub Jelinek <jakub@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);