diff --git a/0001-Add-OpenSSL-support-for-digest-and-signatures.patch b/0001-Add-OpenSSL-support-for-digest-and-signatures.patch deleted file mode 100644 index 9026897..0000000 --- a/0001-Add-OpenSSL-support-for-digest-and-signatures.patch +++ /dev/null @@ -1,1169 +0,0 @@ -From 64c75ba68118e47f65eedf15855d8a50deeebcd1 Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Mon, 16 Jan 2017 09:19:43 -0500 -Subject: [PATCH] Add OpenSSL support for digest and signatures - -Autotools: add --with-crypto=openssl -This enables RPM to locate the appropriate flags for compiling -against OpenSSL for digest and hash functions. - -This implementation changes the old behavior of ---with[out]-beecrypt toggling between beecrypt and nss. It will -now throw an error if attempting to use --with-beecrypt -indicating that the user should instead use --with-crypto= - -See also: -https://github.com/rpm-software-management/rpm/issues/119 - -(cherry picked from commit 64028f9a1c25ada8ffc7a48775f526600edcbf85) ---- - INSTALL | 27 +- - Makefile.am | 17 +- - configure.ac | 115 ++++++- - rpmio/Makefile.am | 6 + - rpmio/digest_openssl.c | 838 +++++++++++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 982 insertions(+), 21 deletions(-) - create mode 100644 rpmio/digest_openssl.c - -diff --git a/INSTALL b/INSTALL -index 60536e316..8eefef799 100644 ---- a/INSTALL -+++ b/INSTALL -@@ -9,17 +9,34 @@ The libmagic (aka file) library for file type detection (used by rpmbuild). - The source for the file utility + library is available from - ftp://ftp.astron.com/pub/file/ - --The NSS >= 3.12 library for encryption, and NSPR library which NSS uses. --Both NSPR and NSS libraries and headers need to be installed during RPM --compilation. As NSPR and NSS typically install their headers outside --the regular include search path, you need to tell configure about this, --eg something like: -+You will need a cryptographic library to support digests and signatures. -+This library may be Mozilla NSS, OpenSSL or beecrypt. Which library to use -+must be specified with the --with-crypto=[beecrypt|nss|openssl] argument -+to configure. -+ -+If using the Mozilla NSS library for encyption (and NSPR library which -+NSS uses) it must be version 3.12 or later. Both NSPR and NSS libraries and -+headers need to be installed during RPM compilation. As NSPR and NSS -+typically install their headers outside the regular include search path, -+you need to tell configure about this, eg something like: - ./configure <......> CPPFLAGS="-I/usr/include/nspr -I/usr/include/nss" - - The NSPR and NSS libraries are available from - http://www.mozilla.org/projects/security/pki/nss/ - http://www.mozilla.org/projects/nspr/ - -+If using the OpenSSL library for encryption, it must be version 1.0.2 or -+later. Note: when compiling against OpenSSL, there is a possible license -+incompatibility. For more details on this, see -+https://people.gnome.org/~markmc/openssl-and-the-gpl.html -+Some Linux distributions have different legal interpretations of this -+possible incompatibility. It is recommended to consult with a lawyer before -+building RPM against OpenSSL. -+Fedora: https://fedoraproject.org/wiki/Licensing:FAQ#What.27s_the_deal_with_the_OpenSSL_license.3F -+Debian: https://lists.debian.org/debian-legal/2002/10/msg00113.html -+ -+The OpenSSL crypto library is available from https://www.openssl.org/ -+ - The Berkeley DB >= 4.3.x (4.5.x or newer recommended) is required for the - default database backend. BDB can be downloaded from - http://www.oracle.com/technology/software/products/berkeley-db/index.html -diff --git a/Makefile.am b/Makefile.am -index 6b37b5898..42a77c0d4 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -41,6 +41,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/build - AM_CPPFLAGS += -I$(top_srcdir)/lib - AM_CPPFLAGS += -I$(top_srcdir)/rpmio - AM_CPPFLAGS += @WITH_NSS_INCLUDE@ -+AM_CPPFLAGS += @WITH_OPENSSL_INCLUDE@ - AM_CPPFLAGS += @WITH_POPT_INCLUDE@ - AM_CPPFLAGS += -I$(top_srcdir)/misc - AM_CPPFLAGS += -DLOCALEDIR="\"$(localedir)\"" -@@ -113,45 +114,45 @@ rpm_SOURCES = rpmqv.c debug.h system.h - rpm_CPPFLAGS = $(AM_CPPFLAGS) -DIAM_RPMEIU -DIAM_RPMQ -DIAM_RPMV - rpm_LDADD = libcliutils.la - rpm_LDADD += lib/librpm.la rpmio/librpmio.la --rpm_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpm_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpmdb_SOURCES = rpmdb.c debug.h system.h - rpmdb_CPPFLAGS = $(AM_CPPFLAGS) - rpmdb_LDADD = libcliutils.la - rpmdb_LDADD += lib/librpm.la rpmio/librpmio.la --rpmdb_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpmdb_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpmkeys_SOURCES = rpmkeys.c debug.h system.h - rpmkeys_CPPFLAGS = $(AM_CPPFLAGS) - rpmkeys_LDADD = libcliutils.la - rpmkeys_LDADD += lib/librpm.la rpmio/librpmio.la --rpmkeys_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpmkeys_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpmsign_SOURCES = rpmsign.c debug.h system.h - rpmsign_CPPFLAGS = $(AM_CPPFLAGS) - rpmsign_LDADD = libcliutils.la - rpmsign_LDADD += sign/librpmsign.la lib/librpm.la rpmio/librpmio.la --rpmsign_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpmsign_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpmbuild_SOURCES = rpmbuild.c debug.h system.h - rpmbuild_CPPFLAGS = $(AM_CPPFLAGS) - rpmbuild_LDADD = libcliutils.la - rpmbuild_LDADD += build/librpmbuild.la lib/librpm.la rpmio/librpmio.la --rpmbuild_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpmbuild_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpmspec_SOURCES = rpmspec.c debug.h system.h - rpmspec_CPPFLAGS = $(AM_CPPFLAGS) - rpmspec_LDADD = libcliutils.la - rpmspec_LDADD += build/librpmbuild.la lib/librpm.la rpmio/librpmio.la --rpmspec_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpmspec_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpm2cpio_SOURCES = rpm2cpio.c debug.h system.h - rpm2cpio_LDADD = lib/librpm.la rpmio/librpmio.la --rpm2cpio_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ -+rpm2cpio_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ - - rpm2archive_SOURCES = rpm2archive.c debug.h system.h - rpm2archive_LDADD = lib/librpm.la rpmio/librpmio.la --rpm2archive_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ @WITH_ARCHIVE_LIB@ -+rpm2archive_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ @WITH_ARCHIVE_LIB@ - - - if LIBELF -diff --git a/configure.ac b/configure.ac -index 91fadbade..d21b67220 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -243,18 +243,30 @@ AC_CHECK_HEADERS([dwarf.h], [ - AM_CONDITIONAL(LIBDWARF,[test "$WITH_LIBDWARF" = yes]) - - #================= -+# Select crypto library -+AC_ARG_WITH(crypto, -+ [AC_HELP_STRING([--with-crypto=CRYPTO_LIB], -+ [The cryptographic library to use (nss|beecrypt|openssl). The default is nss.]) -+ ],[], -+ [with_crypto=nss]) -+ -+# Refuse to proceed if someone specified --with-beecrypt (removed) -+AC_ARG_WITH(beecrypt, -+ [AC_HELP_STRING([--with-beecrypt (OBSOLETE)], [Obsolete argument. Use --with-crypto=beecrypt]) -+ ],[AC_MSG_ERROR([--with-beecrypt no longer supported. Use --with-crypto=beecrypt])], -+ []) -+ - # Check for beecrypt library if requested. --AC_ARG_WITH(beecrypt, [ --with-beecrypt build with beecrypt support ],,[with_beecrypt=no]) - AC_ARG_WITH(internal_beecrypt, [ --with-internal-beecrypt build with internal beecrypt library ],,[with_internal_beecrypt=no]) - AM_CONDITIONAL([WITH_INTERNAL_BEECRYPT],[test "$with_internal_beecrypt" = yes]) - if test "$with_internal_beecrypt" = yes ; then -- with_beecrypt=yes -+ with_crypto=beecrypt - fi --AM_CONDITIONAL([WITH_BEECRYPT],[test "$with_beecrypt" = yes]) -+AM_CONDITIONAL([WITH_BEECRYPT],[test "$with_crypto" = beecrypt]) - - WITH_BEECRYPT_INCLUDE= - WITH_BEECRYPT_LIB= --if test "$with_beecrypt" = yes ; then -+if test "$with_crypto" = beecrypt ; then - AC_DEFINE(WITH_BEECRYPT, 1, [Build with beecrypt instead of nss3 support?]) - if test "$with_internal_beecrypt" = yes ; then - WITH_BEECRYPT_INCLUDE="-I\$(top_srcdir)/beecrypt" -@@ -263,7 +275,7 @@ if test "$with_beecrypt" = yes ; then - AC_CHECK_LIB(beecrypt, mpfprintln, [ - WITH_BEECRYPT_LIB="-lbeecrypt" - ],[ -- AC_MSG_ERROR([missing required library 'beecrypt']) -+ AC_MSG_ERROR([missing required library 'beecrypt']) - ]) - AC_CHECK_HEADER([beecrypt/api.h], [AC_DEFINE(HAVE_BEECRYPT_API_H, 1, [Define to 1 if you have the header file.]) - ]) -@@ -273,13 +285,100 @@ AC_SUBST(WITH_BEECRYPT_LIB) - AC_SUBST(WITH_BEECRYPT_INCLUDE) - - #================= -+# Check for OpenSSL library. -+# We need evp.h from OpenSSL. -+ -+WITH_OPENSSL_INCLUDE= -+WITH_OPENSSL_LIB= -+if test "$with_crypto" = openssl; then -+# If we have pkgconfig make sure CPPFLAGS are setup correctly for the OpenSSL -+# -I include path. -+AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no], [$PATH:/usr/bin:/usr/local/bin]) -+if test "x$PKGCONFIG" != "xno"; then -+ CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags libcrypto)" -+ WITH_OPENSSL_LIB=$($PKGCONFIG --libs libcrypto) -+else -+ WITH_OPENSSL_LIB=-lcrypto -+fi -+ -+AC_CHECK_HEADERS([openssl/evp.h], [], [ -+ AC_MSG_ERROR([missing required OpenSSL header]) -+]) -+AC_CHECK_HEADERS([openssl/rsa.h], [], [ -+ AC_MSG_ERROR([missing required OpenSSL header]) -+]) -+AC_CHECK_HEADERS([openssl/dsa.h], [], [ -+ AC_MSG_ERROR([missing required OpenSSL header]) -+]) -+ -+AC_CHECK_LIB(crypto, EVP_DigestInit_ex, [], [ -+ AC_MSG_ERROR([required OpenSSL library 'libcrypto' missing or too old]) -+]) -+ -+AC_CHECK_LIB(crypto, EVP_MD_CTX_new, [ -+ AC_DEFINE(HAVE_EVP_MD_CTX_NEW, 1, [Define to 1 if OpenSSL has EVP_MD_CTX_new]) -+ AC_SUBST(HAVE_EVP_MD_CTX_NEW, [1]) -+ ], [ -+ AC_CHECK_LIB(crypt, EVP_MD_CTX_create, [], [ -+ AC_MSG_ERROR([required OpenSSL library 'libcrypto' missing or too old]) -+ ]) -+]) -+ -+AC_CHECK_LIB(crypto, EVP_PKEY_CTX_new, [], [ -+ AC_MSG_ERROR([required OpenSSL library 'libcrypto' missing or too old]) -+]) -+ -+AC_CHECK_LIB(crypto, DSA_set0_key, [ -+ AC_DEFINE(HAVE_DSA_SET0_KEY, 1, [Define to 1 if OpenSSL has DSA_set0_key]) -+ AC_SUBST(HAVE_DSA_SET0_KEY, [1]) -+ ], [] -+) -+ -+AC_CHECK_LIB(crypto, DSA_set0_pqg, [ -+ AC_DEFINE(HAVE_DSA_SET0_PQG, 1, [Define to 1 if OpenSSL has DSA_set0_pqg]) -+ AC_SUBST(HAVE_DSA_SET0_PQG, [1]) -+ ], [] -+) -+ -+AC_CHECK_LIB(crypto, DSA_SIG_set0, [ -+ AC_DEFINE(HAVE_DSA_SIG_SET0, 1, [Define to 1 if OpenSSL has DSA_SIG_set0]) -+ AC_SUBST(HAVE_DSA_SIG_SET0, [1]) -+ ], [] -+) -+ -+AC_CHECK_LIB(crypto, RSA_set0_key, [ -+ AC_DEFINE(HAVE_RSA_SET0_KEY, 1, [Define to 1 if OpenSSL has RSA_set0_key]) -+ AC_SUBST(HAVE_RSA_SET0_KEY, [1]) -+ ], [] -+) -+ -+AC_CHECK_LIB(crypto, BN_bn2binpad, [ -+ AC_DEFINE(HAVE_BN2BINPAD, 1, [Define to 1 if OpenSSL has BN_bn2binpad]) -+ AC_SUBST(HAVE_BN2BINPAD, [1]) -+ ], [] -+) -+ -+fi -+ -+AM_CONDITIONAL([WITH_OPENSSL],[test "$with_crypto" = openssl]) -+AC_SUBST(WITH_OPENSSL_INCLUDE) -+AC_SUBST(WITH_OPENSSL_LIB) -+ -+#================= - # Check for NSS library. --# We need nss.h from NSS which needs nspr.h. Unfortunately both glibc and NSS --# have a header named nss.h... so make extra check for NSS's sechash.h -+# We need nss.h from NSS which needs nspr.h. Unfortunately both glibc and NSS -+# have a header named nss.h... so make extra check for NSS's sechash.h - # which we use too and hopefully is slightly more unique to NSS. - WITH_NSS_INCLUDE= - WITH_NSS_LIB= --if test "$with_beecrypt" != yes ; then -+if test "$with_crypto" = nss; then -+# If we have pkgconfig make sure CPPFLAGS are setup correctly for the nss -+# -I include path. Otherwise the below checks will fail because nspr.h -+# cannot be found. -+AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no], [$PATH:/usr/bin:/usr/local/bin]) -+if test "x$PKGCONFIG" != "xno"; then -+ CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags nss)" -+fi - AC_CHECK_HEADERS([nspr.h nss.h sechash.h], [], [ - AC_MSG_ERROR([missing required NSPR / NSS header]) - ]) -diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am -index 68a821934..9062f58a5 100644 ---- a/rpmio/Makefile.am -+++ b/rpmio/Makefile.am -@@ -5,6 +5,7 @@ include $(top_srcdir)/rpm.am - AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/ - AM_CPPFLAGS += @WITH_NSS_INCLUDE@ - AM_CPPFLAGS += @WITH_BEECRYPT_INCLUDE@ -+AM_CPPFLAGS += @WITH_OPENSSL_INCLUDE@ - AM_CPPFLAGS += @WITH_POPT_INCLUDE@ - AM_CPPFLAGS += -I$(top_srcdir)/misc - AM_CPPFLAGS += -DRPMCONFIGDIR="\"@RPMCONFIGDIR@\"" -@@ -23,8 +24,12 @@ librpmio_la_SOURCES = \ - if WITH_BEECRYPT - librpmio_la_SOURCES += digest_beecrypt.c - else -+if WITH_OPENSSL -+librpmio_la_SOURCES += digest_openssl.c -+else - librpmio_la_SOURCES += digest_nss.c - endif -+endif - - - librpmio_la_LDFLAGS = -version-info $(rpm_version_info) -@@ -32,6 +37,7 @@ librpmio_la_LIBADD = \ - ../misc/libmisc.la \ - @WITH_NSS_LIB@ \ - @WITH_BEECRYPT_LIB@ \ -+ @WITH_OPENSSL_LIB@ \ - @WITH_BZ2_LIB@ \ - @WITH_ZLIB_LIB@ \ - @WITH_LIBELF_LIB@ \ -diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c -new file mode 100644 -index 000000000..aea460e39 ---- /dev/null -+++ b/rpmio/digest_openssl.c -@@ -0,0 +1,838 @@ -+#include "system.h" -+ -+#include -+#include -+#include -+#include -+ -+#include "rpmio/digest.h" -+ -+ -+/* Compatibility functions for OpenSSL 1.0.2 */ -+ -+#ifndef HAVE_EVP_MD_CTX_NEW -+# define EVP_MD_CTX_new EVP_MD_CTX_create -+# define EVP_MD_CTX_free EVP_MD_CTX_destroy -+#endif -+ -+#ifndef HAVE_RSA_SET0_KEY -+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); -+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) -+{ -+ if (!r) return 0; -+ -+ if (n) { -+ r->n = n; -+ } -+ -+ if (e) { -+ r->e = e; -+ } -+ -+ if (d) { -+ r->d = d; -+ } -+ -+ return 1; -+} -+#endif /* HAVE_RSA_SET0_KEY */ -+ -+#ifndef HAVE_DSA_SET0_KEY -+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); -+ -+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) -+{ -+ if (!d) return 0; -+ -+ if (pub_key) { -+ d->pub_key = pub_key; -+ } -+ -+ if (priv_key) { -+ d->priv_key = priv_key; -+ } -+ -+ return 1; -+} -+#endif /* HAVE_DSA_SET0_KEY */ -+ -+#ifndef HAVE_DSA_SET0_PQG -+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); -+ -+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) -+{ -+ if (!d) return 0; -+ -+ if (p) { -+ d->p = p; -+ } -+ -+ if (q) { -+ d->q = q; -+ } -+ -+ if (g) { -+ d->g = g; -+ } -+ -+ return 1; -+} -+#endif /* HAVE_DSA_SET0_PQG */ -+ -+#ifndef HAVE_DSA_SIG_SET0 -+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); -+ -+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) -+{ -+ if (!sig) return 0; -+ -+ if (r) { -+ sig->r = r; -+ } -+ -+ if (s) { -+ sig->s = s; -+ } -+ -+ return 1; -+} -+#endif /* HAVE_DSA_SIG_SET0 */ -+ -+#ifndef HAVE_BN2BINPAD -+static int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) -+{ -+ int i; -+ -+ i = BN_num_bytes(a); -+ if (tolen < i) -+ return -1; -+ -+ /* Add leading zeroes if necessary */ -+ if (tolen > i) { -+ memset(to, 0, tolen - i); -+ to += tolen - i; -+ } -+ -+ BN_bn2bin(a, to); -+ -+ return tolen; -+} -+#endif /* HAVE_BN2BINPAD */ -+ -+struct DIGEST_CTX_s { -+ rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */ -+ int algo; /*!< Used hash algorithm */ -+ -+ EVP_MD_CTX *md_ctx; /* Digest context (opaque) */ -+ -+}; -+ -+/**************************** init ************************************/ -+ -+int rpmInitCrypto(void) { -+ return 0; -+} -+ -+int rpmFreeCrypto(void) { -+ return 0; -+} -+ -+/**************************** digest ************************************/ -+ -+DIGEST_CTX rpmDigestDup(DIGEST_CTX octx) -+{ -+ if (!octx) return NULL; -+ -+ DIGEST_CTX nctx = NULL; -+ nctx = xcalloc(1, sizeof(*nctx)); -+ -+ nctx->flags = octx->flags; -+ nctx->algo = octx->algo; -+ nctx->md_ctx = EVP_MD_CTX_new(); -+ if (!nctx->md_ctx) { -+ free(nctx); -+ return NULL; -+ } -+ -+ if (!EVP_MD_CTX_copy(nctx->md_ctx, octx->md_ctx)) { -+ free(nctx); -+ return NULL; -+ } -+ -+ return nctx; -+} -+ -+static const EVP_MD *getEVPMD(int hashalgo) -+{ -+ switch (hashalgo) { -+ -+ case PGPHASHALGO_MD5: -+ return EVP_md5(); -+ -+ case PGPHASHALGO_SHA1: -+ return EVP_sha1(); -+ -+ case PGPHASHALGO_RIPEMD160: -+ return EVP_ripemd160(); -+ -+ case PGPHASHALGO_MD2: -+ return EVP_md2(); -+ -+ case PGPHASHALGO_SHA256: -+ return EVP_sha256(); -+ -+ case PGPHASHALGO_SHA384: -+ return EVP_sha384(); -+ -+ case PGPHASHALGO_SHA512: -+ return EVP_sha512(); -+ -+ case PGPHASHALGO_SHA224: -+ return EVP_sha224(); -+ -+ default: -+ return EVP_md_null(); -+ } -+} -+ -+size_t rpmDigestLength(int hashalgo) -+{ -+ return EVP_MD_size(getEVPMD(hashalgo)); -+} -+ -+DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags) -+{ -+ DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx)); -+ -+ ctx->md_ctx = EVP_MD_CTX_new(); -+ if (!ctx->md_ctx) { -+ free(ctx); -+ return NULL; -+ } -+ -+ const EVP_MD *md = getEVPMD(hashalgo); -+ if (md == EVP_md_null()) { -+ free(ctx->md_ctx); -+ free(ctx); -+ return NULL; -+ } -+ -+ ctx->algo = hashalgo; -+ ctx->flags = flags; -+ if (!EVP_DigestInit_ex(ctx->md_ctx, md, NULL)) { -+ free(ctx->md_ctx); -+ free(ctx); -+ return NULL; -+ } -+ -+ return ctx; -+} -+ -+int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len) -+{ -+ if (ctx == NULL) return -1; -+ -+ EVP_DigestUpdate(ctx->md_ctx, data, len); -+ -+ return 0; -+} -+ -+int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii) -+{ -+ int ret; -+ unsigned char *digest = NULL; -+ unsigned int digestlen; -+ -+ if (ctx == NULL) return -1; -+ -+ digestlen = EVP_MD_CTX_size(ctx->md_ctx); -+ digest = xcalloc(digestlen, sizeof(*digest)); -+ -+ ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, &digestlen); -+ if (ret != 1) goto done; -+ -+ if (!asAscii) { -+ /* Raw data requested */ -+ if (lenp) *lenp = digestlen; -+ if (datap) { -+ *datap = digest; -+ digest = NULL; -+ } -+ } -+ -+ else { -+ /* ASCII requested */ -+ if (lenp) *lenp = (2*digestlen) + 1; -+ if (datap) { -+ const uint8_t * s = (const uint8_t *) digest; -+ *datap = pgpHexStr(s, digestlen); -+ } -+ } -+ -+ ret = 1; -+ -+done: -+ if (digest) { -+ /* Zero the digest, just in case it's sensitive */ -+ memset(digest, 0, digestlen); -+ free(digest); -+ } -+ -+ EVP_MD_CTX_free(ctx->md_ctx); -+ free(ctx); -+ -+ if (ret != 1) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+ -+/****************************** RSA **************************************/ -+ -+/* Key */ -+ -+struct pgpDigKeyRSA_s { -+ size_t nbytes; /* Size of modulus */ -+ -+ BIGNUM *n; /* Common Modulus */ -+ BIGNUM *e; /* Public Exponent */ -+ -+ EVP_PKEY *evp_pkey; /* Fully constructed key */ -+}; -+ -+static int constructRSASigningKey(struct pgpDigKeyRSA_s *key) -+{ -+ if (key->evp_pkey) { -+ /* We've already constructed it, so just reuse it */ -+ return 1; -+ } -+ -+ /* Create the RSA key */ -+ RSA *rsa = RSA_new(); -+ if (!rsa) return 0; -+ -+ if (!RSA_set0_key(rsa, key->n, key->e, NULL)) { -+ RSA_free(rsa); -+ return 0; -+ } -+ -+ /* Create an EVP_PKEY container to abstract the key-type. */ -+ key->evp_pkey = EVP_PKEY_new(); -+ if (!key->evp_pkey) { -+ RSA_free(rsa); -+ return 0; -+ } -+ -+ /* Assign the RSA key to the EVP_PKEY structure. -+ This will take over memory management of the RSA key */ -+ if (!EVP_PKEY_assign_RSA(key->evp_pkey, rsa)) { -+ EVP_PKEY_free(key->evp_pkey); -+ key->evp_pkey = NULL; -+ RSA_free(rsa); -+ } -+ -+ return 1; -+} -+ -+static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p) -+{ -+ size_t mlen = pgpMpiLen(p) - 2; -+ struct pgpDigKeyRSA_s *key = pgpkey->data; -+ -+ if(!key) { -+ key = pgpkey->data = xcalloc(1, sizeof(*key)); -+ } -+ -+ switch(num) { -+ case 0: -+ /* Modulus */ -+ if (key->n) { -+ /* This should only ever happen once per key */ -+ return 1; -+ } -+ -+ key->nbytes = mlen; -+ /* Create a BIGNUM from the pointer. -+ Note: this assumes big-endian data as required by PGP */ -+ key->n = BN_bin2bn(p+2, mlen, NULL); -+ if (!key->n) return 1; -+ break; -+ -+ case 1: -+ /* Exponent */ -+ if (key->e) { -+ /* This should only ever happen once per key */ -+ return 1; -+ } -+ -+ /* Create a BIGNUM from the pointer. -+ Note: this assumes big-endian data as required by PGP */ -+ key->e = BN_bin2bn(p+2, mlen, NULL); -+ if (!key->e) return 1; -+ break; -+ } -+ -+ return 0; -+} -+ -+static void pgpFreeKeyRSA(pgpDigAlg pgpkey) -+{ -+ struct pgpDigKeyRSA_s *key = pgpkey->data; -+ if (key) { -+ if (key->evp_pkey) { -+ EVP_PKEY_free(key->evp_pkey); -+ } else { -+ /* If key->evp_pkey was constructed, -+ * the memory management of these BNs -+ * are freed with it. */ -+ BN_clear_free(key->n); -+ BN_clear_free(key->e); -+ } -+ -+ free(key); -+ } -+} -+ -+/* Signature */ -+ -+struct pgpDigSigRSA_s { -+ BIGNUM *bn; -+ size_t len; -+}; -+ -+static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, const uint8_t *p) -+{ -+ BIGNUM *bn = NULL; -+ -+ int mlen = pgpMpiLen(p) - 2; -+ int rc = 1; -+ -+ struct pgpDigSigRSA_s *sig = pgpsig->data; -+ if (!sig) { -+ sig = xcalloc(1, sizeof(*sig)); -+ } -+ -+ switch (num) { -+ case 0: -+ if (sig->bn) { -+ /* This should only ever happen once per signature */ -+ return 1; -+ } -+ -+ bn = sig->bn = BN_new(); -+ if (!bn) return 1; -+ -+ /* Create a BIGNUM from the signature pointer. -+ Note: this assumes big-endian data as required -+ by the PGP multiprecision integer format -+ (RFC4880, Section 3.2) -+ This will be useful later, as we can -+ retrieve this value with appropriate -+ padding. */ -+ bn = BN_bin2bn(p+2, mlen, bn); -+ if (!bn) return 1; -+ -+ sig->bn = bn; -+ sig->len = mlen; -+ -+ pgpsig->data = sig; -+ rc = 0; -+ break; -+ } -+ return rc; -+} -+ -+static void pgpFreeSigRSA(pgpDigAlg pgpsig) -+{ -+ struct pgpDigSigRSA_s *sig = pgpsig->data; -+ if (sig) { -+ BN_clear_free(sig->bn); -+ free(pgpsig->data); -+ } -+} -+ -+static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, -+ uint8_t *hash, size_t hashlen, int hash_algo) -+{ -+ int rc, ret; -+ EVP_PKEY_CTX *pkey_ctx = NULL; -+ struct pgpDigSigRSA_s *sig = pgpsig->data; -+ -+ void *padded_sig = NULL; -+ -+ struct pgpDigKeyRSA_s *key = pgpkey->data; -+ -+ if(!constructRSASigningKey(key)) { -+ rc = 1; -+ goto done; -+ } -+ -+ pkey_ctx = EVP_PKEY_CTX_new(key->evp_pkey, NULL); -+ if (!pkey_ctx) { -+ rc = 1; -+ goto done; -+ } -+ -+ ret = EVP_PKEY_verify_init(pkey_ctx); -+ if (ret < 0) { -+ rc = 1; -+ goto done; -+ } -+ -+ ret = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING); -+ if (ret < 0) { -+ rc = 1; -+ goto done; -+ } -+ -+ ret = EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo)); -+ if (ret < 0) { -+ rc = 1; -+ goto done; -+ } -+ -+ int pkey_len = EVP_PKEY_size(key->evp_pkey); -+ padded_sig = xcalloc(1, pkey_len); -+ if (!BN_bn2binpad(sig->bn, padded_sig, pkey_len)) { -+ rc = 1; -+ goto done; -+ } -+ -+ ret = EVP_PKEY_verify(pkey_ctx, padded_sig, pkey_len, hash, hashlen); -+ if (ret == 1) -+ { -+ /* Success */ -+ rc = 0; -+ } -+ else -+ { -+ /* Failure */ -+ rc = 1; -+ } -+ -+done: -+ EVP_PKEY_CTX_free(pkey_ctx); -+ free(padded_sig); -+ return rc; -+} -+ -+/****************************** DSA ***************************************/ -+/* Key */ -+ -+struct pgpDigKeyDSA_s { -+ BIGNUM *p; /* Prime */ -+ BIGNUM *q; /* Subprime */ -+ BIGNUM *g; /* Base */ -+ BIGNUM *y; /* Public Key */ -+ -+ DSA *dsa_key; /* Fully constructed key */ -+}; -+ -+static int constructDSASigningKey(struct pgpDigKeyDSA_s *key) -+{ -+ int rc; -+ -+ if (key->dsa_key) { -+ /* We've already constructed it, so just reuse it */ -+ return 1; -+ } -+ -+ /* Create the DSA key */ -+ DSA *dsa = DSA_new(); -+ if (!dsa) return 0; -+ -+ if (!DSA_set0_pqg(dsa, key->p, key->q, key->g)) { -+ rc = 0; -+ goto done; -+ } -+ -+ if (!DSA_set0_key(dsa, key->y, NULL)) { -+ rc = 0; -+ } -+ -+ key->dsa_key = dsa; -+ -+ rc = 1; -+done: -+ if (rc == 0) { -+ DSA_free(dsa); -+ } -+ return rc; -+} -+ -+ -+static int pgpSetKeyMpiDSA(pgpDigAlg pgpkey, int num, const uint8_t *p) -+{ -+ BIGNUM *bn; -+ size_t mlen = pgpMpiLen(p) - 2; -+ struct pgpDigKeyDSA_s *key = pgpkey->data; -+ -+ if(!key) { -+ key = pgpkey->data = xcalloc(1, sizeof(*key)); -+ } -+ -+ /* Create a BIGNUM from the key pointer. -+ Note: this assumes big-endian data as required -+ by the PGP multiprecision integer format -+ (RFC4880, Section 3.2) */ -+ bn = BN_bin2bn(p+2, mlen, NULL); -+ if (!bn) return 1; -+ -+ switch(num) { -+ case 0: -+ /* Prime */ -+ if (key->p) { -+ /* This should only ever happen once per key */ -+ return 1; -+ } -+ key->p = bn; -+ break; -+ -+ case 1: -+ /* Subprime */ -+ if (key->q) { -+ /* This should only ever happen once per key */ -+ return 1; -+ } -+ key->q = bn; -+ break; -+ case 2: -+ /* Base */ -+ if (key->g) { -+ /* This should only ever happen once per key */ -+ return 1; -+ } -+ key->g = bn; -+ break; -+ case 3: -+ /* Public */ -+ if (key->y) { -+ /* This should only ever happen once per key */ -+ return 1; -+ } -+ key->y = bn; -+ break; -+ } -+ -+ return 0; -+} -+ -+static void pgpFreeKeyDSA(pgpDigAlg pgpkey) -+{ -+ struct pgpDigKeyDSA_s *key = pgpkey->data; -+ if (key) { -+ if (key->dsa_key) { -+ DSA_free(key->dsa_key); -+ } else { -+ /* If sig->dsa_key was constructed, -+ * the memory management of these BNs -+ * are freed with it. */ -+ BN_clear_free(key->p); -+ BN_clear_free(key->q); -+ BN_clear_free(key->g); -+ BN_clear_free(key->y); -+ } -+ free(key); -+ } -+} -+ -+/* Signature */ -+ -+struct pgpDigSigDSA_s { -+ BIGNUM *r; -+ BIGNUM *s; -+ -+ DSA_SIG *dsa_sig; -+}; -+ -+static int constructDSASignature(struct pgpDigSigDSA_s *sig) -+{ -+ int rc; -+ -+ if (sig->dsa_sig) { -+ /* We've already constructed it, so just reuse it */ -+ return 1; -+ } -+ -+ /* Create the DSA signature */ -+ DSA_SIG *dsa_sig = DSA_SIG_new(); -+ if (!dsa_sig) return 0; -+ -+ if (!DSA_SIG_set0(dsa_sig, sig->r, sig->s)) { -+ rc = 0; -+ goto done; -+ } -+ -+ sig->dsa_sig = dsa_sig; -+ -+ rc = 1; -+done: -+ if (rc == 0) { -+ DSA_SIG_free(sig->dsa_sig); -+ } -+ return rc; -+} -+ -+static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p) -+{ -+ BIGNUM *bn = NULL; -+ -+ int mlen = pgpMpiLen(p) - 2; -+ int rc = 1; -+ -+ struct pgpDigSigDSA_s *sig = pgpsig->data; -+ if (!sig) { -+ sig = xcalloc(1, sizeof(*sig)); -+ } -+ -+ /* Create a BIGNUM from the signature pointer. -+ Note: this assumes big-endian data as required -+ by the PGP multiprecision integer format -+ (RFC4880, Section 3.2) */ -+ bn = BN_bin2bn(p+2, mlen, NULL); -+ if (!bn) return 1; -+ -+ switch (num) { -+ case 0: -+ if (sig->r) { -+ /* This should only ever happen once per signature */ -+ BN_free(bn); -+ return 1; -+ } -+ sig->r = bn; -+ rc = 0; -+ break; -+ case 1: -+ if (sig->s) { -+ /* This should only ever happen once per signature */ -+ BN_free(bn); -+ return 1; -+ } -+ sig->s = bn; -+ rc = 0; -+ break; -+ } -+ -+ pgpsig->data = sig; -+ -+ return rc; -+} -+ -+static void pgpFreeSigDSA(pgpDigAlg pgpsig) -+{ -+ struct pgpDigSigDSA_s *sig = pgpsig->data; -+ if (sig) { -+ if (sig->dsa_sig) { -+ DSA_SIG_free(sig->dsa_sig); -+ } else { -+ /* If sig->dsa_sig was constructed, -+ * the memory management of these BNs -+ * are freed with it. */ -+ BN_clear_free(sig->r); -+ BN_clear_free(sig->s); -+ } -+ free(pgpsig->data); -+ } -+} -+ -+static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, -+ uint8_t *hash, size_t hashlen, int hash_algo) -+{ -+ int rc, ret; -+ struct pgpDigSigDSA_s *sig = pgpsig->data; -+ -+ struct pgpDigKeyDSA_s *key = pgpkey->data; -+ -+ if(!constructDSASigningKey(key)) { -+ rc = 1; -+ goto done; -+ } -+ -+ if (!constructDSASignature(sig)) { -+ rc = 1; -+ goto done; -+ } -+ -+ ret = DSA_do_verify(hash, hashlen, sig->dsa_sig, key->dsa_key); -+ if (ret == 1) -+ { -+ /* Success */ -+ rc = 0; -+ } -+ else -+ { -+ /* Failure */ -+ rc = 1; -+ } -+ -+done: -+ return rc; -+} -+ -+/****************************** NULL **************************************/ -+ -+static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p) -+{ -+ return 1; -+} -+ -+static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig, -+ uint8_t *hash, size_t hashlen, int hash_algo) -+{ -+ return 1; -+} -+ -+/****************************** PGP **************************************/ -+pgpDigAlg pgpPubkeyNew(int algo) -+{ -+ pgpDigAlg ka = xcalloc(1, sizeof(*ka));; -+ -+ switch (algo) { -+ case PGPPUBKEYALGO_RSA: -+ ka->setmpi = pgpSetKeyMpiRSA; -+ ka->free = pgpFreeKeyRSA; -+ ka->mpis = 2; -+ break; -+ case PGPPUBKEYALGO_DSA: -+ ka->setmpi = pgpSetKeyMpiDSA; -+ ka->free = pgpFreeKeyDSA; -+ ka->mpis = 4; -+ break; -+ default: -+ ka->setmpi = pgpSetMpiNULL; -+ ka->mpis = -1; -+ break; -+ } -+ -+ ka->verify = pgpVerifyNULL; /* keys can't be verified */ -+ -+ return ka; -+} -+ -+pgpDigAlg pgpSignatureNew(int algo) -+{ -+ pgpDigAlg sa = xcalloc(1, sizeof(*sa)); -+ -+ switch (algo) { -+ case PGPPUBKEYALGO_RSA: -+ sa->setmpi = pgpSetSigMpiRSA; -+ sa->free = pgpFreeSigRSA; -+ sa->verify = pgpVerifySigRSA; -+ sa->mpis = 1; -+ break; -+ case PGPPUBKEYALGO_DSA: -+ sa->setmpi = pgpSetSigMpiDSA; -+ sa->free = pgpFreeSigDSA; -+ sa->verify = pgpVerifySigDSA; -+ sa->mpis = 2; -+ break; -+ default: -+ sa->setmpi = pgpSetMpiNULL; -+ sa->verify = pgpVerifyNULL; -+ sa->mpis = -1; -+ break; -+ } -+ return sa; -+} --- -2.12.0 - diff --git a/0001-Add-build-id-links-to-rpm-for-all-ELF-files.patch b/0001-Add-build-id-links-to-rpm-for-all-ELF-files.patch deleted file mode 100644 index 274c317..0000000 --- a/0001-Add-build-id-links-to-rpm-for-all-ELF-files.patch +++ /dev/null @@ -1,1566 +0,0 @@ -From 189b4f88c8e100155ec23a1e0b214bdc8473532a Mon Sep 17 00:00:00 2001 -Message-Id: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Tue, 14 Jun 2016 17:07:12 +0200 -Subject: [PATCH 01/11] Add build-id links to rpm for all ELF files. - -This patch moves the main ELF file build-id symlinks from the -debuginfo package into the main package. And uses different -base directories for the main ELF file build-id symlink. -For the main build-id use /usr/lib/.build-id and for the debug -build-id use /usr/lib/debug/.build-id. - -There are two reasons for doing this. The main package and the -debuginfo package might get out of sync, or the debuginfo package -might not be installed at all. In which case finding the main ELF -file through the build-id symlink becomes impossible. Secondly by -moving the main ELF build-id symlink in its own directory the -/usr/lib/debug directory gets populated with only debuginfo files -which is convenient if the user might want to have that directory -populated through a network mountpoint. - -To support the new logic the symlink code has been moved from -find-debuginfo.sh to build/files.c. - -This also includes support for a new config %_build_id_links that -defaults to compat. The other settings are none, alldebug (the old -style) and separate. compat is like separate, but adds a compatibility -link under /usr/lib/debug/.build-id for the main build-id symlink. - -There are several new testcases added to test the various settings -using the new keyword "buildid". - -Signed-off-by: Mark Wielaard ---- - build/Makefile.am | 4 + - build/files.c | 375 ++++++++++++++++++++ - configure.ac | 15 + - macros.in | 28 ++ - scripts/find-debuginfo.sh | 60 ---- - tests/Makefile.am | 1 + - tests/data/SPECS/hello2cp.spec | 64 ++++ - tests/data/SPECS/hello2ln.spec | 63 ++++ - tests/rpmbuildid.at | 761 +++++++++++++++++++++++++++++++++++++++++ - tests/rpmtests.at | 1 + - 10 files changed, 1312 insertions(+), 60 deletions(-) - create mode 100644 tests/data/SPECS/hello2cp.spec - create mode 100644 tests/data/SPECS/hello2ln.spec - create mode 100644 tests/rpmbuildid.at - -diff --git a/build/Makefile.am b/build/Makefile.am -index dbda716..71edbd1 100644 ---- a/build/Makefile.am -+++ b/build/Makefile.am -@@ -26,3 +26,7 @@ librpmbuild_la_LIBADD = \ - @LTLIBICONV@ \ - @WITH_POPT_LIB@ \ - @WITH_MAGIC_LIB@ -+ -+if LIBDW -+librpmbuild_la_LIBADD += @WITH_LIBELF_LIB@ @WITH_LIBDW_LIB@ -+endif -diff --git a/build/files.c b/build/files.c -index b76ce04..b010483 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -14,6 +14,11 @@ - #include - #endif - -+#if HAVE_LIBDW -+#include -+#include -+#endif -+ - #include - #include - #include -@@ -1551,6 +1556,368 @@ exit: - return rc; - } - -+#if HAVE_LIBDW -+/* How build id links are generated. See macros.in for description. */ -+#define BUILD_IDS_NONE 0 -+#define BUILD_IDS_ALLDEBUG 1 -+#define BUILD_IDS_SEPARATE 2 -+#define BUILD_IDS_COMPAT 3 -+ -+static int addNewIDSymlink(FileList fl, -+ char *targetpath, char *idlinkpath, -+ int isDbg, int isCompat) -+{ -+ const char *linkerr = _("failed symlink"); -+ int rc = 0; -+ int nr = 0; -+ char *origpath, *linkpath; -+ -+ if (isDbg) -+ rasprintf(&linkpath, "%s.debug", idlinkpath); -+ else -+ linkpath = idlinkpath; -+ origpath = linkpath; -+ -+ while (faccessat(AT_FDCWD, linkpath, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { -+ if (nr > 0) -+ free(linkpath); -+ nr++; -+ rasprintf(&linkpath, "%s.%d%s", idlinkpath, nr, -+ isDbg ? ".debug" : ""); -+ } -+ -+ char *symtarget = targetpath; -+ if (nr > 0 && isCompat) -+ rasprintf (&symtarget, "%s.%d", targetpath, nr); -+ -+ if (symlink(symtarget, linkpath) < 0) { -+ rc = 1; -+ rpmlog(RPMLOG_ERR, "%s: %s -> %s: %m\n", -+ linkerr, linkpath, symtarget); -+ } else { -+ fl->cur.isDir = 0; -+ rc = addFile(fl, linkpath, NULL); -+ } -+ -+ /* Don't warn (again) if this is a compat id-link, we retarget it. */ -+ if (nr > 0 && !isCompat) { -+ /* Lets see why there are multiple build-ids. If the original -+ targets are hard linked, then it is OK, otherwise warn -+ something fishy is going on. Would be nice to call -+ something like eu-elfcmp to see if they are really the same -+ ELF file or not. */ -+ struct stat st1, st2; -+ if (stat (origpath, &st1) != 0) { -+ rpmlog(RPMLOG_WARNING, _("Duplicate build-id, stat %s: %m\n"), -+ origpath); -+ } else if (stat (linkpath, &st2) != 0) { -+ rpmlog(RPMLOG_WARNING, _("Duplicate build-id, stat %s: %m\n"), -+ linkpath); -+ } else if (!(S_ISREG(st1.st_mode) && S_ISREG(st2.st_mode) -+ && st1.st_nlink > 1 && st2.st_nlink == st1.st_nlink -+ && st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev)) { -+ char *rpath1 = realpath(origpath, NULL); -+ char *rpath2 = realpath(linkpath, NULL); -+ rpmlog(RPMLOG_WARNING, _("Duplicate build-ids %s and %s\n"), -+ rpath1, rpath2); -+ free(rpath1); -+ free(rpath2); -+ } -+ } -+ -+ if (isDbg) -+ free(origpath); -+ if (nr > 0) -+ free(linkpath); -+ if (nr > 0 && isCompat) -+ free(symtarget); -+ -+ return rc; -+} -+ -+static int generateBuildIDs(FileList fl) -+{ -+ int rc = 0; -+ int i; -+ FileListRec flp; -+ char **ids = NULL; -+ char **paths = NULL; -+ size_t nr_ids, allocated; -+ nr_ids = allocated = 0; -+ -+ /* How are we supposed to create the build-id links? */ -+ char *build_id_links_macro = rpmExpand("%{?_build_id_links}", NULL); -+ int build_id_links; -+ if (build_id_links_macro == NULL) { -+ rpmlog(RPMLOG_WARNING, -+ _("_build_id_links macro not set, assuming 'compat'\n")); -+ build_id_links = BUILD_IDS_COMPAT; -+ } else if (strcmp(build_id_links_macro, "none") == 0) { -+ build_id_links = BUILD_IDS_NONE; -+ } else if (strcmp(build_id_links_macro, "alldebug") == 0) { -+ build_id_links = BUILD_IDS_ALLDEBUG; -+ } else if (strcmp(build_id_links_macro, "separate") == 0) { -+ build_id_links = BUILD_IDS_SEPARATE; -+ } else if (strcmp(build_id_links_macro, "compat") == 0) { -+ build_id_links = BUILD_IDS_COMPAT; -+ } else { -+ rc = 1; -+ rpmlog(RPMLOG_ERR, -+ _("_build_id_links macro set to unknown value '%s'\n"), -+ build_id_links_macro); -+ build_id_links = BUILD_IDS_NONE; -+ } -+ free(build_id_links_macro); -+ -+ if (build_id_links == BUILD_IDS_NONE || rc != 0) -+ return rc; -+ -+ int terminate = rpmExpandNumeric("%{?_missing_build_ids_terminate_build}"); -+ -+ /* Collect and check all build-ids for ELF files in this package. */ -+ int needMain = 0; -+ int needDbg = 0; -+ for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { -+ int fd; -+ fd = open (flp->diskPath, O_RDONLY); -+ if (fd >= 0) { -+ struct stat sbuf; -+ if (fstat (fd, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { -+ Elf *elf = elf_begin (fd, ELF_C_READ, NULL); -+ if (elf != NULL && elf_kind(elf) == ELF_K_ELF) { -+ const void *build_id; -+ ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id); -+ /* len == -1 means error. Zero means no -+ build-id. We want at least a length of 2 so we -+ have at least a xx/yy (hex) dir/file. But -+ reasonable build-ids are between 16 bytes (md5 -+ is 128 bits) and 64 bytes (largest sha3 is 512 -+ bits), common is 20 bytes (sha1 is 160 bits). */ -+ if (len >= 16 && len <= 64) { -+ /* We determine whether this is a main or -+ debug ELF based on path. */ -+ #define DEBUGPATH "/usr/lib/debug/" -+ int addid = 0; -+ if (strncmp (flp->cpioPath, -+ DEBUGPATH, strlen (DEBUGPATH)) == 0) { -+ needDbg = 1; -+ addid = 1; -+ } -+ else if (build_id_links != BUILD_IDS_ALLDEBUG) { -+ needMain = 1; -+ addid = 1; -+ } -+ if (addid) { -+ const unsigned char *p = build_id; -+ const unsigned char *end = p + len; -+ char *id_str; -+ if (allocated <= nr_ids) { -+ allocated += 16; -+ paths = xrealloc (paths, -+ allocated * sizeof(char *)); -+ ids = xrealloc (ids, -+ allocated * sizeof(char *)); -+ } -+ -+ paths[nr_ids] = xstrdup(flp->cpioPath); -+ id_str = ids[nr_ids] = xmalloc(2 * len + 1); -+ while (p < end) -+ id_str += sprintf(id_str, "%02x", -+ (unsigned)*p++); -+ *id_str = '\0'; -+ nr_ids++; -+ } -+ } else { -+ if (len < 0) { -+ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, -+ _("error reading build-id in %s: %s\n"), -+ flp->diskPath, elf_errmsg (-1)); -+ } else if (len == 0) { -+ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, -+ _("Missing build-id in %s\n"), -+ flp->diskPath); -+ } else { -+ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, -+ (len < 16 -+ ? _("build-id found in %s too small\n") -+ : _("build-id found in %s too large\n")), -+ flp->diskPath); -+ } -+ if (terminate) -+ rc = 1; -+ } -+ elf_end (elf); -+ } -+ } -+ close (fd); -+ } -+ } -+ -+ /* Process and clean up all build-ids. */ -+ if (nr_ids > 0) { -+ const char *errdir = _("failed to create directory"); -+ char *mainiddir = NULL; -+ char *debugiddir = NULL; -+ if (rc == 0) { -+ /* Add .build-id directories to hold the subdirs/symlinks. */ -+ #define BUILD_ID_DIR "/usr/lib/.build-id" -+ #define DEBUG_ID_DIR "/usr/lib/debug/.build-id" -+ -+ mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL); -+ debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL); -+ -+ /* Supported, but questionable. */ -+ if (needMain && needDbg) -+ rpmlog(RPMLOG_WARNING, -+ _("Mixing main ELF and debug files in package")); -+ -+ if (needMain) { -+ if ((rc = rpmioMkpath(mainiddir, 0755, -1, -1)) != 0) { -+ rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, mainiddir); -+ } else { -+ fl->cur.isDir = 1; -+ rc = addFile(fl, mainiddir, NULL); -+ } -+ } -+ -+ if (rc == 0 && needDbg) { -+ if ((rc = rpmioMkpath(debugiddir, 0755, -1, -1)) != 0) { -+ rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, debugiddir); -+ } else { -+ fl->cur.isDir = 1; -+ rc = addFile(fl, debugiddir, NULL); -+ } -+ } -+ } -+ -+ /* Now add a subdir and symlink for each buildid found. */ -+ for (i = 0; i < nr_ids; i++) { -+ /* Don't add anything more when an error occured. But do -+ cleanup. */ -+ if (rc == 0) { -+ int isDbg = strncmp (paths[i], DEBUGPATH, -+ strlen (DEBUGPATH)) == 0; -+ -+ char *buildidsubdir; -+ char subdir[4]; -+ subdir[0] = '/'; -+ subdir[1] = ids[i][0]; -+ subdir[2] = ids[i][1]; -+ subdir[3] = '\0'; -+ if (isDbg) -+ buildidsubdir = rpmGetPath(debugiddir, subdir, NULL); -+ else -+ buildidsubdir = rpmGetPath(mainiddir, subdir, NULL); -+ /* We only need to create and add the subdir once. */ -+ int addsubdir = access (buildidsubdir, F_OK) == -1; -+ if (addsubdir -+ && (rc = rpmioMkpath(buildidsubdir, 0755, -1, -1)) != 0) { -+ rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, buildidsubdir); -+ } else { -+ fl->cur.isDir = 1; -+ if (!addsubdir -+ || (rc = addFile(fl, buildidsubdir, NULL)) == 0) { -+ char *linkpattern, *targetpattern; -+ char *linkpath, *targetpath; -+ if (isDbg) { -+ linkpattern = "%s/%s"; -+ targetpattern = "../../../../..%s"; -+ } else { -+ linkpattern = "%s/%s"; -+ targetpattern = "../../../..%s"; -+ } -+ rasprintf(&linkpath, linkpattern, -+ buildidsubdir, &ids[i][2]); -+ rasprintf(&targetpath, targetpattern, paths[i]); -+ rc = addNewIDSymlink(fl, targetpath, linkpath, -+ isDbg, 0); -+ -+ /* We might want to have a link from the debug -+ build_ids dir to the main one. We create it -+ when we are creating compat links or doing -+ an old style alldebug build-ids package. In -+ the first case things are simple since we -+ just link to the main build-id symlink. The -+ second case is a bit tricky, since we -+ cannot be 100% sure the file names in the -+ main and debug package match. Currently -+ they do, but when creating parallel -+ installable debuginfo packages they might -+ not (in that case we might have to also -+ strip the nvr from the debug name). -+ -+ In general either method is discouraged -+ since it might create dangling symlinks if -+ the package versions get out of sync. */ -+ if (rc == 0 && isDbg -+ && build_id_links == BUILD_IDS_COMPAT) { -+ /* buildidsubdir already points to the -+ debug buildid. We just need to setup -+ the symlink to the main one. */ -+ free(linkpath); -+ free(targetpath); -+ rasprintf(&linkpath, "%s/%s", -+ buildidsubdir, &ids[i][2]); -+ rasprintf(&targetpath, -+ "../../../.build-id%s/%s", -+ subdir, &ids[i][2]); -+ rc = addNewIDSymlink(fl, targetpath, linkpath, -+ 0, 1); -+ } -+ -+ if (rc == 0 && isDbg -+ && build_id_links == BUILD_IDS_ALLDEBUG) { -+ /* buildidsubdir already points to the -+ debug buildid. We do have to figure out -+ the main ELF file though (which is most -+ likely not in this package). Guess we -+ can find it by stripping the -+ /usr/lib/debug path and .debug -+ prefix. Which might not really be -+ correct if there was a more involved -+ transformation (for example for -+ parallel installable debuginfo -+ packages), but then we shouldn't be -+ using ALLDEBUG in the first place. -+ Also ignore things like .dwz multifiles -+ which don't end in ".debug". */ -+ int pathlen = strlen(paths[i]); -+ int debuglen = strlen(".debug"); -+ int prefixlen = strlen("/usr/lib/debug"); -+ if (pathlen > prefixlen -+ && strcmp (paths[i] + pathlen - debuglen, -+ ".debug") == 0) { -+ free(linkpath); -+ free(targetpath); -+ char *targetstr = xstrdup (paths[i] -+ + prefixlen); -+ int targetlen = pathlen - prefixlen; -+ targetstr[targetlen - debuglen] = '\0'; -+ rasprintf(&linkpath, "%s/%s", -+ buildidsubdir, &ids[i][2]); -+ rasprintf(&targetpath, "../../../../..%s", -+ targetstr); -+ rc = addNewIDSymlink(fl, targetpath, -+ linkpath, 0, 0); -+ free(targetstr); -+ } -+ } -+ free(linkpath); -+ free(targetpath); -+ } -+ } -+ free(buildidsubdir); -+ } -+ free(paths[i]); -+ free(ids[i]); -+ } -+ free(paths); -+ free(ids); -+ } -+ return rc; -+} -+#endif -+ - /** - * Add a file to a binary package. - * @param pkg -@@ -1963,6 +2330,11 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - if (fl.processingFailed) - goto exit; - -+#if HAVE_LIBDW -+ if (generateBuildIDs (&fl) != 0) -+ goto exit; -+#endif -+ - /* Verify that file attributes scope over hardlinks correctly. */ - if (checkHardLinks(&fl.files)) - (void) rpmlibNeedsFeature(pkg, "PartialHardlinkSets", "4.0.4-1"); -@@ -2161,6 +2533,9 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - Package pkg; - rpmRC rc = RPMRC_OK; - -+#if HAVE_LIBDW -+ elf_version (EV_CURRENT); -+#endif - check_fileList = newStringBuf(); - genSourceRpmName(spec); - -diff --git a/configure.ac b/configure.ac -index b2ec501..08eceeb 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -367,6 +367,21 @@ AC_SUBST(WITH_ARCHIVE_LIB) - AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) - - #================= -+# Check for elfutils libdw library with dwelf_elf_gnu_build_id. -+AS_IF([test "$WITH_LIBELF" = yes],[ -+ AC_CHECK_HEADERS([elfutils/libdwelf.h],[ -+ AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ -+ AC_DEFINE(HAVE_LIBDW, 1, -+ [Define to 1 if you have elfutils libdw library]) -+ WITH_LIBDW_LIB="-ldw" -+ WITH_LIBDW=yes -+ ]) -+ ]) -+ AC_SUBST(WITH_LIBDW_LIB) -+ AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) -+]) -+ -+#================= - # Process --with/without-external-db - AC_ARG_WITH(external_db, [AS_HELP_STRING([--with-external-db],[build against an external Berkeley db])], - [case "$with_external_db" in -diff --git a/macros.in b/macros.in -index fd57f2e..e43d62b0 100644 ---- a/macros.in -+++ b/macros.in -@@ -449,6 +449,34 @@ package or when debugging this package.\ - #%_include_minidebuginfo 1 - - # -+# Defines how and if build_id links are generated for ELF files. -+# The following settings are supported: -+# -+# - none -+# No build_id links are generated. -+# -+# - alldebug -+# build_id links are generated only when the __debug_package global is -+# defined. This will generate build_id links in the -debuginfo package -+# for both the main file as /usr/lib/debug/.build-id/xx/yyy and for -+# the .debug file as /usr/lib/debug/.build-id/xx/yyy.debug. -+# This is the old style build_id links as generated by the original -+# find-debuginfo.sh script. -+# -+# - separate -+# build_id links are generate for all binary packages. If this is a -+# main package (the __debug_package global isn't set) then the -+# build_id link is generated as /usr/lib/.build-id/xx/yyy. If this is -+# a -debuginfo package (the __debug_package global is set) then the -+# build_id link is generated as /usr/lib/debug/.build-id/xx/yyy. -+# -+# - compat -+# Same as for "separate" but if the __debug_package global is set then -+# the -debuginfo package will have a compatibility link for the main -+# ELF /usr/lib/debug/.build-id/xx/yyy -> /usr/lib/.build-id/xx/yyy -+%_build_id_links compat -+ -+# - # 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 4293261..c9e2293 100644 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -207,57 +207,6 @@ debug_link() - link_relative "$t" "$l" "$RPM_BUILD_ROOT" - } - --# Provide .2, .3, ... symlinks to all filename instances of this build-id. --make_id_dup_link() --{ -- local id="$1" file="$2" idfile -- -- local n=1 -- while true; do -- idfile=".build-id/${id:0:2}/${id:2}.$n" -- [ $# -eq 3 ] && idfile="${idfile}$3" -- if [ ! -L "$RPM_BUILD_ROOT/usr/lib/debug/$idfile" ]; then -- break -- fi -- n=$[$n+1] -- done -- debug_link "$file" "/$idfile" --} -- --# Make a build-id symlink for id $1 with suffix $3 to file $2. --make_id_link() --{ -- local id="$1" file="$2" -- local idfile=".build-id/${id:0:2}/${id:2}" -- [ $# -eq 3 ] && idfile="${idfile}$3" -- local root_idfile="$RPM_BUILD_ROOT/usr/lib/debug/$idfile" -- -- if [ ! -L "$root_idfile" ]; then -- debug_link "$file" "/$idfile" -- return -- fi -- -- make_id_dup_link "$@" -- -- [ $# -eq 3 ] && return 0 -- -- local other=$(readlink -m "$root_idfile") -- other=${other#$RPM_BUILD_ROOT} -- if cmp -s "$root_idfile" "$RPM_BUILD_ROOT$file" || -- eu-elfcmp -q "$root_idfile" "$RPM_BUILD_ROOT$file" 2> /dev/null; then -- # Two copies. Maybe one has to be setuid or something. -- echo >&2 "*** WARNING: identical binaries are copied, not linked:" -- echo >&2 " $file" -- echo >&2 " and $other" -- else -- # This is pathological, break the build. -- echo >&2 "*** ERROR: same build ID in nonidentical files!" -- echo >&2 " $file" -- echo >&2 " and $other" -- exit 2 -- fi --} -- - get_debugfn() - { - dn=$(dirname "${1#$RPM_BUILD_ROOT}") -@@ -288,8 +237,6 @@ while read nlinks inum f; do - eval linked=\$linked_$inum - if [ -n "$linked" ]; then - eval id=\$linkedid_$inum -- make_id_dup_link "$id" "$dn/$(basename $f)" -- make_id_dup_link "$id" "/usr/lib/debug$dn/$bn" .debug - link=$debugfn - get_debugfn "$linked" - echo "hard linked $link to $debugfn" -@@ -318,7 +265,6 @@ while read nlinks inum f; do - # just has its file names collected and adjusted. - case "$dn" in - /usr/lib/debug/*) -- [ -z "$id" ] || make_id_link "$id" "$dn/$(basename $f)" - continue ;; - esac - -@@ -336,10 +282,6 @@ while read nlinks inum f; do - - echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" - -- if [ -n "$id" ]; then -- make_id_link "$id" "$dn/$(basename $f)" -- make_id_link "$id" "/usr/lib/debug$dn/$bn" .debug -- fi - done || exit - - # Invoke the DWARF Compressor utility. -@@ -367,8 +309,6 @@ if $run_dwz && type dwz >/dev/null 2>&1 \ - 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 - - # dwz invalidates .gnu_debuglink CRC32 in the main files. -diff --git a/tests/Makefile.am b/tests/Makefile.am -index 7a5cc65..10555ce 100644 ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -19,6 +19,7 @@ TESTSUITE_AT += rpmquery.at - TESTSUITE_AT += rpmverify.at - TESTSUITE_AT += rpmdb.at - TESTSUITE_AT += rpmbuild.at -+TESTSUITE_AT += rpmbuildid.at - TESTSUITE_AT += rpmi.at - TESTSUITE_AT += rpmvercmp.at - TESTSUITE_AT += rpmdeps.at -diff --git a/tests/data/SPECS/hello2cp.spec b/tests/data/SPECS/hello2cp.spec -new file mode 100644 -index 0000000..33d8dc2 ---- /dev/null -+++ b/tests/data/SPECS/hello2cp.spec -@@ -0,0 +1,64 @@ -+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 -+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" -+cp hello hello2 -+ -+%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 -+* Mon Jun 6 2016 Mark Wielaard -+- Copy hello to hello2 for duplicate build-id testing. -+ -+* Wed May 18 2016 Mark Wielaard -+- Add hello2 for dwz testing support. -+ -+* Tue Oct 20 1998 Jeff Johnson -+- create. -diff --git a/tests/data/SPECS/hello2ln.spec b/tests/data/SPECS/hello2ln.spec -new file mode 100644 -index 0000000..2c40dcc ---- /dev/null -+++ b/tests/data/SPECS/hello2ln.spec -@@ -0,0 +1,63 @@ -+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 -+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" -+ -+%install -+rm -rf $RPM_BUILD_ROOT -+mkdir -p $RPM_BUILD_ROOT/usr/local/bin -+make DESTDIR=$RPM_BUILD_ROOT install -+ln $RPM_BUILD_ROOT/usr/local/bin/hello $RPM_BUILD_ROOT/usr/local/bin/hello2 -+ -+%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 -+* Mon Jun 6 2016 Mark Wielaard -+- Hard link hello to hello2 for duplicate build-id testing. -+ -+* Wed May 18 2016 Mark Wielaard -+- Add hello2 for dwz testing support. -+ -+* Tue Oct 20 1998 Jeff Johnson -+- create. -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -new file mode 100644 -index 0000000..eddca96 ---- /dev/null -+++ b/tests/rpmbuildid.at -@@ -0,0 +1,761 @@ -+# rpmbuildid.at: test rpmbuild buildid symlink support -+# -+# This file is part of RPM, the RPM Package Manager. -+# Copyright (C) 2016 Mark J. Wielaard -+# -+# This file is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# RPM is distributed in the hope that it will be useful, but -+# WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+AT_BANNER([RPM buildid tests]) -+ -+# ------------------------------ -+# Check if rpmbuild "none" doesn't generates buildid symlinks for hello program -+AT_SETUP([rpmbuild buildid none]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links none" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be zero build-id files in both the main and debuginfo package -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+], -+[0], -+[hello build-id files: 0 -+hello debuginfo build-id files: 0 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks -+AT_SETUP([rpmbuild buildid alldebug]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links alldebug" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be zero build-id files in the main package -+# Main and debug should be in the debuginfo package, -+# plus the .build-id/xx subdir, 3 in total. -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+# Extract the both packages to check the build-id files link to the -+# main and .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -+ | cpio -diu -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu -+ -+# Check there is a build-id symlink for the main file. -+main_file=./usr/local/bin/hello -+test -f "${main_file}" || echo "No main file ${main_file}" -+ -+# Extract the build-id from the main file -+id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_main_file" || echo "No build-id file $id_main_file" -+ -+canon_main_file=$(readlink -f ${main_file}) -+ -+test -f "$canon_main_file" \ -+ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" -+ -+canon_main_id_file=$(readlink -f ${id_main_file}) -+ -+test -f "$canon_main_id_file" \ -+ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" -+ -+test "$canon_main_file" = "$canon_main_id_file" \ -+ || echo "main and build-id file not linked" -+ -+# And check the same for the debug file. -+debug_file=./usr/lib/debug/usr/local/bin/hello.debug -+test -f "${debug_file}" || echo "No debug file ${debug_file}" -+ -+# Extract the build-id from the .debug file -+id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test ${id_main} = ${id_debug} || echo "unequal main and debug id" -+ -+id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" -+test -L "$id_debug_file" || echo "No build-id file $id_debug_file" -+ -+canon_debug_file=$(readlink -f ${debug_file}) -+ -+test -f "$canon_debug_file" \ -+ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" -+ -+canon_debug_id_file=$(readlink -f ${id_debug_file}) -+ -+test -f "$canon_debug_id_file" \ -+ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" -+ -+test "$canon_debug_file" = "$canon_debug_id_file" \ -+ || echo "debug and build-id not linked" -+], -+[0], -+[hello build-id files: 0 -+hello debuginfo build-id files: 3 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check if rpmbuild "separate" generates main and debuginfo buildid symlinks -+AT_SETUP([rpmbuild buildid separate]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links separate" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be one build-id files in the main and debuginfo package -+# plus the .build-id/xx subdir, 2 in total. -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+# Extract the both packages to check the build-id files link to the -+# main and .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -+ | cpio -diu -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu -+ -+# Check there is a build-id symlink for the main file. -+main_file=./usr/local/bin/hello -+test -f "${main_file}" || echo "No main file ${main_file}" -+ -+# Extract the build-id from the main file -+id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_main_file" || echo "No build-id file $id_main_file" -+ -+canon_main_file=$(readlink -f ${main_file}) -+ -+test -f "$canon_main_file" \ -+ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" -+ -+canon_main_id_file=$(readlink -f ${id_main_file}) -+ -+test -f "$canon_main_id_file" \ -+ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" -+ -+test "$canon_main_file" = "$canon_main_id_file" \ -+ || echo "main and build-id file not linked" -+ -+# And check the same for the debug file. -+debug_file=./usr/lib/debug/usr/local/bin/hello.debug -+test -f "${debug_file}" || echo "No debug file ${debug_file}" -+ -+# Extract the build-id from the .debug file -+id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test ${id_main} = ${id_debug} || echo "unequal main and debug id" -+ -+id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" -+test -L "$id_debug_file" || echo "No build-id file $id_debug_file" -+ -+canon_debug_file=$(readlink -f ${debug_file}) -+ -+test -f "$canon_debug_file" \ -+ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" -+ -+canon_debug_id_file=$(readlink -f ${id_debug_file}) -+ -+test -f "$canon_debug_id_file" \ -+ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" -+ -+test "$canon_debug_file" = "$canon_debug_id_file" \ -+ || echo "debug and build-id not linked" -+], -+[0], -+[hello build-id files: 2 -+hello debuginfo build-id files: 2 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check if rpmbuild "compat" generates main and debuginfo buildid symlinks -+AT_SETUP([rpmbuild buildid compat]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links compat" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be one build-id files in the main and debuginfo package. -+# the debuginfo package has one extra main build-id compat symlink -+# plus the .build-id/xx subdir, 2 in total in main, 3 in total in debug -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+# Extract the both packages to check the build-id files link to the -+# main and .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -+ | cpio -diu -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu -+ -+# Check there is a build-id symlink for the main file. -+main_file=./usr/local/bin/hello -+test -f "${main_file}" || echo "No main file ${main_file}" -+ -+# Extract the build-id from the main file -+id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_main_file" || echo "No build-id file $id_main_file" -+ -+canon_main_file=$(readlink -f ${main_file}) -+ -+test -f "$canon_main_file" \ -+ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" -+ -+canon_main_id_file=$(readlink -f ${id_main_file}) -+ -+test -f "$canon_main_id_file" \ -+ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" -+ -+test "$canon_main_file" = "$canon_main_id_file" \ -+ || echo "main and build-id file not linked" -+ -+# And check the same for the debug file. -+debug_file=./usr/lib/debug/usr/local/bin/hello.debug -+test -f "${debug_file}" || echo "No debug file ${debug_file}" -+ -+# Extract the build-id from the .debug file -+id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test ${id_main} = ${id_debug} || echo "unequal main and debug id" -+ -+id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" -+test -L "$id_debug_file" || echo "No build-id file $id_debug_file" -+ -+canon_debug_file=$(readlink -f ${debug_file}) -+ -+test -f "$canon_debug_file" \ -+ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" -+ -+canon_debug_id_file=$(readlink -f ${id_debug_file}) -+ -+test -f "$canon_debug_id_file" \ -+ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" -+ -+test "$canon_debug_file" = "$canon_debug_id_file" \ -+ || echo "debug and build-id not linked" -+ -+# The compat link should also point to the same (indirectly). -+id_compat_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_compat_file" || echo "No build-id compat file $id_compat_file" -+ -+canon_compat_file=$(readlink -f ${id_compat_file}) -+ -+test -f "$canon_compat_file" \ -+ || echo "Cannot resolve compat file ${id_compat_file} -> ${canon_compat_file}" -+ -+test "$canon_compat_file" = "$canon_main_file" \ -+ || echo "compat and build-id not linked" -+], -+[0], -+[hello build-id files: 2 -+hello debuginfo build-id files: 3 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that (copied) files with duplicate build-ids are handled correctly. -+# This should create "numbered" build-id files. -+# This is simply the hello example with one binary copied. -+AT_SETUP([rpmbuild buildid duplicate alldebug]) -+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 -+ -+# Should create two warnings -+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="_build_id_links alldebug" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2cp.spec 2>&1 | grep "^warning: " \ -+ | cut -f1-3 -d' ' -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+hello_file=./usr/local/bin/hello -+ -+# Extract the build-id from the main file -+id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+# alldebug not here... -+id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" -+test -L "$id_file" && echo "main id in main package" -+id_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" -+test -L "$id_dup_file" && echo "main dup id in main package" -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# alldebug, so they are all here -+test -L "$id_file" && echo "main id in debug package" -+test -L "$id_dup_file" && echo "main dup id in debug package" -+ -+debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" -+test -L "$debug_id_file" && echo "debug id in debug package" -+debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" -+test -L "$debug_dup_file" && echo "debug dup id in debug package" -+ -+# We don't know which points to which, but we do know they point -+# to different files. -+canon_id_file=$(readlink -f ${id_file}) -+canon_dup_file=$(readlink -f ${id_dup_file}) -+test "$canon_id_file" != "$canon_dup_file" \ -+ || echo "id and dup same" -+ -+canon_debug_id_file=$(readlink -f ${debug_id_file}) -+canon_debug_dup_file=$(readlink -f ${debug_dup_file}) -+test "$canon_debug_id_file" != "$canon_debug_dup_file" \ -+ || echo "debug id and dup same" -+], -+[0], -+[warning: Duplicate build-ids -+warning: Duplicate build-ids -+main id in debug package -+main dup id in debug package -+debug id in debug package -+debug dup id in debug package -+], -+[]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that hard linked files are handled correctly. -+# Since the hard linked files have duplicate build-ids, -+# it should create "numbered" build-id files. -+# This is simply the hello example with one binary hard linked. -+AT_SETUP([rpmbuild buildid hardlink alldebug]) -+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="_build_id_links alldebug" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2ln.spec 2>&1 | grep "^warning: " \ -+ | cut -f1-3 -d' ' -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+hello_file=./usr/local/bin/hello -+ -+# Extract the build-id from the main file -+id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+# alldebug not here... -+id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" -+test -L "$id_file" && echo "main id in main package" -+id_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" -+test -L "$id_dup_file" && echo "main dup id in main package" -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# alldebug, so they are all here -+test -L "$id_file" && echo "main id in debug package" -+test -L "$id_dup_file" && echo "main dup id in debug package" -+ -+debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" -+test -L "$debug_id_file" && echo "debug id in debug package" -+debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" -+test -L "$debug_dup_file" && echo "debug dup id in debug package" -+ -+# We don't know which points to which, but we do know they point -+# to different files. -+canon_id_file=$(readlink -f ${id_file}) -+canon_dup_file=$(readlink -f ${id_dup_file}) -+test "$canon_id_file" != "$canon_dup_file" \ -+ || echo "id and dup same" -+ -+canon_debug_id_file=$(readlink -f ${debug_id_file}) -+canon_debug_dup_file=$(readlink -f ${debug_dup_file}) -+test "$canon_debug_id_file" != "$canon_debug_dup_file" \ -+ || echo "debug id and dup same" -+], -+[0], -+[main id in debug package -+main dup id in debug package -+debug id in debug package -+debug dup id in debug package -+], -+[]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that (copied) files with duplicate build-ids are handled correctly. -+# This should create "numbered" build-id files. -+# This is simply the hello example with one binary copied. -+AT_SETUP([rpmbuild buildid duplicate separate]) -+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 -+ -+# Should create two warnings -+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="_build_id_links separate" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2cp.spec 2>&1 | grep "^warning: " \ -+ | cut -f1-3 -d' ' -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+hello_file=./usr/local/bin/hello -+ -+# Extract the build-id from the main file -+id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+# separate build-ids split... -+id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -+test -L "$id_file" && echo "main id in main package" -+id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" -+test -L "$id_dup_file" && echo "main dup id in main package" -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# seperate, so debug ids are here -+debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" -+test -L "$debug_id_file" && echo "debug id in debug package" -+debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" -+test -L "$debug_dup_file" && echo "debug dup id in debug package" -+ -+# We don't know which points to which, but we do know they point -+# to different files. -+canon_id_file=$(readlink -f ${id_file}) -+canon_dup_file=$(readlink -f ${id_dup_file}) -+test "$canon_id_file" != "$canon_dup_file" \ -+ || echo "id and dup same" -+ -+canon_debug_id_file=$(readlink -f ${debug_id_file}) -+canon_debug_dup_file=$(readlink -f ${debug_dup_file}) -+test "$canon_debug_id_file" != "$canon_debug_dup_file" \ -+ || echo "debug id and dup same" -+], -+[0], -+[warning: Duplicate build-ids -+warning: Duplicate build-ids -+main id in main package -+main dup id in main package -+debug id in debug package -+debug dup id in debug package -+], -+[]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that hard linked files are handled correctly. -+# Since the hard linked files have duplicate build-ids, -+# it should create "numbered" build-id files. -+# This is simply the hello example with one binary hard linked. -+AT_SETUP([rpmbuild buildid hardlink separate]) -+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="_build_id_links separate" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2ln.spec 2>&1 | grep "^warning: " \ -+ | cut -f1-3 -d' ' -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+hello_file=./usr/local/bin/hello -+ -+# Extract the build-id from the main file -+id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+# separate build-ids split... -+id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -+test -L "$id_file" && echo "main id in main package" -+id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" -+test -L "$id_dup_file" && echo "main dup id in main package" -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# separate, so debug ids are here -+debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" -+test -L "$debug_id_file" && echo "debug id in debug package" -+debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" -+test -L "$debug_dup_file" && echo "debug dup id in debug package" -+ -+# We don't know which points to which, but we do know they point -+# to different files. -+canon_id_file=$(readlink -f ${id_file}) -+canon_dup_file=$(readlink -f ${id_dup_file}) -+test "$canon_id_file" != "$canon_dup_file" \ -+ || echo "id and dup same" -+ -+canon_debug_id_file=$(readlink -f ${debug_id_file}) -+canon_debug_dup_file=$(readlink -f ${debug_dup_file}) -+test "$canon_debug_id_file" != "$canon_debug_dup_file" \ -+ || echo "debug id and dup same" -+], -+[0], -+[main id in main package -+main dup id in main package -+debug id in debug package -+debug dup id in debug package -+], -+[]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that (copied) files with duplicate build-ids are handled correctly. -+# This should create "numbered" build-id files. -+# This is simply the hello example with one binary copied. -+AT_SETUP([rpmbuild buildid duplicate compat]) -+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 -+ -+# Should create two warnings -+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="_build_id_links compat" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2cp.spec 2>&1 | grep "^warning: " \ -+ | cut -f1-3 -d' ' -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+hello_file=./usr/local/bin/hello -+ -+# Extract the build-id from the main file -+id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+# compat build-ids split... -+id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -+test -L "$id_file" && echo "main id in main package" -+id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" -+test -L "$id_dup_file" && echo "main dup id in main package" -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# compat, so main (and debug) ids are (also) here -+compat_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" -+test -L "$compat_file" && echo "compat id in debug package" -+compat_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" -+test -L "$compat_dup_file" && echo "compat dup id in debug package" -+ -+debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" -+test -L "$debug_id_file" && echo "debug id in debug package" -+debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" -+test -L "$debug_dup_file" && echo "debug dup id in debug package" -+ -+# We don't know which points to which, but we do know they point -+# to different files. -+canon_id_file=$(readlink -f ${id_file}) -+canon_dup_file=$(readlink -f ${id_dup_file}) -+test "$canon_id_file" != "$canon_dup_file" \ -+ || echo "id and dup same" -+ -+canon_debug_id_file=$(readlink -f ${debug_id_file}) -+canon_debug_dup_file=$(readlink -f ${debug_dup_file}) -+test "$canon_debug_id_file" != "$canon_debug_dup_file" \ -+ || echo "debug id and dup same" -+ -+canon_compat_file=$(readlink -f ${compat_file}) -+canon_compat_dup_file=$(readlink -f ${compat_dup_file}) -+test "$canon_compat_file" != "$canon_compat_dup_file" \ -+ || echo "compat id and dup same" -+], -+[0], -+[warning: Duplicate build-ids -+warning: Duplicate build-ids -+main id in main package -+main dup id in main package -+compat id in debug package -+compat dup id in debug package -+debug id in debug package -+debug dup id in debug package -+], -+[]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that hard linked files are handled correctly. -+# Since the hard linked files have duplicate build-ids, -+# it should create "numbered" build-id files. -+# This is simply the hello example with one binary hard linked. -+AT_SETUP([rpmbuild buildid hardlink compat]) -+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="_build_id_links compat" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2ln.spec 2>&1 | grep "^warning: " \ -+ | cut -f1-3 -d' ' -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+hello_file=./usr/local/bin/hello -+ -+# Extract the build-id from the main file -+id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+# compat build-ids split... -+id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -+test -L "$id_file" && echo "main id in main package" -+id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" -+test -L "$id_dup_file" && echo "main dup id in main package" -+ -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# compat, so main (and debug) ids are (also) here -+compat_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" -+test -L "$compat_file" && echo "compat id in debug package" -+compat_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" -+test -L "$compat_dup_file" && echo "compat dup id in debug package" -+ -+debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" -+test -L "$debug_id_file" && echo "debug id in debug package" -+debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" -+test -L "$debug_dup_file" && echo "debug dup id in debug package" -+ -+# We don't know which points to which, but we do know they point -+# to different files. -+canon_id_file=$(readlink -f ${id_file}) -+canon_dup_file=$(readlink -f ${id_dup_file}) -+test "$canon_id_file" != "$canon_dup_file" \ -+ || echo "id and dup same" -+ -+canon_debug_id_file=$(readlink -f ${debug_id_file}) -+canon_debug_dup_file=$(readlink -f ${debug_dup_file}) -+test "$canon_debug_id_file" != "$canon_debug_dup_file" \ -+ || echo "debug id and dup same" -+ -+canon_compat_file=$(readlink -f ${compat_file}) -+canon_compat_dup_file=$(readlink -f ${compat_dup_file}) -+test "$canon_compat_file" != "$canon_compat_dup_file" \ -+ || echo "compat id and dup same" -+], -+[0], -+[main id in main package -+main dup id in main package -+compat id in debug package -+compat dup id in debug package -+debug id in debug package -+debug dup id in debug package -+], -+[]) -+AT_CLEANUP -\ No newline at end of file -diff --git a/tests/rpmtests.at b/tests/rpmtests.at -index b51266a..5495cce 100644 ---- a/tests/rpmtests.at -+++ b/tests/rpmtests.at -@@ -4,6 +4,7 @@ m4_include([rpmverify.at]) - m4_include([rpmdb.at]) - m4_include([rpmi.at]) - m4_include([rpmbuild.at]) -+m4_include([rpmbuildid.at]) - m4_include([rpmscript.at]) - m4_include([rpmvercmp.at]) - m4_include([rpmdeps.at]) --- -2.9.3 - diff --git a/0001-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch b/0001-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch deleted file mode 100644 index b44247a..0000000 --- a/0001-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 6739797e1c4a1c24f691568956597adcaece788e Mon Sep 17 00:00:00 2001 -From: Florian Festi -Date: Tue, 28 Feb 2017 10:57:56 +0100 -Subject: [PATCH 1/6] Use RPMTAG_*NAME instead of RPMTAG_*FLAGS in - parsePreamble.c and parseRCPOT() - -Using the FLGS tags is awkward and inconsistent with other part of the code -routinly use the NAME tags to denominate the type of dependencies. -This is also going to make using parseRCPOT() easier for the rpmfc code -that is also based on NAME tags. - -(cherry picked from commit 9d5bbd9774d00f50749bb045217eaf91c87b6de0) ---- - build/parsePreamble.c | 36 ++++++++++++++++++------------------ - build/parseReqs.c | 37 +++++++++++-------------------------- - build/rpmfc.c | 2 +- - 3 files changed, 30 insertions(+), 45 deletions(-) - -diff --git a/build/parsePreamble.c b/build/parsePreamble.c -index 3bb833cff..bc639e86c 100644 ---- a/build/parsePreamble.c -+++ b/build/parsePreamble.c -@@ -850,8 +850,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, - if (parseNoSource(spec, field, tag)) - goto exit; - break; -- case RPMTAG_ORDERFLAGS: -- case RPMTAG_REQUIREFLAGS: -+ case RPMTAG_ORDERNAME: -+ case RPMTAG_REQUIRENAME: - if (parseBits(lang, installScriptBits, &tagflags)) { - rpmlog(RPMLOG_ERR, _("line %d: Bad %s: qualifiers: %s\n"), - spec->lineNum, rpmTagGetName(tag), spec->line); -@@ -859,13 +859,13 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, - } - /* fallthrough */ - case RPMTAG_PREREQ: -- case RPMTAG_RECOMMENDFLAGS: -- case RPMTAG_SUGGESTFLAGS: -- case RPMTAG_SUPPLEMENTFLAGS: -- case RPMTAG_ENHANCEFLAGS: -- case RPMTAG_CONFLICTFLAGS: -- case RPMTAG_OBSOLETEFLAGS: -- case RPMTAG_PROVIDEFLAGS: -+ case RPMTAG_RECOMMENDNAME: -+ case RPMTAG_SUGGESTNAME: -+ case RPMTAG_SUPPLEMENTNAME: -+ case RPMTAG_ENHANCENAME: -+ case RPMTAG_CONFLICTNAME: -+ case RPMTAG_OBSOLETENAME: -+ case RPMTAG_PROVIDENAME: - if (parseRCPOT(spec, pkg, field, tag, 0, tagflags)) - goto exit; - break; -@@ -970,15 +970,15 @@ static struct PreambleRec_s const preambleList[] = { - {RPMTAG_EXCLUDEOS, 0, 0, LEN_AND_STR("excludeos")}, - {RPMTAG_EXCLUSIVEOS, 0, 0, LEN_AND_STR("exclusiveos")}, - {RPMTAG_ICON, 0, 0, LEN_AND_STR("icon")}, -- {RPMTAG_PROVIDEFLAGS, 0, 0, LEN_AND_STR("provides")}, -- {RPMTAG_REQUIREFLAGS, 2, 0, LEN_AND_STR("requires")}, -- {RPMTAG_RECOMMENDFLAGS, 0, 0, LEN_AND_STR("recommends")}, -- {RPMTAG_SUGGESTFLAGS, 0, 0, LEN_AND_STR("suggests")}, -- {RPMTAG_SUPPLEMENTFLAGS, 0, 0, LEN_AND_STR("supplements")}, -- {RPMTAG_ENHANCEFLAGS, 0, 0, LEN_AND_STR("enhances")}, -+ {RPMTAG_PROVIDENAME, 0, 0, LEN_AND_STR("provides")}, -+ {RPMTAG_REQUIRENAME, 2, 0, LEN_AND_STR("requires")}, -+ {RPMTAG_RECOMMENDNAME, 0, 0, LEN_AND_STR("recommends")}, -+ {RPMTAG_SUGGESTNAME, 0, 0, LEN_AND_STR("suggests")}, -+ {RPMTAG_SUPPLEMENTNAME, 0, 0, LEN_AND_STR("supplements")}, -+ {RPMTAG_ENHANCENAME, 0, 0, LEN_AND_STR("enhances")}, - {RPMTAG_PREREQ, 2, 1, LEN_AND_STR("prereq")}, -- {RPMTAG_CONFLICTFLAGS, 0, 0, LEN_AND_STR("conflicts")}, -- {RPMTAG_OBSOLETEFLAGS, 0, 0, LEN_AND_STR("obsoletes")}, -+ {RPMTAG_CONFLICTNAME, 0, 0, LEN_AND_STR("conflicts")}, -+ {RPMTAG_OBSOLETENAME, 0, 0, LEN_AND_STR("obsoletes")}, - {RPMTAG_PREFIXES, 0, 0, LEN_AND_STR("prefixes")}, - {RPMTAG_PREFIXES, 0, 0, LEN_AND_STR("prefix")}, - {RPMTAG_BUILDROOT, 0, 0, LEN_AND_STR("buildroot")}, -@@ -993,7 +993,7 @@ static struct PreambleRec_s const preambleList[] = { - {RPMTAG_DOCDIR, 0, 0, LEN_AND_STR("docdir")}, - {RPMTAG_DISTTAG, 0, 0, LEN_AND_STR("disttag")}, - {RPMTAG_BUGURL, 0, 0, LEN_AND_STR("bugurl")}, -- {RPMTAG_ORDERFLAGS, 2, 0, LEN_AND_STR("orderwithrequires")}, -+ {RPMTAG_ORDERNAME, 2, 0, LEN_AND_STR("orderwithrequires")}, - {RPMTAG_REMOVEPATHPOSTFIXES,0, 0, LEN_AND_STR("removepathpostfixes")}, - {0, 0, 0, 0} - }; -diff --git a/build/parseReqs.c b/build/parseReqs.c -index a443505e4..bd728ed2d 100644 ---- a/build/parseReqs.c -+++ b/build/parseReqs.c -@@ -132,33 +132,18 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - - switch (tagN) { - default: -- case RPMTAG_REQUIREFLAGS: -- nametag = RPMTAG_REQUIRENAME; -+ case RPMTAG_REQUIRENAME: - tagflags |= RPMSENSE_ANY; -- break; -- case RPMTAG_RECOMMENDFLAGS: -- nametag = RPMTAG_RECOMMENDNAME; -- break; -- case RPMTAG_SUGGESTFLAGS: -- nametag = RPMTAG_SUGGESTNAME; -- break; -- case RPMTAG_SUPPLEMENTFLAGS: -- nametag = RPMTAG_SUPPLEMENTNAME; -- break; -- case RPMTAG_ENHANCEFLAGS: -- nametag = RPMTAG_ENHANCENAME; -- break; -- case RPMTAG_PROVIDEFLAGS: -- nametag = RPMTAG_PROVIDENAME; -- break; -- case RPMTAG_OBSOLETEFLAGS: -- nametag = RPMTAG_OBSOLETENAME; -- break; -- case RPMTAG_CONFLICTFLAGS: -- nametag = RPMTAG_CONFLICTNAME; -- break; -- case RPMTAG_ORDERFLAGS: -- nametag = RPMTAG_ORDERNAME; -+ /* fall through */ -+ case RPMTAG_RECOMMENDNAME: -+ case RPMTAG_SUGGESTNAME: -+ case RPMTAG_SUPPLEMENTNAME: -+ case RPMTAG_ENHANCENAME: -+ case RPMTAG_PROVIDENAME: -+ case RPMTAG_OBSOLETENAME: -+ case RPMTAG_CONFLICTNAME: -+ case RPMTAG_ORDERNAME: -+ nametag = tagN; - break; - case RPMTAG_PREREQ: - /* XXX map legacy PreReq into Requires(pre,preun) */ -diff --git a/build/rpmfc.c b/build/rpmfc.c -index 73915015a..ce192fa9c 100644 ---- a/build/rpmfc.c -+++ b/build/rpmfc.c -@@ -1297,7 +1297,7 @@ static rpmRC rpmfcApplyExternal(rpmfc fc) - } - - /* Parse dependencies into header */ -- rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), tag, 0, tagflags); -+ rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags); - freeStringBuf(sb_stdout); - - if (rc) { --- -2.13.1 - diff --git a/0001-Use-correct-source-file-for-rpmsign-module.patch b/0001-Use-correct-source-file-for-rpmsign-module.patch new file mode 100644 index 0000000..9c02b6a --- /dev/null +++ b/0001-Use-correct-source-file-for-rpmsign-module.patch @@ -0,0 +1,26 @@ +From 3936d5a227dfcfd502588c6fd8f52ccb826f11c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Nikola=20Forr=C3=B3?= +Date: Wed, 20 Apr 2016 15:39:36 +0200 +Subject: [PATCH 01/49] Use correct source file for rpmsign module + +(cherry picked from commit eb632e5158fa4ef993b0e5df2a354f0be7a7a71d) +--- + python/setup.py.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/python/setup.py.in b/python/setup.py.in +index b2c394136..f94873fe5 100644 +--- a/python/setup.py.in ++++ b/python/setup.py.in +@@ -48,7 +48,7 @@ rpmbuild_mod = Extension('rpm._rpmb', + ) + + rpmsign_mod = Extension('rpm._rpms', +- sources = ['rpmbmodule.c'], ++ sources = ['rpmsmodule.c'], + include_dirs = pkgconfig('--cflags'), + libraries = pkgconfig('--libs') + ['rpmsign'], + extra_compile_args = cflags, +-- +2.13.2 + diff --git a/0002-Fix-check-for-weak-deps-in-external-dependency-gener.patch b/0002-Fix-check-for-weak-deps-in-external-dependency-gener.patch deleted file mode 100644 index 1bc5774..0000000 --- a/0002-Fix-check-for-weak-deps-in-external-dependency-gener.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 01dc6ada3bf33a06ad58d3b1246c287ac148d912 Mon Sep 17 00:00:00 2001 -From: Florian Festi -Date: Tue, 28 Feb 2017 17:42:21 +0100 -Subject: [PATCH 2/6] Fix check for weak deps in external dependency generator - -(cherry picked from commit 43d230884365d90d42184a0000f44bb33e5f1ab8) ---- - build/rpmfc.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/build/rpmfc.c b/build/rpmfc.c -index ce192fa9c..921814ad1 100644 ---- a/build/rpmfc.c -+++ b/build/rpmfc.c -@@ -1267,12 +1267,12 @@ static rpmRC rpmfcApplyExternal(rpmfc fc) - tagflags = RPMSENSE_FIND_PROVIDES; - break; - case RPMTAG_REQUIREFLAGS: -- case RPMTAG_RECOMMENDNAME: -- case RPMTAG_SUGGESTNAME: -- case RPMTAG_SUPPLEMENTNAME: -- case RPMTAG_ENHANCENAME: -- case RPMTAG_CONFLICTNAME: -- case RPMTAG_OBSOLETENAME: -+ case RPMTAG_RECOMMENDFLAGS: -+ case RPMTAG_SUGGESTFLAGS: -+ case RPMTAG_SUPPLEMENTFLAGS: -+ case RPMTAG_ENHANCEFLAGS: -+ case RPMTAG_CONFLICTFLAGS: -+ case RPMTAG_OBSOLETEFLAGS: - if (fc->skipReq) - continue; - tagflags = RPMSENSE_FIND_REQUIRES; --- -2.13.1 - diff --git a/0002-Make-it-possible-to-have-unique-build-ids-across-bui.patch b/0002-Make-it-possible-to-have-unique-build-ids-across-bui.patch deleted file mode 100644 index dc7ca3e..0000000 --- a/0002-Make-it-possible-to-have-unique-build-ids-across-bui.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 2a97fb48279af17049f96c661db040173185a650 Mon Sep 17 00:00:00 2001 -Message-Id: <2a97fb48279af17049f96c661db040173185a650.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Tue, 14 Jun 2016 17:07:13 +0200 -Subject: [PATCH 02/11] 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 ---- - 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 e43d62b0..dcd0961 100644 ---- a/macros.in -+++ b/macros.in -@@ -180,7 +180,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. -@@ -476,6 +476,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 c9e2293..2cb9570 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 - ;; -@@ -249,8 +263,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 -+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 -+- Update release for unique build-id generation tests. -+ -+* Tue Oct 20 1998 Jeff Johnson -+- 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 , 2002 - Based on code by Jakub Jelinek , 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.9.3 - diff --git a/0002-brp-python-bytecompile-Process-python-lib-dirs-even-.patch b/0002-brp-python-bytecompile-Process-python-lib-dirs-even-.patch new file mode 100644 index 0000000..00d41d9 --- /dev/null +++ b/0002-brp-python-bytecompile-Process-python-lib-dirs-even-.patch @@ -0,0 +1,50 @@ +From aa74f749e8eba102069aaafd0b2e18af8f5f0fa0 Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Tue, 14 Feb 2017 14:04:35 +0100 +Subject: [PATCH 02/49] brp-python-bytecompile: Process python lib dirs even + without standard Python + +There is no need for /usr/bin/python when byte compiling files in +/usr/lib/pythonX.Y (only /usr/bin/pythonX.Y). Moved check so we do not exit +prematurely. + +Fixes: rhbz#1411588 +(cherry picked from commit a8e51b3bb05c6acb1d9b2e3d34f859ddda1677be) +--- + scripts/brp-python-bytecompile | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/scripts/brp-python-bytecompile b/scripts/brp-python-bytecompile +index 838f23d9d..894fa3459 100644 +--- a/scripts/brp-python-bytecompile ++++ b/scripts/brp-python-bytecompile +@@ -6,12 +6,6 @@ if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then + exit 0 + fi + +-# If we don't have a python interpreter, avoid changing anything. +-default_python=${1:-/usr/bin/python} +-if [ ! -x "$default_python" ]; then +- exit 0 +-fi +- + # Figure out how deep we need to descend. We could pick an insanely high + # number and hope it's enough, but somewhere, somebody's sure to run into it. + depth=`(find "$RPM_BUILD_ROOT" -type f -name "*.py" -print0 ; echo /) | \ +@@ -86,7 +80,12 @@ done + + + # Handle other locations in the filesystem using the default python +-# implementation: ++# implementation - if we have a default python interpreter ++ ++default_python=${1:-/usr/bin/python} ++if [ ! -x "$default_python" ]; then ++ exit 0 ++fi + + # Generate normal (.pyc) byte-compiled files. + python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/" +-- +2.13.2 + diff --git a/0003-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch b/0003-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch deleted file mode 100644 index cb5b200..0000000 --- a/0003-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 950eafdaac08cb618a4b5a8c923f1535985bcdc3 Mon Sep 17 00:00:00 2001 -From: Florian Festi -Date: Thu, 9 Mar 2017 12:12:32 +0100 -Subject: [PATCH 3/6] Fix check whether to allow rich deps in a given tag - -Broken with 9d5bbd9774d00f50749bb045217eaf91c87b6de0 - -(cherry picked from commit e4349ef7292578a7286bfca2e68a150422e65c3c) ---- - build/parseReqs.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/build/parseReqs.c b/build/parseReqs.c -index bd728ed2d..6c2aead4e 100644 ---- a/build/parseReqs.c -+++ b/build/parseReqs.c -@@ -129,6 +129,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - rpmTagVal nametag = RPMTAG_NOT_FOUND; - rpmsenseFlags Flags; - rpmRC rc = RPMRC_FAIL; /* assume failure */ -+ int allow_richdeps = 0; - - switch (tagN) { - default: -@@ -139,9 +140,11 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - case RPMTAG_SUGGESTNAME: - case RPMTAG_SUPPLEMENTNAME: - case RPMTAG_ENHANCENAME: -+ case RPMTAG_CONFLICTNAME: -+ allow_richdeps = 1; -+ /* fall through */ - case RPMTAG_PROVIDENAME: - case RPMTAG_OBSOLETENAME: -- case RPMTAG_CONFLICTNAME: - case RPMTAG_ORDERNAME: - nametag = tagN; - break; -@@ -149,6 +152,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - /* XXX map legacy PreReq into Requires(pre,preun) */ - nametag = RPMTAG_REQUIRENAME; - tagflags |= (RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_PREUN); -+ allow_richdeps = 1; - break; - case RPMTAG_TRIGGERPREIN: - nametag = RPMTAG_TRIGGERNAME; -@@ -209,9 +213,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - - if (r[0] == '(') { - struct parseRCPOTRichData data; -- if (nametag != RPMTAG_REQUIRENAME && nametag != RPMTAG_CONFLICTNAME && -- nametag != RPMTAG_RECOMMENDNAME && nametag != RPMTAG_SUPPLEMENTNAME && -- nametag != RPMTAG_SUGGESTNAME && nametag != RPMTAG_ENHANCENAME) { -+ if (!allow_richdeps) { - rasprintf(&emsg, _("No rich dependencies allowed for this type")); - goto exit; - } --- -2.13.1 - diff --git a/0003-Fix-number-of-references-on-spec_Type-114.patch b/0003-Fix-number-of-references-on-spec_Type-114.patch new file mode 100644 index 0000000..3774d3d --- /dev/null +++ b/0003-Fix-number-of-references-on-spec_Type-114.patch @@ -0,0 +1,83 @@ +From 6e748a4eb167b2ca201d9e90b927cc4523eabeda Mon Sep 17 00:00:00 2001 +From: Pavlina Moravcova Varekova +Date: Tue, 21 Feb 2017 11:48:27 +0100 +Subject: [PATCH 03/49] Fix number of references on spec_Type (#114) + +After creating a specPkg from a spec file we must increase spec file +reference counter. Otherwise spec file may be accidentally deallocated +and usage of SpecPkg can cause an error. + +(cherry picked from commit 34b61a1f82f6f9b675ab4ca820b6255af63680f1) +--- + python/spec-py.c | 14 +++++++++++--- + python/spec-py.h | 2 +- + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/python/spec-py.c b/python/spec-py.c +index f710f5c87..753afbad4 100644 +--- a/python/spec-py.c ++++ b/python/spec-py.c +@@ -45,8 +45,14 @@ struct specPkgObject_s { + PyObject_HEAD + /*type specific fields */ + rpmSpecPkg pkg; ++ specObject *source_spec; + }; + ++static void specPkg_dealloc(specPkgObject * s) ++{ ++ Py_DECREF(s->source_spec); ++} ++ + static PyObject *pkgGetSection(rpmSpecPkg pkg, int section) + { + char *sect = rpmSpecPkgGetSection(pkg, section); +@@ -95,7 +101,7 @@ PyTypeObject specPkg_Type = { + "rpm.specpkg", /* tp_name */ + sizeof(specPkgObject), /* tp_size */ + 0, /* tp_itemsize */ +- 0, /* tp_dealloc */ ++ (destructor) specPkg_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ +@@ -227,7 +233,7 @@ static PyObject * spec_get_packages(specObject *s, void *closure) + iter = rpmSpecPkgIterInit(s->spec); + + while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) { +- PyObject *po = specPkg_Wrap(&specPkg_Type, pkg); ++ PyObject *po = specPkg_Wrap(&specPkg_Type, pkg, s); + if (!po) { + rpmSpecPkgIterFree(iter); + Py_DECREF(pkgList); +@@ -350,12 +356,14 @@ spec_Wrap(PyTypeObject *subtype, rpmSpec spec) + return (PyObject *) s; + } + +-PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg) ++PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source) + { + specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->pkg = pkg; ++ s->source_spec = source; ++ Py_INCREF(s->source_spec); + return (PyObject *) s; + } + +diff --git a/python/spec-py.h b/python/spec-py.h +index 558fbf207..65b8dc3d7 100644 +--- a/python/spec-py.h ++++ b/python/spec-py.h +@@ -13,6 +13,6 @@ extern PyTypeObject specPkg_Type; + #define specPkgObject_Check(v) ((v)->ob_type == &specPkg_Type) + + PyObject * spec_Wrap(PyTypeObject *subtype, rpmSpec spec); +-PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg); ++PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source); + + #endif /* RPMPYTHON_SPEC */ +-- +2.13.2 + diff --git a/0003-Make-adding-GDB-index-sections-configurable.patch b/0003-Make-adding-GDB-index-sections-configurable.patch deleted file mode 100644 index e8722bc..0000000 --- a/0003-Make-adding-GDB-index-sections-configurable.patch +++ /dev/null @@ -1,214 +0,0 @@ -From 270b8627b03bc39fb008a7da1a4fd6b259ff92b8 Mon Sep 17 00:00:00 2001 -Message-Id: <270b8627b03bc39fb008a7da1a4fd6b259ff92b8.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Tue, 14 Jun 2016 17:07:14 +0200 -Subject: [PATCH 03/11] Make adding GDB index sections configurable. - -Introduces _include_gdb_index macro and -i flag to find-debuginfo.sh to -enable or disable adding a .gdb_index section to debug files. Adds tests -to make sure the .gdb_index is really added (or not) when requested. -Checks that gdb-add-index is actually installed instead of silently -failing if not. Similar for dwz. - -Signed-off-by: Mark Wielaard ---- - macros.debug | 1 + - macros.in | 8 ++++++- - scripts/find-debuginfo.sh | 29 ++++++++++++++++++---- - tests/rpmbuild.at | 61 +++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 94 insertions(+), 5 deletions(-) - -diff --git a/macros.debug b/macros.debug -index 6a8432e..d273c08 100644 ---- a/macros.debug -+++ b/macros.debug -@@ -2,6 +2,7 @@ - - %_enable_debug_packages 1 - %_include_minidebuginfo 1 -+%_include_gdb_index 1 - - # Expanded at end of %install scriptlet - -diff --git a/macros.in b/macros.in -index dcd0961..c845f58 100644 ---- a/macros.in -+++ b/macros.in -@@ -180,7 +180,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} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ - %{nil} - - # Template for debug information sub-package. -@@ -449,6 +449,12 @@ package or when debugging this package.\ - #%_include_minidebuginfo 1 - - # -+# Include a .gdb_index section in the .debug files. -+# Requires _enable_debug_packages and gdb-add-index installed. -+# -+#%_include_gdb_index 1 -+ -+# - # Defines how and if build_id links are generated for ELF files. - # The following settings are supported: - # -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index 2cb9570..8e60813 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] [-m] -+# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] - # [-o debugfiles.list] - # [--run-dwz] [--dwz-low-mem-die-limit N] - # [--dwz-max-die-limit N] -@@ -14,6 +14,8 @@ - # The --strict-build-id flag says to exit with failure status if - # any ELF binary processed fails to contain a build-id note. - # The -r flag says to use eu-strip --reloc-debug-sections. -+# The -m flag says to include a .gnu_debugdata section in the main binary. -+# The -i flag says to include a .gdb_index section in the .debug file. - # - # A single -o switch before any -l or -p switches simply renames - # the primary output file from debugfiles.list to something else. -@@ -48,6 +50,9 @@ strip_r=false - # with -m arg, add minimal debuginfo to binary. - include_minidebug=false - -+# with -i arg, add GDB index to .debug file. -+include_gdb_index=false -+ - # Barf on missing build IDs. - strict=false - -@@ -88,6 +93,9 @@ while [ $# -gt 0 ]; do - -m) - include_minidebug=true - ;; -+ -i) -+ include_gdb_index=true -+ ;; - -o) - if [ -z "${lists[$nout]}" -a -z "${ptns[$nout]}" ]; then - out=$2 -@@ -277,7 +285,15 @@ while read nlinks inum f; do - $strict && exit 2 - fi - -- type gdb-add-index >/dev/null 2>&1 && gdb-add-index "$f" > /dev/null 2>&1 -+ # Add .gdb_index if requested. -+ if $include_gdb_index; then -+ if type gdb-add-index >/dev/null 2>&1; then -+ gdb-add-index "$f" -+ else -+ echo >&2 "*** ERROR: GDB index requested, but no gdb-add-index installed" -+ exit 2 -+ fi -+ fi - - # A binary already copied into /usr/lib/debug doesn't get stripped, - # just has its file names collected and adjusted. -@@ -303,7 +319,7 @@ while read nlinks inum f; do - done || exit - - # Invoke the DWARF Compressor utility. --if $run_dwz && type dwz >/dev/null 2>&1 \ -+if $run_dwz \ - && [ -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 -@@ -321,7 +337,12 @@ if $run_dwz && type dwz >/dev/null 2>&1 \ - && 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 ) -+ if type dwz >/dev/null 2>&1; then -+ ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts $dwz_files ) -+ else -+ echo >&2 "*** ERROR: DWARF compression requested, but no dwz installed" -+ exit 2 -+ fi - # 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 -diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at -index 1531700..a312324 100644 ---- a/tests/rpmbuild.at -+++ b/tests/rpmbuild.at -@@ -532,3 +532,64 @@ usr/local/bin/hello2 - ], - [ignore]) - AT_CLEANUP -+ -+# ------------------------------ -+# Check that a GDB index is included when requested. -+AT_SETUP([rpmbuild debuginfo gdb index included]) -+AT_KEYWORDS([build] [debuginfo] [gdb]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Build a package that has some debuginfo -+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 \ -+ --define "_include_gdb_index 1" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2.spec -+ -+# Unpack the debuginfo rpms so we can check the .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# Check that gdb-add-index has ran and a .gdb_index section has been added -+readelf -S ./usr/lib/debug/usr/local/bin/hello2*.debug \ -+ | grep gdb_index | cut -c8-17 -+], -+[0], -+[.gdb_index -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that a GDB index is NOT included when not requested. -+AT_SETUP([rpmbuild debuginfo no gdb index included]) -+AT_KEYWORDS([build] [debuginfo] [gdb]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Build a package that has some debuginfo -+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 \ -+ --undefine "_include_gdb_index" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2.spec -+ -+# Unpack the debuginfo rpms so we can check the .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# Check that gdb-add-index has not ran and no .gdb_index section has been added -+readelf -S ./usr/lib/debug/usr/local/bin/hello2*.debug \ -+ | grep gdb_index | cut -c8-17 -+], -+[0], -+[], -+[ignore]) -+AT_CLEANUP --- -2.9.3 - diff --git a/0004-Add-build-id-links-to-rpm-for-all-ELF-files.patch b/0004-Add-build-id-links-to-rpm-for-all-ELF-files.patch new file mode 100644 index 0000000..ea77b8b --- /dev/null +++ b/0004-Add-build-id-links-to-rpm-for-all-ELF-files.patch @@ -0,0 +1,1566 @@ +From 46b763e54de34d0dd28d82e3a87b59c6a94a4c07 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 14 Jun 2016 17:07:12 +0200 +Subject: [PATCH 04/49] Add build-id links to rpm for all ELF files. + +This patch moves the main ELF file build-id symlinks from the +debuginfo package into the main package. And uses different +base directories for the main ELF file build-id symlink. +For the main build-id use /usr/lib/.build-id and for the debug +build-id use /usr/lib/debug/.build-id. + +There are two reasons for doing this. The main package and the +debuginfo package might get out of sync, or the debuginfo package +might not be installed at all. In which case finding the main ELF +file through the build-id symlink becomes impossible. Secondly by +moving the main ELF build-id symlink in its own directory the +/usr/lib/debug directory gets populated with only debuginfo files +which is convenient if the user might want to have that directory +populated through a network mountpoint. + +To support the new logic the symlink code has been moved from +find-debuginfo.sh to build/files.c. + +This also includes support for a new config %_build_id_links that +defaults to compat. The other settings are none, alldebug (the old +style) and separate. compat is like separate, but adds a compatibility +link under /usr/lib/debug/.build-id for the main build-id symlink. + +There are several new testcases added to test the various settings +using the new keyword "buildid". + +Signed-off-by: Mark Wielaard +(cherry picked from commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2) +--- + build/Makefile.am | 4 + + build/files.c | 375 ++++++++++++++++++++ + configure.ac | 15 + + macros.in | 28 ++ + scripts/find-debuginfo.sh | 60 ---- + tests/Makefile.am | 1 + + tests/data/SPECS/hello2cp.spec | 64 ++++ + tests/data/SPECS/hello2ln.spec | 63 ++++ + tests/rpmbuildid.at | 761 +++++++++++++++++++++++++++++++++++++++++ + tests/rpmtests.at | 1 + + 10 files changed, 1312 insertions(+), 60 deletions(-) + create mode 100644 tests/data/SPECS/hello2cp.spec + create mode 100644 tests/data/SPECS/hello2ln.spec + create mode 100644 tests/rpmbuildid.at + +diff --git a/build/Makefile.am b/build/Makefile.am +index dbda716ac..71edbd1c4 100644 +--- a/build/Makefile.am ++++ b/build/Makefile.am +@@ -26,3 +26,7 @@ librpmbuild_la_LIBADD = \ + @LTLIBICONV@ \ + @WITH_POPT_LIB@ \ + @WITH_MAGIC_LIB@ ++ ++if LIBDW ++librpmbuild_la_LIBADD += @WITH_LIBELF_LIB@ @WITH_LIBDW_LIB@ ++endif +diff --git a/build/files.c b/build/files.c +index b76ce048f..b010483e4 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -14,6 +14,11 @@ + #include + #endif + ++#if HAVE_LIBDW ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -1551,6 +1556,368 @@ exit: + return rc; + } + ++#if HAVE_LIBDW ++/* How build id links are generated. See macros.in for description. */ ++#define BUILD_IDS_NONE 0 ++#define BUILD_IDS_ALLDEBUG 1 ++#define BUILD_IDS_SEPARATE 2 ++#define BUILD_IDS_COMPAT 3 ++ ++static int addNewIDSymlink(FileList fl, ++ char *targetpath, char *idlinkpath, ++ int isDbg, int isCompat) ++{ ++ const char *linkerr = _("failed symlink"); ++ int rc = 0; ++ int nr = 0; ++ char *origpath, *linkpath; ++ ++ if (isDbg) ++ rasprintf(&linkpath, "%s.debug", idlinkpath); ++ else ++ linkpath = idlinkpath; ++ origpath = linkpath; ++ ++ while (faccessat(AT_FDCWD, linkpath, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { ++ if (nr > 0) ++ free(linkpath); ++ nr++; ++ rasprintf(&linkpath, "%s.%d%s", idlinkpath, nr, ++ isDbg ? ".debug" : ""); ++ } ++ ++ char *symtarget = targetpath; ++ if (nr > 0 && isCompat) ++ rasprintf (&symtarget, "%s.%d", targetpath, nr); ++ ++ if (symlink(symtarget, linkpath) < 0) { ++ rc = 1; ++ rpmlog(RPMLOG_ERR, "%s: %s -> %s: %m\n", ++ linkerr, linkpath, symtarget); ++ } else { ++ fl->cur.isDir = 0; ++ rc = addFile(fl, linkpath, NULL); ++ } ++ ++ /* Don't warn (again) if this is a compat id-link, we retarget it. */ ++ if (nr > 0 && !isCompat) { ++ /* Lets see why there are multiple build-ids. If the original ++ targets are hard linked, then it is OK, otherwise warn ++ something fishy is going on. Would be nice to call ++ something like eu-elfcmp to see if they are really the same ++ ELF file or not. */ ++ struct stat st1, st2; ++ if (stat (origpath, &st1) != 0) { ++ rpmlog(RPMLOG_WARNING, _("Duplicate build-id, stat %s: %m\n"), ++ origpath); ++ } else if (stat (linkpath, &st2) != 0) { ++ rpmlog(RPMLOG_WARNING, _("Duplicate build-id, stat %s: %m\n"), ++ linkpath); ++ } else if (!(S_ISREG(st1.st_mode) && S_ISREG(st2.st_mode) ++ && st1.st_nlink > 1 && st2.st_nlink == st1.st_nlink ++ && st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev)) { ++ char *rpath1 = realpath(origpath, NULL); ++ char *rpath2 = realpath(linkpath, NULL); ++ rpmlog(RPMLOG_WARNING, _("Duplicate build-ids %s and %s\n"), ++ rpath1, rpath2); ++ free(rpath1); ++ free(rpath2); ++ } ++ } ++ ++ if (isDbg) ++ free(origpath); ++ if (nr > 0) ++ free(linkpath); ++ if (nr > 0 && isCompat) ++ free(symtarget); ++ ++ return rc; ++} ++ ++static int generateBuildIDs(FileList fl) ++{ ++ int rc = 0; ++ int i; ++ FileListRec flp; ++ char **ids = NULL; ++ char **paths = NULL; ++ size_t nr_ids, allocated; ++ nr_ids = allocated = 0; ++ ++ /* How are we supposed to create the build-id links? */ ++ char *build_id_links_macro = rpmExpand("%{?_build_id_links}", NULL); ++ int build_id_links; ++ if (build_id_links_macro == NULL) { ++ rpmlog(RPMLOG_WARNING, ++ _("_build_id_links macro not set, assuming 'compat'\n")); ++ build_id_links = BUILD_IDS_COMPAT; ++ } else if (strcmp(build_id_links_macro, "none") == 0) { ++ build_id_links = BUILD_IDS_NONE; ++ } else if (strcmp(build_id_links_macro, "alldebug") == 0) { ++ build_id_links = BUILD_IDS_ALLDEBUG; ++ } else if (strcmp(build_id_links_macro, "separate") == 0) { ++ build_id_links = BUILD_IDS_SEPARATE; ++ } else if (strcmp(build_id_links_macro, "compat") == 0) { ++ build_id_links = BUILD_IDS_COMPAT; ++ } else { ++ rc = 1; ++ rpmlog(RPMLOG_ERR, ++ _("_build_id_links macro set to unknown value '%s'\n"), ++ build_id_links_macro); ++ build_id_links = BUILD_IDS_NONE; ++ } ++ free(build_id_links_macro); ++ ++ if (build_id_links == BUILD_IDS_NONE || rc != 0) ++ return rc; ++ ++ int terminate = rpmExpandNumeric("%{?_missing_build_ids_terminate_build}"); ++ ++ /* Collect and check all build-ids for ELF files in this package. */ ++ int needMain = 0; ++ int needDbg = 0; ++ for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { ++ int fd; ++ fd = open (flp->diskPath, O_RDONLY); ++ if (fd >= 0) { ++ struct stat sbuf; ++ if (fstat (fd, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { ++ Elf *elf = elf_begin (fd, ELF_C_READ, NULL); ++ if (elf != NULL && elf_kind(elf) == ELF_K_ELF) { ++ const void *build_id; ++ ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id); ++ /* len == -1 means error. Zero means no ++ build-id. We want at least a length of 2 so we ++ have at least a xx/yy (hex) dir/file. But ++ reasonable build-ids are between 16 bytes (md5 ++ is 128 bits) and 64 bytes (largest sha3 is 512 ++ bits), common is 20 bytes (sha1 is 160 bits). */ ++ if (len >= 16 && len <= 64) { ++ /* We determine whether this is a main or ++ debug ELF based on path. */ ++ #define DEBUGPATH "/usr/lib/debug/" ++ int addid = 0; ++ if (strncmp (flp->cpioPath, ++ DEBUGPATH, strlen (DEBUGPATH)) == 0) { ++ needDbg = 1; ++ addid = 1; ++ } ++ else if (build_id_links != BUILD_IDS_ALLDEBUG) { ++ needMain = 1; ++ addid = 1; ++ } ++ if (addid) { ++ const unsigned char *p = build_id; ++ const unsigned char *end = p + len; ++ char *id_str; ++ if (allocated <= nr_ids) { ++ allocated += 16; ++ paths = xrealloc (paths, ++ allocated * sizeof(char *)); ++ ids = xrealloc (ids, ++ allocated * sizeof(char *)); ++ } ++ ++ paths[nr_ids] = xstrdup(flp->cpioPath); ++ id_str = ids[nr_ids] = xmalloc(2 * len + 1); ++ while (p < end) ++ id_str += sprintf(id_str, "%02x", ++ (unsigned)*p++); ++ *id_str = '\0'; ++ nr_ids++; ++ } ++ } else { ++ if (len < 0) { ++ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, ++ _("error reading build-id in %s: %s\n"), ++ flp->diskPath, elf_errmsg (-1)); ++ } else if (len == 0) { ++ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, ++ _("Missing build-id in %s\n"), ++ flp->diskPath); ++ } else { ++ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, ++ (len < 16 ++ ? _("build-id found in %s too small\n") ++ : _("build-id found in %s too large\n")), ++ flp->diskPath); ++ } ++ if (terminate) ++ rc = 1; ++ } ++ elf_end (elf); ++ } ++ } ++ close (fd); ++ } ++ } ++ ++ /* Process and clean up all build-ids. */ ++ if (nr_ids > 0) { ++ const char *errdir = _("failed to create directory"); ++ char *mainiddir = NULL; ++ char *debugiddir = NULL; ++ if (rc == 0) { ++ /* Add .build-id directories to hold the subdirs/symlinks. */ ++ #define BUILD_ID_DIR "/usr/lib/.build-id" ++ #define DEBUG_ID_DIR "/usr/lib/debug/.build-id" ++ ++ mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL); ++ debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL); ++ ++ /* Supported, but questionable. */ ++ if (needMain && needDbg) ++ rpmlog(RPMLOG_WARNING, ++ _("Mixing main ELF and debug files in package")); ++ ++ if (needMain) { ++ if ((rc = rpmioMkpath(mainiddir, 0755, -1, -1)) != 0) { ++ rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, mainiddir); ++ } else { ++ fl->cur.isDir = 1; ++ rc = addFile(fl, mainiddir, NULL); ++ } ++ } ++ ++ if (rc == 0 && needDbg) { ++ if ((rc = rpmioMkpath(debugiddir, 0755, -1, -1)) != 0) { ++ rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, debugiddir); ++ } else { ++ fl->cur.isDir = 1; ++ rc = addFile(fl, debugiddir, NULL); ++ } ++ } ++ } ++ ++ /* Now add a subdir and symlink for each buildid found. */ ++ for (i = 0; i < nr_ids; i++) { ++ /* Don't add anything more when an error occured. But do ++ cleanup. */ ++ if (rc == 0) { ++ int isDbg = strncmp (paths[i], DEBUGPATH, ++ strlen (DEBUGPATH)) == 0; ++ ++ char *buildidsubdir; ++ char subdir[4]; ++ subdir[0] = '/'; ++ subdir[1] = ids[i][0]; ++ subdir[2] = ids[i][1]; ++ subdir[3] = '\0'; ++ if (isDbg) ++ buildidsubdir = rpmGetPath(debugiddir, subdir, NULL); ++ else ++ buildidsubdir = rpmGetPath(mainiddir, subdir, NULL); ++ /* We only need to create and add the subdir once. */ ++ int addsubdir = access (buildidsubdir, F_OK) == -1; ++ if (addsubdir ++ && (rc = rpmioMkpath(buildidsubdir, 0755, -1, -1)) != 0) { ++ rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, buildidsubdir); ++ } else { ++ fl->cur.isDir = 1; ++ if (!addsubdir ++ || (rc = addFile(fl, buildidsubdir, NULL)) == 0) { ++ char *linkpattern, *targetpattern; ++ char *linkpath, *targetpath; ++ if (isDbg) { ++ linkpattern = "%s/%s"; ++ targetpattern = "../../../../..%s"; ++ } else { ++ linkpattern = "%s/%s"; ++ targetpattern = "../../../..%s"; ++ } ++ rasprintf(&linkpath, linkpattern, ++ buildidsubdir, &ids[i][2]); ++ rasprintf(&targetpath, targetpattern, paths[i]); ++ rc = addNewIDSymlink(fl, targetpath, linkpath, ++ isDbg, 0); ++ ++ /* We might want to have a link from the debug ++ build_ids dir to the main one. We create it ++ when we are creating compat links or doing ++ an old style alldebug build-ids package. In ++ the first case things are simple since we ++ just link to the main build-id symlink. The ++ second case is a bit tricky, since we ++ cannot be 100% sure the file names in the ++ main and debug package match. Currently ++ they do, but when creating parallel ++ installable debuginfo packages they might ++ not (in that case we might have to also ++ strip the nvr from the debug name). ++ ++ In general either method is discouraged ++ since it might create dangling symlinks if ++ the package versions get out of sync. */ ++ if (rc == 0 && isDbg ++ && build_id_links == BUILD_IDS_COMPAT) { ++ /* buildidsubdir already points to the ++ debug buildid. We just need to setup ++ the symlink to the main one. */ ++ free(linkpath); ++ free(targetpath); ++ rasprintf(&linkpath, "%s/%s", ++ buildidsubdir, &ids[i][2]); ++ rasprintf(&targetpath, ++ "../../../.build-id%s/%s", ++ subdir, &ids[i][2]); ++ rc = addNewIDSymlink(fl, targetpath, linkpath, ++ 0, 1); ++ } ++ ++ if (rc == 0 && isDbg ++ && build_id_links == BUILD_IDS_ALLDEBUG) { ++ /* buildidsubdir already points to the ++ debug buildid. We do have to figure out ++ the main ELF file though (which is most ++ likely not in this package). Guess we ++ can find it by stripping the ++ /usr/lib/debug path and .debug ++ prefix. Which might not really be ++ correct if there was a more involved ++ transformation (for example for ++ parallel installable debuginfo ++ packages), but then we shouldn't be ++ using ALLDEBUG in the first place. ++ Also ignore things like .dwz multifiles ++ which don't end in ".debug". */ ++ int pathlen = strlen(paths[i]); ++ int debuglen = strlen(".debug"); ++ int prefixlen = strlen("/usr/lib/debug"); ++ if (pathlen > prefixlen ++ && strcmp (paths[i] + pathlen - debuglen, ++ ".debug") == 0) { ++ free(linkpath); ++ free(targetpath); ++ char *targetstr = xstrdup (paths[i] ++ + prefixlen); ++ int targetlen = pathlen - prefixlen; ++ targetstr[targetlen - debuglen] = '\0'; ++ rasprintf(&linkpath, "%s/%s", ++ buildidsubdir, &ids[i][2]); ++ rasprintf(&targetpath, "../../../../..%s", ++ targetstr); ++ rc = addNewIDSymlink(fl, targetpath, ++ linkpath, 0, 0); ++ free(targetstr); ++ } ++ } ++ free(linkpath); ++ free(targetpath); ++ } ++ } ++ free(buildidsubdir); ++ } ++ free(paths[i]); ++ free(ids[i]); ++ } ++ free(paths); ++ free(ids); ++ } ++ return rc; ++} ++#endif ++ + /** + * Add a file to a binary package. + * @param pkg +@@ -1963,6 +2330,11 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + if (fl.processingFailed) + goto exit; + ++#if HAVE_LIBDW ++ if (generateBuildIDs (&fl) != 0) ++ goto exit; ++#endif ++ + /* Verify that file attributes scope over hardlinks correctly. */ + if (checkHardLinks(&fl.files)) + (void) rpmlibNeedsFeature(pkg, "PartialHardlinkSets", "4.0.4-1"); +@@ -2161,6 +2533,9 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + Package pkg; + rpmRC rc = RPMRC_OK; + ++#if HAVE_LIBDW ++ elf_version (EV_CURRENT); ++#endif + check_fileList = newStringBuf(); + genSourceRpmName(spec); + +diff --git a/configure.ac b/configure.ac +index 91fadbade..8890c3c32 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -360,6 +360,21 @@ AC_SUBST(WITH_ARCHIVE_LIB) + AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) + + #================= ++# Check for elfutils libdw library with dwelf_elf_gnu_build_id. ++AS_IF([test "$WITH_LIBELF" = yes],[ ++ AC_CHECK_HEADERS([elfutils/libdwelf.h],[ ++ AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ ++ AC_DEFINE(HAVE_LIBDW, 1, ++ [Define to 1 if you have elfutils libdw library]) ++ WITH_LIBDW_LIB="-ldw" ++ WITH_LIBDW=yes ++ ]) ++ ]) ++ AC_SUBST(WITH_LIBDW_LIB) ++ AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) ++]) ++ ++#================= + # Process --with/without-external-db + AC_ARG_WITH(external_db, [AS_HELP_STRING([--with-external-db],[build against an external Berkeley db])], + [case "$with_external_db" in +diff --git a/macros.in b/macros.in +index fd57f2eba..e43d62b0a 100644 +--- a/macros.in ++++ b/macros.in +@@ -449,6 +449,34 @@ package or when debugging this package.\ + #%_include_minidebuginfo 1 + + # ++# Defines how and if build_id links are generated for ELF files. ++# The following settings are supported: ++# ++# - none ++# No build_id links are generated. ++# ++# - alldebug ++# build_id links are generated only when the __debug_package global is ++# defined. This will generate build_id links in the -debuginfo package ++# for both the main file as /usr/lib/debug/.build-id/xx/yyy and for ++# the .debug file as /usr/lib/debug/.build-id/xx/yyy.debug. ++# This is the old style build_id links as generated by the original ++# find-debuginfo.sh script. ++# ++# - separate ++# build_id links are generate for all binary packages. If this is a ++# main package (the __debug_package global isn't set) then the ++# build_id link is generated as /usr/lib/.build-id/xx/yyy. If this is ++# a -debuginfo package (the __debug_package global is set) then the ++# build_id link is generated as /usr/lib/debug/.build-id/xx/yyy. ++# ++# - compat ++# Same as for "separate" but if the __debug_package global is set then ++# the -debuginfo package will have a compatibility link for the main ++# ELF /usr/lib/debug/.build-id/xx/yyy -> /usr/lib/.build-id/xx/yyy ++%_build_id_links compat ++ ++# + # 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 4293261c9..c9e2293de 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -207,57 +207,6 @@ debug_link() + link_relative "$t" "$l" "$RPM_BUILD_ROOT" + } + +-# Provide .2, .3, ... symlinks to all filename instances of this build-id. +-make_id_dup_link() +-{ +- local id="$1" file="$2" idfile +- +- local n=1 +- while true; do +- idfile=".build-id/${id:0:2}/${id:2}.$n" +- [ $# -eq 3 ] && idfile="${idfile}$3" +- if [ ! -L "$RPM_BUILD_ROOT/usr/lib/debug/$idfile" ]; then +- break +- fi +- n=$[$n+1] +- done +- debug_link "$file" "/$idfile" +-} +- +-# Make a build-id symlink for id $1 with suffix $3 to file $2. +-make_id_link() +-{ +- local id="$1" file="$2" +- local idfile=".build-id/${id:0:2}/${id:2}" +- [ $# -eq 3 ] && idfile="${idfile}$3" +- local root_idfile="$RPM_BUILD_ROOT/usr/lib/debug/$idfile" +- +- if [ ! -L "$root_idfile" ]; then +- debug_link "$file" "/$idfile" +- return +- fi +- +- make_id_dup_link "$@" +- +- [ $# -eq 3 ] && return 0 +- +- local other=$(readlink -m "$root_idfile") +- other=${other#$RPM_BUILD_ROOT} +- if cmp -s "$root_idfile" "$RPM_BUILD_ROOT$file" || +- eu-elfcmp -q "$root_idfile" "$RPM_BUILD_ROOT$file" 2> /dev/null; then +- # Two copies. Maybe one has to be setuid or something. +- echo >&2 "*** WARNING: identical binaries are copied, not linked:" +- echo >&2 " $file" +- echo >&2 " and $other" +- else +- # This is pathological, break the build. +- echo >&2 "*** ERROR: same build ID in nonidentical files!" +- echo >&2 " $file" +- echo >&2 " and $other" +- exit 2 +- fi +-} +- + get_debugfn() + { + dn=$(dirname "${1#$RPM_BUILD_ROOT}") +@@ -288,8 +237,6 @@ while read nlinks inum f; do + eval linked=\$linked_$inum + if [ -n "$linked" ]; then + eval id=\$linkedid_$inum +- make_id_dup_link "$id" "$dn/$(basename $f)" +- make_id_dup_link "$id" "/usr/lib/debug$dn/$bn" .debug + link=$debugfn + get_debugfn "$linked" + echo "hard linked $link to $debugfn" +@@ -318,7 +265,6 @@ while read nlinks inum f; do + # just has its file names collected and adjusted. + case "$dn" in + /usr/lib/debug/*) +- [ -z "$id" ] || make_id_link "$id" "$dn/$(basename $f)" + continue ;; + esac + +@@ -336,10 +282,6 @@ while read nlinks inum f; do + + echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" + +- if [ -n "$id" ]; then +- make_id_link "$id" "$dn/$(basename $f)" +- make_id_link "$id" "/usr/lib/debug$dn/$bn" .debug +- fi + done || exit + + # Invoke the DWARF Compressor utility. +@@ -367,8 +309,6 @@ if $run_dwz && type dwz >/dev/null 2>&1 \ + 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 + + # dwz invalidates .gnu_debuglink CRC32 in the main files. +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 7a5cc6544..10555ce9a 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -19,6 +19,7 @@ TESTSUITE_AT += rpmquery.at + TESTSUITE_AT += rpmverify.at + TESTSUITE_AT += rpmdb.at + TESTSUITE_AT += rpmbuild.at ++TESTSUITE_AT += rpmbuildid.at + TESTSUITE_AT += rpmi.at + TESTSUITE_AT += rpmvercmp.at + TESTSUITE_AT += rpmdeps.at +diff --git a/tests/data/SPECS/hello2cp.spec b/tests/data/SPECS/hello2cp.spec +new file mode 100644 +index 000000000..33d8dc260 +--- /dev/null ++++ b/tests/data/SPECS/hello2cp.spec +@@ -0,0 +1,64 @@ ++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 ++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" ++cp hello hello2 ++ ++%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 ++* Mon Jun 6 2016 Mark Wielaard ++- Copy hello to hello2 for duplicate build-id testing. ++ ++* Wed May 18 2016 Mark Wielaard ++- Add hello2 for dwz testing support. ++ ++* Tue Oct 20 1998 Jeff Johnson ++- create. +diff --git a/tests/data/SPECS/hello2ln.spec b/tests/data/SPECS/hello2ln.spec +new file mode 100644 +index 000000000..2c40dcc32 +--- /dev/null ++++ b/tests/data/SPECS/hello2ln.spec +@@ -0,0 +1,63 @@ ++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 ++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" ++ ++%install ++rm -rf $RPM_BUILD_ROOT ++mkdir -p $RPM_BUILD_ROOT/usr/local/bin ++make DESTDIR=$RPM_BUILD_ROOT install ++ln $RPM_BUILD_ROOT/usr/local/bin/hello $RPM_BUILD_ROOT/usr/local/bin/hello2 ++ ++%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 ++* Mon Jun 6 2016 Mark Wielaard ++- Hard link hello to hello2 for duplicate build-id testing. ++ ++* Wed May 18 2016 Mark Wielaard ++- Add hello2 for dwz testing support. ++ ++* Tue Oct 20 1998 Jeff Johnson ++- create. +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +new file mode 100644 +index 000000000..eddca969b +--- /dev/null ++++ b/tests/rpmbuildid.at +@@ -0,0 +1,761 @@ ++# rpmbuildid.at: test rpmbuild buildid symlink support ++# ++# This file is part of RPM, the RPM Package Manager. ++# Copyright (C) 2016 Mark J. Wielaard ++# ++# This file is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# RPM is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++AT_BANNER([RPM buildid tests]) ++ ++# ------------------------------ ++# Check if rpmbuild "none" doesn't generates buildid symlinks for hello program ++AT_SETUP([rpmbuild buildid none]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links none" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be zero build-id files in both the main and debuginfo package ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++], ++[0], ++[hello build-id files: 0 ++hello debuginfo build-id files: 0 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks ++AT_SETUP([rpmbuild buildid alldebug]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links alldebug" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be zero build-id files in the main package ++# Main and debug should be in the debuginfo package, ++# plus the .build-id/xx subdir, 3 in total. ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++# Extract the both packages to check the build-id files link to the ++# main and .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ ++ | cpio -diu ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu ++ ++# Check there is a build-id symlink for the main file. ++main_file=./usr/local/bin/hello ++test -f "${main_file}" || echo "No main file ${main_file}" ++ ++# Extract the build-id from the main file ++id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_main_file" || echo "No build-id file $id_main_file" ++ ++canon_main_file=$(readlink -f ${main_file}) ++ ++test -f "$canon_main_file" \ ++ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" ++ ++canon_main_id_file=$(readlink -f ${id_main_file}) ++ ++test -f "$canon_main_id_file" \ ++ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" ++ ++test "$canon_main_file" = "$canon_main_id_file" \ ++ || echo "main and build-id file not linked" ++ ++# And check the same for the debug file. ++debug_file=./usr/lib/debug/usr/local/bin/hello.debug ++test -f "${debug_file}" || echo "No debug file ${debug_file}" ++ ++# Extract the build-id from the .debug file ++id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test ${id_main} = ${id_debug} || echo "unequal main and debug id" ++ ++id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" ++test -L "$id_debug_file" || echo "No build-id file $id_debug_file" ++ ++canon_debug_file=$(readlink -f ${debug_file}) ++ ++test -f "$canon_debug_file" \ ++ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" ++ ++canon_debug_id_file=$(readlink -f ${id_debug_file}) ++ ++test -f "$canon_debug_id_file" \ ++ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" ++ ++test "$canon_debug_file" = "$canon_debug_id_file" \ ++ || echo "debug and build-id not linked" ++], ++[0], ++[hello build-id files: 0 ++hello debuginfo build-id files: 3 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check if rpmbuild "separate" generates main and debuginfo buildid symlinks ++AT_SETUP([rpmbuild buildid separate]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links separate" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be one build-id files in the main and debuginfo package ++# plus the .build-id/xx subdir, 2 in total. ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++# Extract the both packages to check the build-id files link to the ++# main and .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ ++ | cpio -diu ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu ++ ++# Check there is a build-id symlink for the main file. ++main_file=./usr/local/bin/hello ++test -f "${main_file}" || echo "No main file ${main_file}" ++ ++# Extract the build-id from the main file ++id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_main_file" || echo "No build-id file $id_main_file" ++ ++canon_main_file=$(readlink -f ${main_file}) ++ ++test -f "$canon_main_file" \ ++ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" ++ ++canon_main_id_file=$(readlink -f ${id_main_file}) ++ ++test -f "$canon_main_id_file" \ ++ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" ++ ++test "$canon_main_file" = "$canon_main_id_file" \ ++ || echo "main and build-id file not linked" ++ ++# And check the same for the debug file. ++debug_file=./usr/lib/debug/usr/local/bin/hello.debug ++test -f "${debug_file}" || echo "No debug file ${debug_file}" ++ ++# Extract the build-id from the .debug file ++id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test ${id_main} = ${id_debug} || echo "unequal main and debug id" ++ ++id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" ++test -L "$id_debug_file" || echo "No build-id file $id_debug_file" ++ ++canon_debug_file=$(readlink -f ${debug_file}) ++ ++test -f "$canon_debug_file" \ ++ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" ++ ++canon_debug_id_file=$(readlink -f ${id_debug_file}) ++ ++test -f "$canon_debug_id_file" \ ++ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" ++ ++test "$canon_debug_file" = "$canon_debug_id_file" \ ++ || echo "debug and build-id not linked" ++], ++[0], ++[hello build-id files: 2 ++hello debuginfo build-id files: 2 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check if rpmbuild "compat" generates main and debuginfo buildid symlinks ++AT_SETUP([rpmbuild buildid compat]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links compat" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be one build-id files in the main and debuginfo package. ++# the debuginfo package has one extra main build-id compat symlink ++# plus the .build-id/xx subdir, 2 in total in main, 3 in total in debug ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++# Extract the both packages to check the build-id files link to the ++# main and .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ ++ | cpio -diu ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu ++ ++# Check there is a build-id symlink for the main file. ++main_file=./usr/local/bin/hello ++test -f "${main_file}" || echo "No main file ${main_file}" ++ ++# Extract the build-id from the main file ++id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_main_file" || echo "No build-id file $id_main_file" ++ ++canon_main_file=$(readlink -f ${main_file}) ++ ++test -f "$canon_main_file" \ ++ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" ++ ++canon_main_id_file=$(readlink -f ${id_main_file}) ++ ++test -f "$canon_main_id_file" \ ++ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" ++ ++test "$canon_main_file" = "$canon_main_id_file" \ ++ || echo "main and build-id file not linked" ++ ++# And check the same for the debug file. ++debug_file=./usr/lib/debug/usr/local/bin/hello.debug ++test -f "${debug_file}" || echo "No debug file ${debug_file}" ++ ++# Extract the build-id from the .debug file ++id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test ${id_main} = ${id_debug} || echo "unequal main and debug id" ++ ++id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" ++test -L "$id_debug_file" || echo "No build-id file $id_debug_file" ++ ++canon_debug_file=$(readlink -f ${debug_file}) ++ ++test -f "$canon_debug_file" \ ++ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" ++ ++canon_debug_id_file=$(readlink -f ${id_debug_file}) ++ ++test -f "$canon_debug_id_file" \ ++ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" ++ ++test "$canon_debug_file" = "$canon_debug_id_file" \ ++ || echo "debug and build-id not linked" ++ ++# The compat link should also point to the same (indirectly). ++id_compat_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_compat_file" || echo "No build-id compat file $id_compat_file" ++ ++canon_compat_file=$(readlink -f ${id_compat_file}) ++ ++test -f "$canon_compat_file" \ ++ || echo "Cannot resolve compat file ${id_compat_file} -> ${canon_compat_file}" ++ ++test "$canon_compat_file" = "$canon_main_file" \ ++ || echo "compat and build-id not linked" ++], ++[0], ++[hello build-id files: 2 ++hello debuginfo build-id files: 3 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that (copied) files with duplicate build-ids are handled correctly. ++# This should create "numbered" build-id files. ++# This is simply the hello example with one binary copied. ++AT_SETUP([rpmbuild buildid duplicate alldebug]) ++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 ++ ++# Should create two warnings ++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="_build_id_links alldebug" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2cp.spec 2>&1 | grep "^warning: " \ ++ | cut -f1-3 -d' ' ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++hello_file=./usr/local/bin/hello ++ ++# Extract the build-id from the main file ++id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++# alldebug not here... ++id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" ++test -L "$id_file" && echo "main id in main package" ++id_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" ++test -L "$id_dup_file" && echo "main dup id in main package" ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# alldebug, so they are all here ++test -L "$id_file" && echo "main id in debug package" ++test -L "$id_dup_file" && echo "main dup id in debug package" ++ ++debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" ++test -L "$debug_id_file" && echo "debug id in debug package" ++debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" ++test -L "$debug_dup_file" && echo "debug dup id in debug package" ++ ++# We don't know which points to which, but we do know they point ++# to different files. ++canon_id_file=$(readlink -f ${id_file}) ++canon_dup_file=$(readlink -f ${id_dup_file}) ++test "$canon_id_file" != "$canon_dup_file" \ ++ || echo "id and dup same" ++ ++canon_debug_id_file=$(readlink -f ${debug_id_file}) ++canon_debug_dup_file=$(readlink -f ${debug_dup_file}) ++test "$canon_debug_id_file" != "$canon_debug_dup_file" \ ++ || echo "debug id and dup same" ++], ++[0], ++[warning: Duplicate build-ids ++warning: Duplicate build-ids ++main id in debug package ++main dup id in debug package ++debug id in debug package ++debug dup id in debug package ++], ++[]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that hard linked files are handled correctly. ++# Since the hard linked files have duplicate build-ids, ++# it should create "numbered" build-id files. ++# This is simply the hello example with one binary hard linked. ++AT_SETUP([rpmbuild buildid hardlink alldebug]) ++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="_build_id_links alldebug" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2ln.spec 2>&1 | grep "^warning: " \ ++ | cut -f1-3 -d' ' ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++hello_file=./usr/local/bin/hello ++ ++# Extract the build-id from the main file ++id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++# alldebug not here... ++id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" ++test -L "$id_file" && echo "main id in main package" ++id_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" ++test -L "$id_dup_file" && echo "main dup id in main package" ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# alldebug, so they are all here ++test -L "$id_file" && echo "main id in debug package" ++test -L "$id_dup_file" && echo "main dup id in debug package" ++ ++debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" ++test -L "$debug_id_file" && echo "debug id in debug package" ++debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" ++test -L "$debug_dup_file" && echo "debug dup id in debug package" ++ ++# We don't know which points to which, but we do know they point ++# to different files. ++canon_id_file=$(readlink -f ${id_file}) ++canon_dup_file=$(readlink -f ${id_dup_file}) ++test "$canon_id_file" != "$canon_dup_file" \ ++ || echo "id and dup same" ++ ++canon_debug_id_file=$(readlink -f ${debug_id_file}) ++canon_debug_dup_file=$(readlink -f ${debug_dup_file}) ++test "$canon_debug_id_file" != "$canon_debug_dup_file" \ ++ || echo "debug id and dup same" ++], ++[0], ++[main id in debug package ++main dup id in debug package ++debug id in debug package ++debug dup id in debug package ++], ++[]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that (copied) files with duplicate build-ids are handled correctly. ++# This should create "numbered" build-id files. ++# This is simply the hello example with one binary copied. ++AT_SETUP([rpmbuild buildid duplicate separate]) ++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 ++ ++# Should create two warnings ++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="_build_id_links separate" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2cp.spec 2>&1 | grep "^warning: " \ ++ | cut -f1-3 -d' ' ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++hello_file=./usr/local/bin/hello ++ ++# Extract the build-id from the main file ++id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++# separate build-ids split... ++id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" ++test -L "$id_file" && echo "main id in main package" ++id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" ++test -L "$id_dup_file" && echo "main dup id in main package" ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# seperate, so debug ids are here ++debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" ++test -L "$debug_id_file" && echo "debug id in debug package" ++debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" ++test -L "$debug_dup_file" && echo "debug dup id in debug package" ++ ++# We don't know which points to which, but we do know they point ++# to different files. ++canon_id_file=$(readlink -f ${id_file}) ++canon_dup_file=$(readlink -f ${id_dup_file}) ++test "$canon_id_file" != "$canon_dup_file" \ ++ || echo "id and dup same" ++ ++canon_debug_id_file=$(readlink -f ${debug_id_file}) ++canon_debug_dup_file=$(readlink -f ${debug_dup_file}) ++test "$canon_debug_id_file" != "$canon_debug_dup_file" \ ++ || echo "debug id and dup same" ++], ++[0], ++[warning: Duplicate build-ids ++warning: Duplicate build-ids ++main id in main package ++main dup id in main package ++debug id in debug package ++debug dup id in debug package ++], ++[]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that hard linked files are handled correctly. ++# Since the hard linked files have duplicate build-ids, ++# it should create "numbered" build-id files. ++# This is simply the hello example with one binary hard linked. ++AT_SETUP([rpmbuild buildid hardlink separate]) ++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="_build_id_links separate" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2ln.spec 2>&1 | grep "^warning: " \ ++ | cut -f1-3 -d' ' ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++hello_file=./usr/local/bin/hello ++ ++# Extract the build-id from the main file ++id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++# separate build-ids split... ++id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" ++test -L "$id_file" && echo "main id in main package" ++id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" ++test -L "$id_dup_file" && echo "main dup id in main package" ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# separate, so debug ids are here ++debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" ++test -L "$debug_id_file" && echo "debug id in debug package" ++debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" ++test -L "$debug_dup_file" && echo "debug dup id in debug package" ++ ++# We don't know which points to which, but we do know they point ++# to different files. ++canon_id_file=$(readlink -f ${id_file}) ++canon_dup_file=$(readlink -f ${id_dup_file}) ++test "$canon_id_file" != "$canon_dup_file" \ ++ || echo "id and dup same" ++ ++canon_debug_id_file=$(readlink -f ${debug_id_file}) ++canon_debug_dup_file=$(readlink -f ${debug_dup_file}) ++test "$canon_debug_id_file" != "$canon_debug_dup_file" \ ++ || echo "debug id and dup same" ++], ++[0], ++[main id in main package ++main dup id in main package ++debug id in debug package ++debug dup id in debug package ++], ++[]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that (copied) files with duplicate build-ids are handled correctly. ++# This should create "numbered" build-id files. ++# This is simply the hello example with one binary copied. ++AT_SETUP([rpmbuild buildid duplicate compat]) ++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 ++ ++# Should create two warnings ++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="_build_id_links compat" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2cp.spec 2>&1 | grep "^warning: " \ ++ | cut -f1-3 -d' ' ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++hello_file=./usr/local/bin/hello ++ ++# Extract the build-id from the main file ++id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++# compat build-ids split... ++id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" ++test -L "$id_file" && echo "main id in main package" ++id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" ++test -L "$id_dup_file" && echo "main dup id in main package" ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# compat, so main (and debug) ids are (also) here ++compat_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" ++test -L "$compat_file" && echo "compat id in debug package" ++compat_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" ++test -L "$compat_dup_file" && echo "compat dup id in debug package" ++ ++debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" ++test -L "$debug_id_file" && echo "debug id in debug package" ++debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" ++test -L "$debug_dup_file" && echo "debug dup id in debug package" ++ ++# We don't know which points to which, but we do know they point ++# to different files. ++canon_id_file=$(readlink -f ${id_file}) ++canon_dup_file=$(readlink -f ${id_dup_file}) ++test "$canon_id_file" != "$canon_dup_file" \ ++ || echo "id and dup same" ++ ++canon_debug_id_file=$(readlink -f ${debug_id_file}) ++canon_debug_dup_file=$(readlink -f ${debug_dup_file}) ++test "$canon_debug_id_file" != "$canon_debug_dup_file" \ ++ || echo "debug id and dup same" ++ ++canon_compat_file=$(readlink -f ${compat_file}) ++canon_compat_dup_file=$(readlink -f ${compat_dup_file}) ++test "$canon_compat_file" != "$canon_compat_dup_file" \ ++ || echo "compat id and dup same" ++], ++[0], ++[warning: Duplicate build-ids ++warning: Duplicate build-ids ++main id in main package ++main dup id in main package ++compat id in debug package ++compat dup id in debug package ++debug id in debug package ++debug dup id in debug package ++], ++[]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that hard linked files are handled correctly. ++# Since the hard linked files have duplicate build-ids, ++# it should create "numbered" build-id files. ++# This is simply the hello example with one binary hard linked. ++AT_SETUP([rpmbuild buildid hardlink compat]) ++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="_build_id_links compat" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2ln.spec 2>&1 | grep "^warning: " \ ++ | cut -f1-3 -d' ' ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++hello_file=./usr/local/bin/hello ++ ++# Extract the build-id from the main file ++id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++# compat build-ids split... ++id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" ++test -L "$id_file" && echo "main id in main package" ++id_dup_file="./usr/lib/.build-id/${id:0:2}/${id:2}.1" ++test -L "$id_dup_file" && echo "main dup id in main package" ++ ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# compat, so main (and debug) ids are (also) here ++compat_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" ++test -L "$compat_file" && echo "compat id in debug package" ++compat_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1" ++test -L "$compat_dup_file" && echo "compat dup id in debug package" ++ ++debug_id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.debug" ++test -L "$debug_id_file" && echo "debug id in debug package" ++debug_dup_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}.1.debug" ++test -L "$debug_dup_file" && echo "debug dup id in debug package" ++ ++# We don't know which points to which, but we do know they point ++# to different files. ++canon_id_file=$(readlink -f ${id_file}) ++canon_dup_file=$(readlink -f ${id_dup_file}) ++test "$canon_id_file" != "$canon_dup_file" \ ++ || echo "id and dup same" ++ ++canon_debug_id_file=$(readlink -f ${debug_id_file}) ++canon_debug_dup_file=$(readlink -f ${debug_dup_file}) ++test "$canon_debug_id_file" != "$canon_debug_dup_file" \ ++ || echo "debug id and dup same" ++ ++canon_compat_file=$(readlink -f ${compat_file}) ++canon_compat_dup_file=$(readlink -f ${compat_dup_file}) ++test "$canon_compat_file" != "$canon_compat_dup_file" \ ++ || echo "compat id and dup same" ++], ++[0], ++[main id in main package ++main dup id in main package ++compat id in debug package ++compat dup id in debug package ++debug id in debug package ++debug dup id in debug package ++], ++[]) ++AT_CLEANUP +\ No newline at end of file +diff --git a/tests/rpmtests.at b/tests/rpmtests.at +index b51266a2d..5495cced1 100644 +--- a/tests/rpmtests.at ++++ b/tests/rpmtests.at +@@ -4,6 +4,7 @@ m4_include([rpmverify.at]) + m4_include([rpmdb.at]) + m4_include([rpmi.at]) + m4_include([rpmbuild.at]) ++m4_include([rpmbuildid.at]) + m4_include([rpmscript.at]) + m4_include([rpmvercmp.at]) + m4_include([rpmdeps.at]) +-- +2.13.2 + diff --git a/0004-Add-option-to-have-unique-debug-file-names-across-ve.patch b/0004-Add-option-to-have-unique-debug-file-names-across-ve.patch deleted file mode 100644 index ae3bcc3..0000000 --- a/0004-Add-option-to-have-unique-debug-file-names-across-ve.patch +++ /dev/null @@ -1,808 +0,0 @@ -From 76e637c715e13fe7f746feb29af4a6fd0de3cbc7 Mon Sep 17 00:00:00 2001 -Message-Id: <76e637c715e13fe7f746feb29af4a6fd0de3cbc7.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Thu, 16 Jun 2016 14:24:22 +0200 -Subject: [PATCH 04/11] Add option to have unique debug file names across - version/release/arch. - -Introduce a new macro _unique_debug_names that when set will pass ---unique-debug-arch "%{_arch}" to find-debuginfo.sh to create debuginfo -files which end in "--..debug" instead of simply ".debug". - -Adds testcases for dwz and buildid with and without unique debug file names. - -Signed-off-by: Mark Wielaard ---- - build/files.c | 19 ++- - macros.debug | 3 + - macros.in | 9 +- - scripts/find-debuginfo.sh | 18 ++- - tests/rpmbuild.at | 168 +++++++++++++++++++----- - tests/rpmbuildid.at | 316 +++++++++++++++++++++++++++++++++++++++++++++- - 6 files changed, 494 insertions(+), 39 deletions(-) - -diff --git a/build/files.c b/build/files.c -index b010483..eb39856 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1790,6 +1790,16 @@ static int generateBuildIDs(FileList fl) - } - } - -+ /* In case we need ALLDEBUG links we might need the vra as -+ tagged onto the .debug file name. */ -+ char *vra = NULL; -+ if (rc == 0 && needDbg && build_id_links == BUILD_IDS_ALLDEBUG) { -+ int unique_debug_names = -+ rpmExpandNumeric("%{?_unique_debug_names}"); -+ if (unique_debug_names == 1) -+ vra = rpmExpand("-%{version}-%{release}.%{_arch}", NULL); -+ } -+ - /* Now add a subdir and symlink for each buildid found. */ - for (i = 0; i < nr_ids; i++) { - /* Don't add anything more when an error occured. But do -@@ -1884,15 +1894,17 @@ static int generateBuildIDs(FileList fl) - int pathlen = strlen(paths[i]); - int debuglen = strlen(".debug"); - int prefixlen = strlen("/usr/lib/debug"); -- if (pathlen > prefixlen -- && strcmp (paths[i] + pathlen - debuglen, -+ int vralen = vra == NULL ? 0 : strlen(vra); -+ if (pathlen > prefixlen + debuglen + vralen -+ && strcmp ((paths[i] + pathlen - debuglen), - ".debug") == 0) { - free(linkpath); - free(targetpath); - char *targetstr = xstrdup (paths[i] - + prefixlen); - int targetlen = pathlen - prefixlen; -- targetstr[targetlen - debuglen] = '\0'; -+ int targetend = targetlen - debuglen - vralen; -+ targetstr[targetend] = '\0'; - rasprintf(&linkpath, "%s/%s", - buildidsubdir, &ids[i][2]); - rasprintf(&targetpath, "../../../../..%s", -@@ -1911,6 +1923,7 @@ static int generateBuildIDs(FileList fl) - free(paths[i]); - free(ids[i]); - } -+ free(vra); - free(paths); - free(ids); - } -diff --git a/macros.debug b/macros.debug -index d273c08..ee0cc9e 100644 ---- a/macros.debug -+++ b/macros.debug -@@ -1,4 +1,7 @@ - # macros to include to generate debuginfo -+# Note don't define/enable a feature here if it is already the default in -+# macros.in. Otherwise it cannot simply be --undefined on the command line -+# in the tests (it needs to be undefined multiple times then). - - %_enable_debug_packages 1 - %_include_minidebuginfo 1 -diff --git a/macros.in b/macros.in -index c845f58..68bf391 100644 ---- a/macros.in -+++ b/macros.in -@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ - %{nil} - - # Template for debug information sub-package. -@@ -488,6 +488,13 @@ package or when debugging this package.\ - # onto debugedit --build-id-seed to be used to prime the build-id note hash. - %_unique_build_ids 1 - -+# Whether .debug files should be made unique between package version, -+# release and architecture. If set to 1 this will pass -+# --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create -+# debuginfo files which end in --..debug -+# Requires _unique_build_ids. -+%_unique_debug_names 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 8e60813..3653c48 100644 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -64,6 +64,9 @@ dwz_max_die_limit= - # Version and release of the spec. Given by --ver-rel - ver_rel= - -+# Arch given by --unique-debug-arch -+unique_debug_arch= -+ - BUILDDIR=. - out=debugfiles.list - nout=0 -@@ -87,6 +90,10 @@ while [ $# -gt 0 ]; do - ver_rel=$2 - shift - ;; -+ --unique-debug-arch) -+ unique_debug_arch=$2 -+ shift -+ ;; - -g) - strip_g=true - ;; -@@ -125,6 +132,11 @@ while [ $# -gt 0 ]; do - shift - done - -+if test -z "$ver_rel" -a -n "$unique_debug_arch"; then -+ echo >&2 "*** ERROR: --unique-debug-arch (${unique_debug_arch}) needs --ver-rel (${ver_rel})" -+ exit 2 -+fi -+ - i=0 - while ((i < nout)); do - outs[$i]="$BUILDDIR/${outs[$i]}" -@@ -232,7 +244,11 @@ debug_link() - get_debugfn() - { - dn=$(dirname "${1#$RPM_BUILD_ROOT}") -- bn=$(basename "$1" .debug).debug -+ if test -n "${unique_debug_arch}"; then -+ bn=$(basename "$1" .debug)-${ver_rel}.${unique_debug_arch}.debug -+ else -+ bn=$(basename "$1" .debug).debug -+ fi - - debugdn=${debugdir}${dn} - debugfn=${debugdn}/${bn} -diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at -index a312324..0a2c01e 100644 ---- a/tests/rpmbuild.at -+++ b/tests/rpmbuild.at -@@ -386,8 +386,9 @@ 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. -+# Test the case without unique debug file names. - AT_SETUP([rpmbuild debuginfo dwz]) --AT_KEYWORDS([build] [debuginfo]) -+AT_KEYWORDS([build] [debuginfo] [dwz]) - AT_CHECK([ - rm -rf ${TOPDIR} - AS_MKDIR_P(${TOPDIR}/SOURCES) -@@ -397,63 +398,170 @@ cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/he - 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_debug_names" \ - -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 -+ -+hello_file_debug=./usr/lib/debug/usr/local/bin/hello.debug -+hello2_file_debug=./usr/lib/debug/usr/local/bin/hello2.debug -+hello_multi_file=./usr/lib/debug/.dwz/hello2-1.0-1.* -+test -f $hello_file_debug || echo "no hello debug file: $hello_file_debug" -+test -f $hello2_file_debug || echo "no hello2 debug file: $hello2_file_debug" -+test -f $hello_multi_file || echo "no dwz multi file: $hello_multi_file" - - # 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 -+hello_file=./usr/local/bin/hello -+hello2_file=./usr/local/bin/hello2 -+test -f $hello_file || echo "no hello file: $hello_file" -+test -f $hello2_file || echo "no hello2 file: $hello2_file" -+ -+id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" -+test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" -+ -+# 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 $hello_file) -+canonid1debug=$(readlink -f ${id1file}.debug) -+canondebug1=$(readlink -f $hello_file_debug) -+ -+test "$canonid1file" = "$canonfile1" \ -+ || echo "canonid1file: $canonid1file != $canonfile1" -+test "$canonid1debug" = "$canondebug1" \ -+ || echo "canonid1debug: $canonid1debug != $canondebug1" -+ -+id2file="./usr/lib/debug/.build-id/${id2:0:2}/${id2:2}" -+canonid2file=$(readlink -f ${id2file}) -+canonfile2=$(readlink -f $hello2_file) -+canonid2debug=$(readlink -f ${id2file}.debug) -+canondebug2=$(readlink -f $hello2_file_debug) -+ -+test "$canonid2file" = "$canonfile2" \ -+ || echo "canonid2: $canonid2file != $canonfile2" -+test "$canonid2debug" = "$canondebug2" \ -+ || echo "canonid2debug: $canonid2debug" != "$canondebug2" -+ -+# 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 $hello_file_debug \ -+ | grep '[ 0]' | cut -c13-) -+multiref2=$(readelf --string-dump=.gnu_debugaltlink $hello2_file_debug \ -+ | grep '[ 0]' | cut -c13-) -+ -+test "$multiref1" = "$multiref2" || echo "multiref: $multiref1 != $multiref2" -+ -+canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1) -+canonmultifile=$(readlink -f $hello_multi_file) -+ -+test "$canonmultiref" = "$canonmultifile" \ -+ || echo "canonmultiref: $canonmultiref" != "$canonmultifile" -+], -+[0], -+[], -+[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. -+# Test with unique debug file names. -+AT_SETUP([rpmbuild debuginfo dwz unique debug names]) -+AT_KEYWORDS([build] [debuginfo] [dwz]) -+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 \ -+ --define "_unique_debug_names 1" \ -+ -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 -+ -+hello_file_debug=./usr/lib/debug/usr/local/bin/hello-*.debug -+hello2_file_debug=./usr/lib/debug/usr/local/bin/hello2-*.debug -+hello_multi_file=./usr/lib/debug/.dwz/hello2-1.0-1.* -+test -f $hello_file_debug || echo "no hello debug file: $hello_file_debug" -+test -f $hello2_file_debug || echo "no hello2 debug file: $hello2_file_debug" -+test -f $hello_multi_file || echo "no dwz multi file: $hello_multi_file" -+ -+# 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 -+hello_file=./usr/local/bin/hello -+hello2_file=./usr/local/bin/hello2 -+test -f $hello_file || echo "no hello file: $hello_file" -+test -f $hello2_file || echo "no hello2 file: $hello2_file" -+ -+id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" -+test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" - - # 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) -+canonfile1=$(readlink -f $hello_file) - canonid1debug=$(readlink -f ${id1file}.debug) --canondebug1=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug) -+canondebug1=$(readlink -f $hello_file_debug) - --test "$canonid1file" = "$canonfile1" || exit 1 --test "$canonid1debug" = "$canondebug1" || exit 1 -+test "$canonid1file" = "$canonfile1" \ -+ || echo "canonid1file: $canonid1file != $canonfile1" -+test "$canonid1debug" = "$canondebug1" \ -+ || echo "canonid1debug: $canonid1debug != $canondebug1" - - 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) -+canonid2file=$(readlink -f ${id2file}) -+canonfile2=$(readlink -f $hello2_file) -+canonid2debug=$(readlink -f ${id2file}.debug) -+canondebug2=$(readlink -f $hello2_file_debug) - --test "$canonid2file" = "$canonfile2" || exit 1 --test "$canonid2debug" = "$canondebug2" || exit 1 -+test "$canonid2file" = "$canonfile2" \ -+ || echo "canonid2: $canonid2file != $canonfile2" -+test "$canonid2debug" = "$canondebug2" \ -+ || echo "canonid2debug: $canonid2debug" != "$canondebug2" - - # 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-) -+multiref1=$(readelf --string-dump=.gnu_debugaltlink $hello_file_debug \ -+ | grep '[ 0]' | cut -c13-) -+multiref2=$(readelf --string-dump=.gnu_debugaltlink $hello2_file_debug \ -+ | grep '[ 0]' | cut -c13-) - --test "$multiref1" = "$multiref2" || exit 1 -+test "$multiref1" = "$multiref2" || echo "multiref: $multiref1 != $multiref2" - - canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1) --canonmultifile=$(readlink -f ./usr/lib/debug/.dwz/hello2-1.0-1.*) -+canonmultifile=$(readlink -f $hello_multi_file) - --test "$canonmultiref" = "$canonmultifile" || exit 1 -+test "$canonmultiref" = "$canonmultifile" \ -+ || echo "canonmultiref: $canonmultiref" != "$canonmultifile" - ], - [0], - [], -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -index 1da6302..ede1181 100644 ---- a/tests/rpmbuildid.at -+++ b/tests/rpmbuildid.at -@@ -54,7 +54,8 @@ hello debuginfo build-id files: 0 - AT_CLEANUP - - # ------------------------------ --# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks -+# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks. -+# Without unique debug file names. - AT_SETUP([rpmbuild buildid alldebug]) - AT_KEYWORDS([build] [debuginfo] [buildid]) - AT_CHECK([ -@@ -69,6 +70,7 @@ run rpmbuild \ - --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="_build_id_links alldebug" \ -+ --undefine "_unique_debug_names" \ - --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec - - # There should be zero build-id files in the main package -@@ -114,7 +116,100 @@ test "$canon_main_file" = "$canon_main_id_file" \ - - # And check the same for the debug file. - debug_file=./usr/lib/debug/usr/local/bin/hello.debug --test -f "${debug_file}" || echo "No debug file ${debug_file}" -+test -f ${debug_file} || echo "No debug file ${debug_file}" -+ -+# Extract the build-id from the .debug file -+id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test ${id_main} = ${id_debug} || echo "unequal main and debug id" -+ -+id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" -+test -L "$id_debug_file" || echo "No build-id file $id_debug_file" -+ -+canon_debug_file=$(readlink -f ${debug_file}) -+ -+test -f "$canon_debug_file" \ -+ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" -+ -+canon_debug_id_file=$(readlink -f ${id_debug_file}) -+ -+test -f "$canon_debug_id_file" \ -+ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" -+ -+test "$canon_debug_file" = "$canon_debug_id_file" \ -+ || echo "debug and build-id not linked" -+], -+[0], -+[hello build-id files: 0 -+hello debuginfo build-id files: 3 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks. -+# With unique debug file names. -+AT_SETUP([rpmbuild buildid alldebug unique debug names]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links alldebug" \ -+ --define="_unique_debug_names 1" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be zero build-id files in the main package -+# Main and debug should be in the debuginfo package, -+# plus the .build-id/xx subdir, 3 in total. -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+# Extract the both packages to check the build-id files link to the -+# main and .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -+ | cpio -diu -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu -+ -+# Check there is a build-id symlink for the main file. -+main_file=./usr/local/bin/hello -+test -f "${main_file}" || echo "No main file ${main_file}" -+ -+# Extract the build-id from the main file -+id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_main_file" || echo "No build-id file $id_main_file" -+ -+canon_main_file=$(readlink -f ${main_file}) -+ -+test -f "$canon_main_file" \ -+ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" -+ -+canon_main_id_file=$(readlink -f ${id_main_file}) -+ -+test -f "$canon_main_id_file" \ -+ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" -+ -+test "$canon_main_file" = "$canon_main_id_file" \ -+ || echo "main and build-id file not linked" -+ -+# And check the same for the debug file. -+debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug -+test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file - id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -@@ -146,6 +241,7 @@ AT_CLEANUP - - # ------------------------------ - # Check if rpmbuild "separate" generates main and debuginfo buildid symlinks -+# Without unique debug file names - AT_SETUP([rpmbuild buildid separate]) - AT_KEYWORDS([build] [debuginfo] [buildid]) - AT_CHECK([ -@@ -160,6 +256,7 @@ run rpmbuild \ - --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="_build_id_links separate" \ -+ --undefine "_unique_debug_names" \ - --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec - - # There should be one build-id files in the main and debuginfo package -@@ -204,7 +301,99 @@ test "$canon_main_file" = "$canon_main_id_file" \ - - # And check the same for the debug file. - debug_file=./usr/lib/debug/usr/local/bin/hello.debug --test -f "${debug_file}" || echo "No debug file ${debug_file}" -+test -f ${debug_file} || echo "No debug file ${debug_file}" -+ -+# Extract the build-id from the .debug file -+id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test ${id_main} = ${id_debug} || echo "unequal main and debug id" -+ -+id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" -+test -L "$id_debug_file" || echo "No build-id file $id_debug_file" -+ -+canon_debug_file=$(readlink -f ${debug_file}) -+ -+test -f "$canon_debug_file" \ -+ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" -+ -+canon_debug_id_file=$(readlink -f ${id_debug_file}) -+ -+test -f "$canon_debug_id_file" \ -+ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" -+ -+test "$canon_debug_file" = "$canon_debug_id_file" \ -+ || echo "debug and build-id not linked" -+], -+[0], -+[hello build-id files: 2 -+hello debuginfo build-id files: 2 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check if rpmbuild "separate" generates main and debuginfo buildid symlinks -+# With unique debug file names -+AT_SETUP([rpmbuild buildid separate unique debug names]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links separate" \ -+ --define="_unique_debug_names 1" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be one build-id files in the main and debuginfo package -+# plus the .build-id/xx subdir, 2 in total. -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+# Extract the both packages to check the build-id files link to the -+# main and .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -+ | cpio -diu -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu -+ -+# Check there is a build-id symlink for the main file. -+main_file=./usr/local/bin/hello -+test -f "${main_file}" || echo "No main file ${main_file}" -+ -+# Extract the build-id from the main file -+id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_main_file" || echo "No build-id file $id_main_file" -+ -+canon_main_file=$(readlink -f ${main_file}) -+ -+test -f "$canon_main_file" \ -+ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" -+ -+canon_main_id_file=$(readlink -f ${id_main_file}) -+ -+test -f "$canon_main_id_file" \ -+ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" -+ -+test "$canon_main_file" = "$canon_main_id_file" \ -+ || echo "main and build-id file not linked" -+ -+# And check the same for the debug file. -+debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug -+test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file - id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -@@ -236,6 +425,7 @@ AT_CLEANUP - - # ------------------------------ - # Check if rpmbuild "compat" generates main and debuginfo buildid symlinks -+# Without unique debug file names - AT_SETUP([rpmbuild buildid compat]) - AT_KEYWORDS([build] [debuginfo] [buildid]) - AT_CHECK([ -@@ -250,6 +440,7 @@ run rpmbuild \ - --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="_build_id_links compat" \ -+ --undefine "_unique_debug_names" \ - --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec - - # There should be one build-id files in the main and debuginfo package. -@@ -295,7 +486,112 @@ test "$canon_main_file" = "$canon_main_id_file" \ - - # And check the same for the debug file. - debug_file=./usr/lib/debug/usr/local/bin/hello.debug --test -f "${debug_file}" || echo "No debug file ${debug_file}" -+test -f ${debug_file} || echo "No debug file ${debug_file}" -+ -+# Extract the build-id from the .debug file -+id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+test ${id_main} = ${id_debug} || echo "unequal main and debug id" -+ -+id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" -+test -L "$id_debug_file" || echo "No build-id file $id_debug_file" -+ -+canon_debug_file=$(readlink -f ${debug_file}) -+ -+test -f "$canon_debug_file" \ -+ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" -+ -+canon_debug_id_file=$(readlink -f ${id_debug_file}) -+ -+test -f "$canon_debug_id_file" \ -+ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" -+ -+test "$canon_debug_file" = "$canon_debug_id_file" \ -+ || echo "debug and build-id not linked" -+ -+# The compat link should also point to the same (indirectly). -+id_compat_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_compat_file" || echo "No build-id compat file $id_compat_file" -+ -+canon_compat_file=$(readlink -f ${id_compat_file}) -+ -+test -f "$canon_compat_file" \ -+ || echo "Cannot resolve compat file ${id_compat_file} -> ${canon_compat_file}" -+ -+test "$canon_compat_file" = "$canon_main_file" \ -+ || echo "compat and build-id not linked" -+], -+[0], -+[hello build-id files: 2 -+hello debuginfo build-id files: 3 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check if rpmbuild "compat" generates main and debuginfo buildid symlinks -+# With unique debug file names -+AT_SETUP([rpmbuild buildid compat unique debug names]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links compat" \ -+ --define="_unique_debug_names 1" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec -+ -+# There should be one build-id files in the main and debuginfo package. -+# the debuginfo package has one extra main build-id compat symlink -+# plus the .build-id/xx subdir, 2 in total in main, 3 in total in debug -+echo -n "hello build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+echo -n "hello debuginfo build-id files: " -+run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | grep /.build-id/ | wc --lines -+ -+# Extract the both packages to check the build-id files link to the -+# main and .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -+ | cpio -diu -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu -+ -+# Check there is a build-id symlink for the main file. -+main_file=./usr/local/bin/hello -+test -f "${main_file}" || echo "No main file ${main_file}" -+ -+# Extract the build-id from the main file -+id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+ -+id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" -+test -L "$id_main_file" || echo "No build-id file $id_main_file" -+ -+canon_main_file=$(readlink -f ${main_file}) -+ -+test -f "$canon_main_file" \ -+ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" -+ -+canon_main_id_file=$(readlink -f ${id_main_file}) -+ -+test -f "$canon_main_id_file" \ -+ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" -+ -+test "$canon_main_file" = "$canon_main_id_file" \ -+ || echo "main and build-id file not linked" -+ -+# And check the same for the debug file. -+debug_file=./usr/lib/debug/usr/local/bin/hello-*debug -+test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file - id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -@@ -784,8 +1080,12 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file -+test -f $hello_file || echo "No $hello_file" - id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') - -+# Make sure we generate a new one -+rm $hello_file -+ - # 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 \ -@@ -797,6 +1097,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ - | cpio -diu --quiet - - # Extract the build-id from the main file -+test -f $hello_file || echo "No $hello_file" - id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') - - if test "$id1" == "$id2"; then echo "equal $id1"; else echo "unequal"; fi -@@ -823,6 +1124,7 @@ 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" \ -+ --undefine="_unique_debug_names" \ - -ba "${abs_srcdir}"/data/SPECS/hello.spec - - rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -@@ -831,19 +1133,25 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file -+test -f $hello_file || echo "No $hello_file" - id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') - -+# Make sure we generate a new one -+rm $hello_file -+ - # 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" \ -+ --undefine="_unique_debug_names" \ - -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 -+test -f $hello_file || echo "No $hello_file" - id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') - - if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi --- -2.9.3 - diff --git a/0004-Re-enable-rich-dependecies-for-build-requires-and-co.patch b/0004-Re-enable-rich-dependecies-for-build-requires-and-co.patch deleted file mode 100644 index 9e88f86..0000000 --- a/0004-Re-enable-rich-dependecies-for-build-requires-and-co.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 96772ee932bbfb3f340589fa5cbbe3ec99125cfd Mon Sep 17 00:00:00 2001 -From: Florian Festi -Date: Thu, 9 Mar 2017 14:02:10 +0100 -Subject: [PATCH 4/6] Re-enable rich dependecies for build requires and - conflicts - -(cherry picked from commit cb3dc0b43bd9a119196a527504d03d57d0785092) ---- - build/parseReqs.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/build/parseReqs.c b/build/parseReqs.c -index 6c2aead4e..4d500c1df 100644 ---- a/build/parseReqs.c -+++ b/build/parseReqs.c -@@ -174,9 +174,11 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - case RPMTAG_BUILDREQUIRES: - nametag = RPMTAG_REQUIRENAME; - tagflags |= RPMSENSE_ANY; -+ allow_richdeps = 1; - break; - case RPMTAG_BUILDCONFLICTS: - nametag = RPMTAG_CONFLICTNAME; -+ allow_richdeps = 1; - break; - case RPMTAG_FILETRIGGERIN: - nametag = RPMTAG_FILETRIGGERNAME; --- -2.13.1 - diff --git a/0005-Fix-behavior-when-_build_id_links-is-undefined.patch b/0005-Fix-behavior-when-_build_id_links-is-undefined.patch deleted file mode 100644 index 2eeee49..0000000 --- a/0005-Fix-behavior-when-_build_id_links-is-undefined.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 1a8a0364fd049f3b4432633160fba12aa137f88d Mon Sep 17 00:00:00 2001 -Message-Id: <1a8a0364fd049f3b4432633160fba12aa137f88d.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Panu Matilainen -Date: Mon, 3 Oct 2016 12:36:46 +0300 -Subject: [PATCH 05/11] Fix behavior when %_build_id_links is undefined - -Commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 tries to behave sanely -and use compat setting when %_build_id_links is undefined, but -rpmExpand() never returns NULL so the original check is incorrect. -Check for empty string instead. ---- - build/files.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/build/files.c b/build/files.c -index eb39856..6215bf8 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1648,7 +1648,7 @@ static int generateBuildIDs(FileList fl) - /* How are we supposed to create the build-id links? */ - char *build_id_links_macro = rpmExpand("%{?_build_id_links}", NULL); - int build_id_links; -- if (build_id_links_macro == NULL) { -+ if (*build_id_links_macro == '\0') { - rpmlog(RPMLOG_WARNING, - _("_build_id_links macro not set, assuming 'compat'\n")); - build_id_links = BUILD_IDS_COMPAT; --- -2.9.3 - diff --git a/0005-Make-it-possible-to-have-unique-build-ids-across-bui.patch b/0005-Make-it-possible-to-have-unique-build-ids-across-bui.patch new file mode 100644 index 0000000..723fd96 --- /dev/null +++ b/0005-Make-it-possible-to-have-unique-build-ids-across-bui.patch @@ -0,0 +1,349 @@ +From 3edae790572203f07a28448fedfda82d0629f4fb Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 14 Jun 2016 17:07:13 +0200 +Subject: [PATCH 05/49] 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 +(cherry picked from commit 5ef1166ad96e3545784fa5420a49e1b2cd481e8e) +--- + 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 e43d62b0a..dcd09612c 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,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. +@@ -476,6 +476,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 c9e2293de..2cb9570ba 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 + ;; +@@ -249,8 +263,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 ++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 ++- Update release for unique build-id generation tests. ++ ++* Tue Oct 20 1998 Jeff Johnson ++- 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 , 2002 + Based on code by Jakub Jelinek , 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.13.2 + diff --git a/0005-add-support-for-rich-dependencies-from-dependency-ge.patch b/0005-add-support-for-rich-dependencies-from-dependency-ge.patch deleted file mode 100644 index fe4b513..0000000 --- a/0005-add-support-for-rich-dependencies-from-dependency-ge.patch +++ /dev/null @@ -1,276 +0,0 @@ -From 9ff717b63e94eb6a330050036506f8b78bf1401f Mon Sep 17 00:00:00 2001 -From: Igor Gnatenko -Date: Sat, 25 Feb 2017 12:28:16 +0100 -Subject: [PATCH 5/6] add support for rich dependencies from dependency - generators - -Mostly achieved by replacing custom parser with the parseRCPOT(). - -Closes: https://github.com/rpm-software-management/rpm/issues/167 -Signed-off-by: Igor Gnatenko -(cherry picked from commit 8f509d669b9ae79c86dd510c5a4bc5109f60d733) ---- - build/parsePreamble.c | 4 +-- - build/parseReqs.c | 9 +++-- - build/parseScript.c | 2 +- - build/reqprov.c | 8 +++++ - build/rpmbuild_internal.h | 12 ++++++- - build/rpmfc.c | 90 ++++++++++++++--------------------------------- - 6 files changed, 54 insertions(+), 71 deletions(-) - -diff --git a/build/parsePreamble.c b/build/parsePreamble.c -index bc639e86c..6b3705598 100644 ---- a/build/parsePreamble.c -+++ b/build/parsePreamble.c -@@ -866,13 +866,13 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, - case RPMTAG_CONFLICTNAME: - case RPMTAG_OBSOLETENAME: - case RPMTAG_PROVIDENAME: -- if (parseRCPOT(spec, pkg, field, tag, 0, tagflags)) -+ if (parseRCPOT(spec, pkg, field, tag, 0, tagflags, addReqProvPkg, NULL)) - goto exit; - break; - case RPMTAG_BUILDPREREQ: - case RPMTAG_BUILDREQUIRES: - case RPMTAG_BUILDCONFLICTS: -- if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags)) -+ if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags, addReqProvPkg, NULL)) - goto exit; - break; - case RPMTAG_EXCLUDEARCH: -diff --git a/build/parseReqs.c b/build/parseReqs.c -index 4d500c1df..554ff49a5 100644 ---- a/build/parseReqs.c -+++ b/build/parseReqs.c -@@ -121,7 +121,7 @@ static rpmRC parseRCPOTRichCB(void *cbdata, rpmrichParseType type, - } - - rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, -- int index, rpmsenseFlags tagflags) -+ int index, rpmsenseFlags tagflags, addReqProvFunction cb, void *cbdata) - { - const char *r, *re, *v, *ve; - char *emsg = NULL; -@@ -131,6 +131,9 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - rpmRC rc = RPMRC_FAIL; /* assume failure */ - int allow_richdeps = 0; - -+ if (!cbdata) -+ cbdata = pkg; -+ - switch (tagN) { - default: - case RPMTAG_REQUIRENAME: -@@ -225,7 +228,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - freeStringBuf(data.sb); - goto exit; - } -- if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags, index)) { -+ if (cb && cb(cbdata, nametag, getStringBuf(data.sb), NULL, Flags, index) != RPMRC_OK) { - rasprintf(&emsg, _("invalid dependency")); - freeStringBuf(data.sb); - goto exit; -@@ -300,7 +303,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, - goto exit; - } - -- if (addReqProv(pkg, nametag, N, EVR, Flags, index)) { -+ if (cb && cb(cbdata, nametag, N, EVR, Flags, index) != RPMRC_OK) { - rasprintf(&emsg, _("invalid dependency")); - goto exit; - } -diff --git a/build/parseScript.c b/build/parseScript.c -index 64fd89693..849e40244 100644 ---- a/build/parseScript.c -+++ b/build/parseScript.c -@@ -398,7 +398,7 @@ int parseScript(rpmSpec spec, int parsePart) - priority); - - /* Generate the trigger tags */ -- if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)) -+ if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags, addReqProvPkg, NULL)) - goto exit; - } else { - struct rpmtd_s td; -diff --git a/build/reqprov.c b/build/reqprov.c -index 7422db65f..5fa0a1c6b 100644 ---- a/build/reqprov.c -+++ b/build/reqprov.c -@@ -34,6 +34,14 @@ int addReqProv(Package pkg, rpmTagVal tagN, - return 0; - } - -+rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN, -+ const char * N, const char *EVR, rpmsenseFlags Flags, -+ int index) -+{ -+ Package pkg = cbdata; -+ return addReqProv(pkg, tagN, N, EVR, Flags, index) ? RPMRC_FAIL : RPMRC_OK; -+} -+ - int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEVR) - { - char *reqname = NULL; -diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h -index 7ec05b9c9..1c3332faf 100644 ---- a/build/rpmbuild_internal.h -+++ b/build/rpmbuild_internal.h -@@ -283,6 +283,10 @@ int parseScript(rpmSpec spec, int parsePart); - RPM_GNUC_INTERNAL - rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist); - -+typedef rpmRC (*addReqProvFunction) (void *cbdata, rpmTagVal tagN, -+ const char * N, const char * EVR, rpmsenseFlags Flags, -+ int index); -+ - /** \ingroup rpmbuild - * Parse dependency relations from spec file and/or autogenerated output buffer. - * @param spec spec file control structure -@@ -291,11 +295,13 @@ rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist); - * @param tagN tag, identifies type of dependency - * @param index (0 always) - * @param tagflags dependency flags already known from context -+ * @param cb Callback for adding dependency (nullable) -+ * @param cbdata Callback data (@pkg if NULL) - * @return RPMRC_OK on success, RPMRC_FAIL on failure - */ - RPM_GNUC_INTERNAL - rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char * field, rpmTagVal tagN, -- int index, rpmsenseFlags tagflags); -+ int index, rpmsenseFlags tagflags, addReqProvFunction cb, void *cbdata); - - /** \ingroup rpmbuild - * Evaluate boolean expression. -@@ -440,6 +446,10 @@ int addReqProv(Package pkg, rpmTagVal tagN, - const char * N, const char * EVR, rpmsenseFlags Flags, - uint32_t index); - -+RPM_GNUC_INTERNAL -+rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN, -+ const char * N, const char * EVR, rpmsenseFlags Flags, -+ int index); - - /** \ingroup rpmbuild - * Add self-provides to package. -diff --git a/build/rpmfc.c b/build/rpmfc.c -index 921814ad1..7fa8227d0 100644 ---- a/build/rpmfc.c -+++ b/build/rpmfc.c -@@ -447,44 +447,27 @@ static ARGV_t runCmd(const char *nsdep, const char *depname, - return output; - } - --static const char *parseDep(char **depav, int depac, -- const char **N, const char **EVR, rpmsenseFlags *Flags) -+struct addReqProvDataFc { -+ rpmfc fc; -+ const char *namespace; -+ regex_t *exclude; -+}; -+ -+static rpmRC addReqProvFc(void *cbdata, rpmTagVal tagN, -+ const char * N, const char * EVR, rpmsenseFlags Flags, -+ int index) - { -- const char *err = NULL; -- -- switch (depac) { -- case 1: /* only a name */ -- *N = depav[0]; -- *EVR = ""; -- break; -- case 3: /* name, range and version */ -- for (const char *s = depav[1]; *s; s++) { -- switch(*s) { -- default: -- err = _("bad operator"); -- break; -- case '=': -- *Flags |= RPMSENSE_EQUAL; -- break; -- case '<': -- *Flags |= RPMSENSE_LESS; -- break; -- case '>': -- *Flags |= RPMSENSE_GREATER; -- break; -- } -- } -- if (!err) { -- *N = depav[0]; -- *EVR = depav[2]; -- } -- break; -- default: -- err = _("bad format"); -- break; -- } -+ struct addReqProvDataFc *data = cbdata; -+ rpmfc fc = data->fc; -+ const char *namespace = data->namespace; -+ regex_t *exclude = data->exclude; -+ -+ rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags); -+ /* Add to package and file dependencies unless filtered */ -+ if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) -+ rpmfcAddFileDep(&fc->fileDeps, ds, index); - -- return err; -+ return RPMRC_OK; - } - - /** -@@ -522,35 +505,14 @@ static int rpmfcHelper(rpmfc fc, int ix, - namespace = rpmfcAttrMacro(nsdep, NULL, "namespace"); - exclude = rpmfcAttrReg(depname, NULL, "exclude"); - -+ struct addReqProvDataFc data; -+ data.fc = fc; -+ data.namespace = namespace; -+ data.exclude = exclude; -+ - for (int i = 0; i < pac; i++) { -- char ** depav = NULL; -- int xx, depac = 0; -- const char *N = NULL; -- const char *EVR = NULL; -- const char *err = NULL; -- rpmsenseFlags Flags = dsContext; -- -- if ((xx = poptParseArgvString(pav[i], &depac, (const char ***)&depav))) -- err = poptStrerror(xx); -- -- if (!err) -- err = parseDep(depav, depac, &N, &EVR, &Flags); -- -- if (!err) { -- rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags); -- -- /* Add to package and file dependencies unless filtered */ -- if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) { -- //rpmdsMerge(packageDependencies(fc->pkg, tagN), ds); -- rpmfcAddFileDep(&fc->fileDeps, ds, ix); -- } -- } else { -- rpmlog(RPMLOG_ERR, _("invalid dependency (%s): %s\n"), -- err, pav[i]); -+ if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, 0, dsContext, addReqProvFc, &data)) - rc++; -- } -- -- free(depav); - } - - argvFree(pav); -@@ -1297,7 +1259,7 @@ static rpmRC rpmfcApplyExternal(rpmfc fc) - } - - /* Parse dependencies into header */ -- rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags); -+ rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags, addReqProvPkg, NULL); - freeStringBuf(sb_stdout); - - if (rc) { --- -2.13.1 - diff --git a/0006-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch b/0006-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch deleted file mode 100644 index c14ede5..0000000 --- a/0006-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 53c9e8d00983b0d99caefc0ef94a18184c0ba85c Mon Sep 17 00:00:00 2001 -Message-Id: <53c9e8d00983b0d99caefc0ef94a18184c0ba85c.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Panu Matilainen -Date: Wed, 9 Nov 2016 09:16:48 +0200 -Subject: [PATCH 06/11] Fix debuginfo etc when subpackages have different - versions (RhBug:1051407) - -Rpm has always been a bit dazed and confused when it comes to specs -with sub-packages having different version etc from the main package. -Many things work fine in that case .. except .. when they dont. Debuginfo -picking up wrong versions (RhBug:1051407) is just one example, there -are countless more in bugzilla wrt buildroot paths and whatnot. -The simple and sane solution would be not piling on them macros -from sub-packages, but that would surely break somebodys precious -spec tricks. - -The ugly but brutally simple and compatible solution to this all is to -create separate set of macros when on the main package, this lets users -in and out of rpm pick which one (latest or main) they want. To hopefully -avoid stomping on anybodys toes, use uppercasing for the macro name (other -variants like %pkg_release are awfully commonly used). Pile 'em on, yay! ---- - build/files.c | 2 +- - build/parsePreamble.c | 11 ++++++++++- - macros.in | 18 +++++++++--------- - 3 files changed, 20 insertions(+), 11 deletions(-) - -diff --git a/build/files.c b/build/files.c -index 6215bf8..2ede463 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1797,7 +1797,7 @@ static int generateBuildIDs(FileList fl) - int unique_debug_names = - rpmExpandNumeric("%{?_unique_debug_names}"); - if (unique_debug_names == 1) -- vra = rpmExpand("-%{version}-%{release}.%{_arch}", NULL); -+ vra = rpmExpand("-%{VERSION}-%{RELEASE}.%{_arch}", NULL); - } - - /* Now add a subdir and symlink for each buildid found. */ -diff --git a/build/parsePreamble.c b/build/parsePreamble.c -index 933f734..6be4403 100644 ---- a/build/parsePreamble.c -+++ b/build/parsePreamble.c -@@ -909,8 +909,17 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, - goto exit; - } - -- if (macro) -+ if (macro) { - addMacro(spec->macros, macro, NULL, field, RMIL_SPEC); -+ /* Add a separate uppercase macro for tags from the main package */ -+ if (pkg == spec->packages) { -+ char *m = xstrdup(macro); -+ for (char *p = m; *p; ++p) -+ *p = rtoupper(*p); -+ addMacro(spec->macros, m, NULL, field, RMIL_SPEC); -+ free(m); -+ } -+ } - rc = RPMRC_OK; - exit: - return rc; -diff --git a/macros.in b/macros.in -index 68bf391..4d90282 100644 ---- a/macros.in -+++ b/macros.in -@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ - %{nil} - - # Template for debug information sub-package. -@@ -232,7 +232,7 @@ package or when debugging this package.\ - %_buildrootdir %{_topdir}/BUILDROOT - - # Build root path, where %install installs the package during build. --%buildroot %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch} -+%buildroot %{_buildrootdir}/%{NAME}-%{VERSION}-%{RELEASE}.%{_arch} - - # Directory where temporaray files can be created. - %_tmppath %{_var}/tmp -@@ -484,7 +484,7 @@ package or when debugging this package.\ - - # 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 -+# --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 - -@@ -705,9 +705,9 @@ package or when debugging this package.\ - export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\ - RPM_DOC_DIR=\"%{_docdir}\"\ - export RPM_DOC_DIR\ -- RPM_PACKAGE_NAME=\"%{name}\"\ -- RPM_PACKAGE_VERSION=\"%{version}\"\ -- RPM_PACKAGE_RELEASE=\"%{release}\"\ -+ RPM_PACKAGE_NAME=\"%{NAME}\"\ -+ RPM_PACKAGE_VERSION=\"%{VERSION}\"\ -+ RPM_PACKAGE_RELEASE=\"%{RELEASE}\"\ - export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\ - LANG=C\ - export LANG\ -@@ -1146,7 +1146,7 @@ done \ - %__scm_setup_hg(q)\ - %{__hg} init %{-q} .\ - %{__hg} add %{-q} .\ --%{__hg} commit %{-q} --user "%{__scm_author}" -m "%{name}-%{version} base" -+%{__hg} commit %{-q} --user "%{__scm_author}" -m "%{NAME}-%{VERSION} base" - - %__scm_apply_hg(qp:m:)\ - %{__hg} import - %{-p:-p%{-p*}} %{-q} -m %{-m*} --user "%{__scm_author}" -@@ -1158,7 +1158,7 @@ done \ - %{__git} config user.email "%{__scm_usermail}"\ - %{__git} add .\ - %{__git} commit %{-q} -a\\\ -- --author "%{__scm_author}" -m "%{name}-%{version} base" -+ --author "%{__scm_author}" -m "%{NAME}-%{VERSION} base" - - %__scm_apply_git(qp:m:)\ - %{__git} apply --index %{-p:-p%{-p*}} -\ -@@ -1181,7 +1181,7 @@ done \ - %{__bzr} init %{-q}\ - %{__bzr} whoami --branch "%{__scm_author}"\ - %{__bzr} add .\ --%{__bzr} commit %{-q} -m "%{name}-%{version} base" -+%{__bzr} commit %{-q} -m "%{NAME}-%{VERSION} base" - - # bzr doesn't seem to have its own command to apply patches? - %__scm_apply_bzr(qp:m:)\ --- -2.9.3 - diff --git a/0006-Make-adding-GDB-index-sections-configurable.patch b/0006-Make-adding-GDB-index-sections-configurable.patch new file mode 100644 index 0000000..1842ada --- /dev/null +++ b/0006-Make-adding-GDB-index-sections-configurable.patch @@ -0,0 +1,215 @@ +From 68a0323ab1738aee40f9f5a60a7fb3163162bf39 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 14 Jun 2016 17:07:14 +0200 +Subject: [PATCH 06/49] Make adding GDB index sections configurable. + +Introduces _include_gdb_index macro and -i flag to find-debuginfo.sh to +enable or disable adding a .gdb_index section to debug files. Adds tests +to make sure the .gdb_index is really added (or not) when requested. +Checks that gdb-add-index is actually installed instead of silently +failing if not. Similar for dwz. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 67d3df338875ad5d9601e360bfdbd4289f271bc1) + +Conflicts: + scripts/find-debuginfo.sh +--- + macros.debug | 1 + + macros.in | 8 ++++++- + scripts/find-debuginfo.sh | 29 ++++++++++++++++++---- + tests/rpmbuild.at | 61 +++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 94 insertions(+), 5 deletions(-) + +diff --git a/macros.debug b/macros.debug +index 6a8432eb7..d273c0876 100644 +--- a/macros.debug ++++ b/macros.debug +@@ -2,6 +2,7 @@ + + %_enable_debug_packages 1 + %_include_minidebuginfo 1 ++%_include_gdb_index 1 + + # Expanded at end of %install scriptlet + +diff --git a/macros.in b/macros.in +index dcd09612c..c845f5841 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,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} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ + %{nil} + + # Template for debug information sub-package. +@@ -449,6 +449,12 @@ package or when debugging this package.\ + #%_include_minidebuginfo 1 + + # ++# Include a .gdb_index section in the .debug files. ++# Requires _enable_debug_packages and gdb-add-index installed. ++# ++#%_include_gdb_index 1 ++ ++# + # Defines how and if build_id links are generated for ELF files. + # The following settings are supported: + # +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index 2cb9570ba..8e608134f 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] [-m] ++# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] + # [-o debugfiles.list] + # [--run-dwz] [--dwz-low-mem-die-limit N] + # [--dwz-max-die-limit N] +@@ -14,6 +14,8 @@ + # The --strict-build-id flag says to exit with failure status if + # any ELF binary processed fails to contain a build-id note. + # The -r flag says to use eu-strip --reloc-debug-sections. ++# The -m flag says to include a .gnu_debugdata section in the main binary. ++# The -i flag says to include a .gdb_index section in the .debug file. + # + # A single -o switch before any -l or -p switches simply renames + # the primary output file from debugfiles.list to something else. +@@ -48,6 +50,9 @@ strip_r=false + # with -m arg, add minimal debuginfo to binary. + include_minidebug=false + ++# with -i arg, add GDB index to .debug file. ++include_gdb_index=false ++ + # Barf on missing build IDs. + strict=false + +@@ -88,6 +93,9 @@ while [ $# -gt 0 ]; do + -m) + include_minidebug=true + ;; ++ -i) ++ include_gdb_index=true ++ ;; + -o) + if [ -z "${lists[$nout]}" -a -z "${ptns[$nout]}" ]; then + out=$2 +@@ -277,7 +285,15 @@ while read nlinks inum f; do + $strict && exit 2 + fi + +- type gdb-add-index >/dev/null 2>&1 && gdb-add-index "$f" > /dev/null 2>&1 ++ # Add .gdb_index if requested. ++ if $include_gdb_index; then ++ if type gdb-add-index >/dev/null 2>&1; then ++ gdb-add-index "$f" ++ else ++ echo >&2 "*** ERROR: GDB index requested, but no gdb-add-index installed" ++ exit 2 ++ fi ++ fi + + # A binary already copied into /usr/lib/debug doesn't get stripped, + # just has its file names collected and adjusted. +@@ -303,7 +319,7 @@ while read nlinks inum f; do + done || exit + + # Invoke the DWARF Compressor utility. +-if $run_dwz && type dwz >/dev/null 2>&1 \ ++if $run_dwz \ + && [ -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 +@@ -321,7 +337,12 @@ if $run_dwz && type dwz >/dev/null 2>&1 \ + && 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 ) ++ if type dwz >/dev/null 2>&1; then ++ ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts $dwz_files ) ++ else ++ echo >&2 "*** ERROR: DWARF compression requested, but no dwz installed" ++ exit 2 ++ fi + # 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 +diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at +index 1531700e1..a3123244c 100644 +--- a/tests/rpmbuild.at ++++ b/tests/rpmbuild.at +@@ -532,3 +532,64 @@ usr/local/bin/hello2 + ], + [ignore]) + AT_CLEANUP ++ ++# ------------------------------ ++# Check that a GDB index is included when requested. ++AT_SETUP([rpmbuild debuginfo gdb index included]) ++AT_KEYWORDS([build] [debuginfo] [gdb]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Build a package that has some debuginfo ++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 \ ++ --define "_include_gdb_index 1" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2.spec ++ ++# Unpack the debuginfo rpms so we can check the .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# Check that gdb-add-index has ran and a .gdb_index section has been added ++readelf -S ./usr/lib/debug/usr/local/bin/hello2*.debug \ ++ | grep gdb_index | cut -c8-17 ++], ++[0], ++[.gdb_index ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that a GDB index is NOT included when not requested. ++AT_SETUP([rpmbuild debuginfo no gdb index included]) ++AT_KEYWORDS([build] [debuginfo] [gdb]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Build a package that has some debuginfo ++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 \ ++ --undefine "_include_gdb_index" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2.spec ++ ++# Unpack the debuginfo rpms so we can check the .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# Check that gdb-add-index has not ran and no .gdb_index section has been added ++readelf -S ./usr/lib/debug/usr/local/bin/hello2*.debug \ ++ | grep gdb_index | cut -c8-17 ++], ++[0], ++[], ++[ignore]) ++AT_CLEANUP +-- +2.13.2 + diff --git a/0006-Pass-proper-file-index-when-recording-generated-depe.patch b/0006-Pass-proper-file-index-when-recording-generated-depe.patch deleted file mode 100644 index 7907672..0000000 --- a/0006-Pass-proper-file-index-when-recording-generated-depe.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 34979267904cec0c53cad1e1361db733f56dcbf8 Mon Sep 17 00:00:00 2001 -From: Florian Festi -Date: Wed, 31 May 2017 10:42:03 +0200 -Subject: [PATCH 6/6] Pass proper file index when recording generated - dependencies - -Resolves regression introduced with 8f509d6 -Fixes #224 - -(cherry picked from commit dab75e7f26a08cc6798e4df177adb2dd8d40035c) ---- - build/rpmfc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/build/rpmfc.c b/build/rpmfc.c -index 7fa8227d0..72f29ddf5 100644 ---- a/build/rpmfc.c -+++ b/build/rpmfc.c -@@ -511,7 +511,7 @@ static int rpmfcHelper(rpmfc fc, int ix, - data.exclude = exclude; - - for (int i = 0; i < pac; i++) { -- if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, 0, dsContext, addReqProvFc, &data)) -+ if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, ix, dsContext, addReqProvFc, &data)) - rc++; - } - --- -2.13.1 - diff --git a/0007-Add-option-to-have-unique-debug-file-names-across-ve.patch b/0007-Add-option-to-have-unique-debug-file-names-across-ve.patch new file mode 100644 index 0000000..6a6fe07 --- /dev/null +++ b/0007-Add-option-to-have-unique-debug-file-names-across-ve.patch @@ -0,0 +1,807 @@ +From 5b29c09c31982a712844cb2bbcd0bfff09c457d1 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 16 Jun 2016 14:24:22 +0200 +Subject: [PATCH 07/49] Add option to have unique debug file names across + version/release/arch. + +Introduce a new macro _unique_debug_names that when set will pass +--unique-debug-arch "%{_arch}" to find-debuginfo.sh to create debuginfo +files which end in "--..debug" instead of simply ".debug". + +Adds testcases for dwz and buildid with and without unique debug file names. + +Signed-off-by: Mark Wielaard + +(cherry picked from commit 45bfecbf7dd4249abc197a5fc908e4efcc3108ad) +--- + build/files.c | 19 ++- + macros.debug | 3 + + macros.in | 9 +- + scripts/find-debuginfo.sh | 18 ++- + tests/rpmbuild.at | 168 +++++++++++++++++++----- + tests/rpmbuildid.at | 316 +++++++++++++++++++++++++++++++++++++++++++++- + 6 files changed, 494 insertions(+), 39 deletions(-) + +diff --git a/build/files.c b/build/files.c +index b010483e4..eb398562a 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1790,6 +1790,16 @@ static int generateBuildIDs(FileList fl) + } + } + ++ /* In case we need ALLDEBUG links we might need the vra as ++ tagged onto the .debug file name. */ ++ char *vra = NULL; ++ if (rc == 0 && needDbg && build_id_links == BUILD_IDS_ALLDEBUG) { ++ int unique_debug_names = ++ rpmExpandNumeric("%{?_unique_debug_names}"); ++ if (unique_debug_names == 1) ++ vra = rpmExpand("-%{version}-%{release}.%{_arch}", NULL); ++ } ++ + /* Now add a subdir and symlink for each buildid found. */ + for (i = 0; i < nr_ids; i++) { + /* Don't add anything more when an error occured. But do +@@ -1884,15 +1894,17 @@ static int generateBuildIDs(FileList fl) + int pathlen = strlen(paths[i]); + int debuglen = strlen(".debug"); + int prefixlen = strlen("/usr/lib/debug"); +- if (pathlen > prefixlen +- && strcmp (paths[i] + pathlen - debuglen, ++ int vralen = vra == NULL ? 0 : strlen(vra); ++ if (pathlen > prefixlen + debuglen + vralen ++ && strcmp ((paths[i] + pathlen - debuglen), + ".debug") == 0) { + free(linkpath); + free(targetpath); + char *targetstr = xstrdup (paths[i] + + prefixlen); + int targetlen = pathlen - prefixlen; +- targetstr[targetlen - debuglen] = '\0'; ++ int targetend = targetlen - debuglen - vralen; ++ targetstr[targetend] = '\0'; + rasprintf(&linkpath, "%s/%s", + buildidsubdir, &ids[i][2]); + rasprintf(&targetpath, "../../../../..%s", +@@ -1911,6 +1923,7 @@ static int generateBuildIDs(FileList fl) + free(paths[i]); + free(ids[i]); + } ++ free(vra); + free(paths); + free(ids); + } +diff --git a/macros.debug b/macros.debug +index d273c0876..ee0cc9ebe 100644 +--- a/macros.debug ++++ b/macros.debug +@@ -1,4 +1,7 @@ + # macros to include to generate debuginfo ++# Note don't define/enable a feature here if it is already the default in ++# macros.in. Otherwise it cannot simply be --undefined on the command line ++# in the tests (it needs to be undefined multiple times then). + + %_enable_debug_packages 1 + %_include_minidebuginfo 1 +diff --git a/macros.in b/macros.in +index c845f5841..68bf39194 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ + %{nil} + + # Template for debug information sub-package. +@@ -488,6 +488,13 @@ package or when debugging this package.\ + # onto debugedit --build-id-seed to be used to prime the build-id note hash. + %_unique_build_ids 1 + ++# Whether .debug files should be made unique between package version, ++# release and architecture. If set to 1 this will pass ++# --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create ++# debuginfo files which end in --..debug ++# Requires _unique_build_ids. ++%_unique_debug_names 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 8e608134f..3653c4848 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -64,6 +64,9 @@ dwz_max_die_limit= + # Version and release of the spec. Given by --ver-rel + ver_rel= + ++# Arch given by --unique-debug-arch ++unique_debug_arch= ++ + BUILDDIR=. + out=debugfiles.list + nout=0 +@@ -87,6 +90,10 @@ while [ $# -gt 0 ]; do + ver_rel=$2 + shift + ;; ++ --unique-debug-arch) ++ unique_debug_arch=$2 ++ shift ++ ;; + -g) + strip_g=true + ;; +@@ -125,6 +132,11 @@ while [ $# -gt 0 ]; do + shift + done + ++if test -z "$ver_rel" -a -n "$unique_debug_arch"; then ++ echo >&2 "*** ERROR: --unique-debug-arch (${unique_debug_arch}) needs --ver-rel (${ver_rel})" ++ exit 2 ++fi ++ + i=0 + while ((i < nout)); do + outs[$i]="$BUILDDIR/${outs[$i]}" +@@ -232,7 +244,11 @@ debug_link() + get_debugfn() + { + dn=$(dirname "${1#$RPM_BUILD_ROOT}") +- bn=$(basename "$1" .debug).debug ++ if test -n "${unique_debug_arch}"; then ++ bn=$(basename "$1" .debug)-${ver_rel}.${unique_debug_arch}.debug ++ else ++ bn=$(basename "$1" .debug).debug ++ fi + + debugdn=${debugdir}${dn} + debugfn=${debugdn}/${bn} +diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at +index a3123244c..0a2c01efe 100644 +--- a/tests/rpmbuild.at ++++ b/tests/rpmbuild.at +@@ -386,8 +386,9 @@ 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. ++# Test the case without unique debug file names. + AT_SETUP([rpmbuild debuginfo dwz]) +-AT_KEYWORDS([build] [debuginfo]) ++AT_KEYWORDS([build] [debuginfo] [dwz]) + AT_CHECK([ + rm -rf ${TOPDIR} + AS_MKDIR_P(${TOPDIR}/SOURCES) +@@ -397,63 +398,170 @@ cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/he + 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_debug_names" \ + -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 ++ ++hello_file_debug=./usr/lib/debug/usr/local/bin/hello.debug ++hello2_file_debug=./usr/lib/debug/usr/local/bin/hello2.debug ++hello_multi_file=./usr/lib/debug/.dwz/hello2-1.0-1.* ++test -f $hello_file_debug || echo "no hello debug file: $hello_file_debug" ++test -f $hello2_file_debug || echo "no hello2 debug file: $hello2_file_debug" ++test -f $hello_multi_file || echo "no dwz multi file: $hello_multi_file" + + # 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 ++hello_file=./usr/local/bin/hello ++hello2_file=./usr/local/bin/hello2 ++test -f $hello_file || echo "no hello file: $hello_file" ++test -f $hello2_file || echo "no hello2 file: $hello2_file" ++ ++id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" ++test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" ++ ++# 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 $hello_file) ++canonid1debug=$(readlink -f ${id1file}.debug) ++canondebug1=$(readlink -f $hello_file_debug) ++ ++test "$canonid1file" = "$canonfile1" \ ++ || echo "canonid1file: $canonid1file != $canonfile1" ++test "$canonid1debug" = "$canondebug1" \ ++ || echo "canonid1debug: $canonid1debug != $canondebug1" ++ ++id2file="./usr/lib/debug/.build-id/${id2:0:2}/${id2:2}" ++canonid2file=$(readlink -f ${id2file}) ++canonfile2=$(readlink -f $hello2_file) ++canonid2debug=$(readlink -f ${id2file}.debug) ++canondebug2=$(readlink -f $hello2_file_debug) ++ ++test "$canonid2file" = "$canonfile2" \ ++ || echo "canonid2: $canonid2file != $canonfile2" ++test "$canonid2debug" = "$canondebug2" \ ++ || echo "canonid2debug: $canonid2debug" != "$canondebug2" ++ ++# 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 $hello_file_debug \ ++ | grep '[ 0]' | cut -c13-) ++multiref2=$(readelf --string-dump=.gnu_debugaltlink $hello2_file_debug \ ++ | grep '[ 0]' | cut -c13-) ++ ++test "$multiref1" = "$multiref2" || echo "multiref: $multiref1 != $multiref2" ++ ++canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1) ++canonmultifile=$(readlink -f $hello_multi_file) ++ ++test "$canonmultiref" = "$canonmultifile" \ ++ || echo "canonmultiref: $canonmultiref" != "$canonmultifile" ++], ++[0], ++[], ++[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. ++# Test with unique debug file names. ++AT_SETUP([rpmbuild debuginfo dwz unique debug names]) ++AT_KEYWORDS([build] [debuginfo] [dwz]) ++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 \ ++ --define "_unique_debug_names 1" \ ++ -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 ++ ++hello_file_debug=./usr/lib/debug/usr/local/bin/hello-*.debug ++hello2_file_debug=./usr/lib/debug/usr/local/bin/hello2-*.debug ++hello_multi_file=./usr/lib/debug/.dwz/hello2-1.0-1.* ++test -f $hello_file_debug || echo "no hello debug file: $hello_file_debug" ++test -f $hello2_file_debug || echo "no hello2 debug file: $hello2_file_debug" ++test -f $hello_multi_file || echo "no dwz multi file: $hello_multi_file" ++ ++# 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 ++hello_file=./usr/local/bin/hello ++hello2_file=./usr/local/bin/hello2 ++test -f $hello_file || echo "no hello file: $hello_file" ++test -f $hello2_file || echo "no hello2 file: $hello2_file" ++ ++id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" ++test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" + + # 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) ++canonfile1=$(readlink -f $hello_file) + canonid1debug=$(readlink -f ${id1file}.debug) +-canondebug1=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug) ++canondebug1=$(readlink -f $hello_file_debug) + +-test "$canonid1file" = "$canonfile1" || exit 1 +-test "$canonid1debug" = "$canondebug1" || exit 1 ++test "$canonid1file" = "$canonfile1" \ ++ || echo "canonid1file: $canonid1file != $canonfile1" ++test "$canonid1debug" = "$canondebug1" \ ++ || echo "canonid1debug: $canonid1debug != $canondebug1" + + 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) ++canonid2file=$(readlink -f ${id2file}) ++canonfile2=$(readlink -f $hello2_file) ++canonid2debug=$(readlink -f ${id2file}.debug) ++canondebug2=$(readlink -f $hello2_file_debug) + +-test "$canonid2file" = "$canonfile2" || exit 1 +-test "$canonid2debug" = "$canondebug2" || exit 1 ++test "$canonid2file" = "$canonfile2" \ ++ || echo "canonid2: $canonid2file != $canonfile2" ++test "$canonid2debug" = "$canondebug2" \ ++ || echo "canonid2debug: $canonid2debug" != "$canondebug2" + + # 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-) ++multiref1=$(readelf --string-dump=.gnu_debugaltlink $hello_file_debug \ ++ | grep '[ 0]' | cut -c13-) ++multiref2=$(readelf --string-dump=.gnu_debugaltlink $hello2_file_debug \ ++ | grep '[ 0]' | cut -c13-) + +-test "$multiref1" = "$multiref2" || exit 1 ++test "$multiref1" = "$multiref2" || echo "multiref: $multiref1 != $multiref2" + + canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1) +-canonmultifile=$(readlink -f ./usr/lib/debug/.dwz/hello2-1.0-1.*) ++canonmultifile=$(readlink -f $hello_multi_file) + +-test "$canonmultiref" = "$canonmultifile" || exit 1 ++test "$canonmultiref" = "$canonmultifile" \ ++ || echo "canonmultiref: $canonmultiref" != "$canonmultifile" + ], + [0], + [], +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +index 1da63022d..ede1181e1 100644 +--- a/tests/rpmbuildid.at ++++ b/tests/rpmbuildid.at +@@ -54,7 +54,8 @@ hello debuginfo build-id files: 0 + AT_CLEANUP + + # ------------------------------ +-# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks ++# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks. ++# Without unique debug file names. + AT_SETUP([rpmbuild buildid alldebug]) + AT_KEYWORDS([build] [debuginfo] [buildid]) + AT_CHECK([ +@@ -69,6 +70,7 @@ run rpmbuild \ + --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="_build_id_links alldebug" \ ++ --undefine "_unique_debug_names" \ + --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec + + # There should be zero build-id files in the main package +@@ -114,7 +116,100 @@ test "$canon_main_file" = "$canon_main_id_file" \ + + # And check the same for the debug file. + debug_file=./usr/lib/debug/usr/local/bin/hello.debug +-test -f "${debug_file}" || echo "No debug file ${debug_file}" ++test -f ${debug_file} || echo "No debug file ${debug_file}" ++ ++# Extract the build-id from the .debug file ++id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test ${id_main} = ${id_debug} || echo "unequal main and debug id" ++ ++id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" ++test -L "$id_debug_file" || echo "No build-id file $id_debug_file" ++ ++canon_debug_file=$(readlink -f ${debug_file}) ++ ++test -f "$canon_debug_file" \ ++ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" ++ ++canon_debug_id_file=$(readlink -f ${id_debug_file}) ++ ++test -f "$canon_debug_id_file" \ ++ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" ++ ++test "$canon_debug_file" = "$canon_debug_id_file" \ ++ || echo "debug and build-id not linked" ++], ++[0], ++[hello build-id files: 0 ++hello debuginfo build-id files: 3 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check if rpmbuild "alldebug" generates debuginfo buildid symlinks. ++# With unique debug file names. ++AT_SETUP([rpmbuild buildid alldebug unique debug names]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links alldebug" \ ++ --define="_unique_debug_names 1" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be zero build-id files in the main package ++# Main and debug should be in the debuginfo package, ++# plus the .build-id/xx subdir, 3 in total. ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++# Extract the both packages to check the build-id files link to the ++# main and .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ ++ | cpio -diu ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu ++ ++# Check there is a build-id symlink for the main file. ++main_file=./usr/local/bin/hello ++test -f "${main_file}" || echo "No main file ${main_file}" ++ ++# Extract the build-id from the main file ++id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_main_file" || echo "No build-id file $id_main_file" ++ ++canon_main_file=$(readlink -f ${main_file}) ++ ++test -f "$canon_main_file" \ ++ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" ++ ++canon_main_id_file=$(readlink -f ${id_main_file}) ++ ++test -f "$canon_main_id_file" \ ++ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" ++ ++test "$canon_main_file" = "$canon_main_id_file" \ ++ || echo "main and build-id file not linked" ++ ++# And check the same for the debug file. ++debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug ++test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file + id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +@@ -146,6 +241,7 @@ AT_CLEANUP + + # ------------------------------ + # Check if rpmbuild "separate" generates main and debuginfo buildid symlinks ++# Without unique debug file names + AT_SETUP([rpmbuild buildid separate]) + AT_KEYWORDS([build] [debuginfo] [buildid]) + AT_CHECK([ +@@ -160,6 +256,7 @@ run rpmbuild \ + --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="_build_id_links separate" \ ++ --undefine "_unique_debug_names" \ + --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec + + # There should be one build-id files in the main and debuginfo package +@@ -204,7 +301,99 @@ test "$canon_main_file" = "$canon_main_id_file" \ + + # And check the same for the debug file. + debug_file=./usr/lib/debug/usr/local/bin/hello.debug +-test -f "${debug_file}" || echo "No debug file ${debug_file}" ++test -f ${debug_file} || echo "No debug file ${debug_file}" ++ ++# Extract the build-id from the .debug file ++id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test ${id_main} = ${id_debug} || echo "unequal main and debug id" ++ ++id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" ++test -L "$id_debug_file" || echo "No build-id file $id_debug_file" ++ ++canon_debug_file=$(readlink -f ${debug_file}) ++ ++test -f "$canon_debug_file" \ ++ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" ++ ++canon_debug_id_file=$(readlink -f ${id_debug_file}) ++ ++test -f "$canon_debug_id_file" \ ++ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" ++ ++test "$canon_debug_file" = "$canon_debug_id_file" \ ++ || echo "debug and build-id not linked" ++], ++[0], ++[hello build-id files: 2 ++hello debuginfo build-id files: 2 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check if rpmbuild "separate" generates main and debuginfo buildid symlinks ++# With unique debug file names ++AT_SETUP([rpmbuild buildid separate unique debug names]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links separate" \ ++ --define="_unique_debug_names 1" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be one build-id files in the main and debuginfo package ++# plus the .build-id/xx subdir, 2 in total. ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++# Extract the both packages to check the build-id files link to the ++# main and .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ ++ | cpio -diu ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu ++ ++# Check there is a build-id symlink for the main file. ++main_file=./usr/local/bin/hello ++test -f "${main_file}" || echo "No main file ${main_file}" ++ ++# Extract the build-id from the main file ++id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_main_file" || echo "No build-id file $id_main_file" ++ ++canon_main_file=$(readlink -f ${main_file}) ++ ++test -f "$canon_main_file" \ ++ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" ++ ++canon_main_id_file=$(readlink -f ${id_main_file}) ++ ++test -f "$canon_main_id_file" \ ++ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" ++ ++test "$canon_main_file" = "$canon_main_id_file" \ ++ || echo "main and build-id file not linked" ++ ++# And check the same for the debug file. ++debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug ++test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file + id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +@@ -236,6 +425,7 @@ AT_CLEANUP + + # ------------------------------ + # Check if rpmbuild "compat" generates main and debuginfo buildid symlinks ++# Without unique debug file names + AT_SETUP([rpmbuild buildid compat]) + AT_KEYWORDS([build] [debuginfo] [buildid]) + AT_CHECK([ +@@ -250,6 +440,7 @@ run rpmbuild \ + --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="_build_id_links compat" \ ++ --undefine "_unique_debug_names" \ + --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec + + # There should be one build-id files in the main and debuginfo package. +@@ -295,7 +486,112 @@ test "$canon_main_file" = "$canon_main_id_file" \ + + # And check the same for the debug file. + debug_file=./usr/lib/debug/usr/local/bin/hello.debug +-test -f "${debug_file}" || echo "No debug file ${debug_file}" ++test -f ${debug_file} || echo "No debug file ${debug_file}" ++ ++# Extract the build-id from the .debug file ++id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++test ${id_main} = ${id_debug} || echo "unequal main and debug id" ++ ++id_debug_file="./usr/lib/debug/.build-id/${id_debug:0:2}/${id_debug:2}.debug" ++test -L "$id_debug_file" || echo "No build-id file $id_debug_file" ++ ++canon_debug_file=$(readlink -f ${debug_file}) ++ ++test -f "$canon_debug_file" \ ++ || echo "Cannot resolve debug file ${debug_file} -> ${canon_debug_file}" ++ ++canon_debug_id_file=$(readlink -f ${id_debug_file}) ++ ++test -f "$canon_debug_id_file" \ ++ || echo "Cannot resolve debug build-id file ${id_debug_file} -> ${canon_debug_id_file}" ++ ++test "$canon_debug_file" = "$canon_debug_id_file" \ ++ || echo "debug and build-id not linked" ++ ++# The compat link should also point to the same (indirectly). ++id_compat_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_compat_file" || echo "No build-id compat file $id_compat_file" ++ ++canon_compat_file=$(readlink -f ${id_compat_file}) ++ ++test -f "$canon_compat_file" \ ++ || echo "Cannot resolve compat file ${id_compat_file} -> ${canon_compat_file}" ++ ++test "$canon_compat_file" = "$canon_main_file" \ ++ || echo "compat and build-id not linked" ++], ++[0], ++[hello build-id files: 2 ++hello debuginfo build-id files: 3 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check if rpmbuild "compat" generates main and debuginfo buildid symlinks ++# With unique debug file names ++AT_SETUP([rpmbuild buildid compat unique debug names]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links compat" \ ++ --define="_unique_debug_names 1" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec ++ ++# There should be one build-id files in the main and debuginfo package. ++# the debuginfo package has one extra main build-id compat symlink ++# plus the .build-id/xx subdir, 2 in total in main, 3 in total in debug ++echo -n "hello build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++echo -n "hello debuginfo build-id files: " ++run rpm -ql -p "${TOPDIR}"/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | grep /.build-id/ | wc --lines ++ ++# Extract the both packages to check the build-id files link to the ++# main and .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ ++ | cpio -diu ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu ++ ++# Check there is a build-id symlink for the main file. ++main_file=./usr/local/bin/hello ++test -f "${main_file}" || echo "No main file ${main_file}" ++ ++# Extract the build-id from the main file ++id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++ ++id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" ++test -L "$id_main_file" || echo "No build-id file $id_main_file" ++ ++canon_main_file=$(readlink -f ${main_file}) ++ ++test -f "$canon_main_file" \ ++ || echo "Cannot resolve main file ${main_file} -> ${canon_main_file}" ++ ++canon_main_id_file=$(readlink -f ${id_main_file}) ++ ++test -f "$canon_main_id_file" \ ++ || echo "Cannot resolve main build-id file ${id_main_file} -> ${canon_main_id_file}" ++ ++test "$canon_main_file" = "$canon_main_id_file" \ ++ || echo "main and build-id file not linked" ++ ++# And check the same for the debug file. ++debug_file=./usr/lib/debug/usr/local/bin/hello-*debug ++test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file + id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +@@ -784,8 +1080,12 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file ++test -f $hello_file || echo "No $hello_file" + id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') + ++# Make sure we generate a new one ++rm $hello_file ++ + # 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 \ +@@ -797,6 +1097,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ + | cpio -diu --quiet + + # Extract the build-id from the main file ++test -f $hello_file || echo "No $hello_file" + id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') + + if test "$id1" == "$id2"; then echo "equal $id1"; else echo "unequal"; fi +@@ -823,6 +1124,7 @@ 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" \ ++ --undefine="_unique_debug_names" \ + -ba "${abs_srcdir}"/data/SPECS/hello.spec + + rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ +@@ -831,19 +1133,25 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file ++test -f $hello_file || echo "No $hello_file" + id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') + ++# Make sure we generate a new one ++rm $hello_file ++ + # 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" \ ++ --undefine="_unique_debug_names" \ + -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 ++test -f $hello_file || echo "No $hello_file" + id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') + + if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi +-- +2.13.2 + diff --git a/0007-Only-process-regular-files-when-generating-build-ids.patch b/0007-Only-process-regular-files-when-generating-build-ids.patch deleted file mode 100644 index 7d5b624..0000000 --- a/0007-Only-process-regular-files-when-generating-build-ids.patch +++ /dev/null @@ -1,53 +0,0 @@ -From eb21562bcec67746e756679a60995f68d7d45577 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Panu Matilainen -Date: Thu, 5 Jan 2017 12:13:54 +0200 -Subject: [PATCH 07/11] Only process regular files when generating build-ids - -Versioned shared libraries typically have several symlinks pointing -to them directly and indirectly. When %_build_id_links is set to compat or -separate this causes bogus warnings about duplicate build-ids. - -It looks commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 intends to skip -symlinks since it filters on S_ISREG(), but since uses fstat() -on already open()'ed file it ends up stat()'ing the symlink target. -Flip stat() + open() around and use lstat() instead to fix it. ---- - build/files.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - -diff --git a/build/files.c b/build/files.c -index 2ede463..ca04176 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1678,11 +1678,10 @@ static int generateBuildIDs(FileList fl) - int needMain = 0; - int needDbg = 0; - for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { -- int fd; -- fd = open (flp->diskPath, O_RDONLY); -- if (fd >= 0) { -- struct stat sbuf; -- if (fstat (fd, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { -+ struct stat sbuf; -+ if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { -+ int fd = open (flp->diskPath, O_RDONLY); -+ if (fd >= 0) { - Elf *elf = elf_begin (fd, ELF_C_READ, NULL); - if (elf != NULL && elf_kind(elf) == ELF_K_ELF) { - const void *build_id; -@@ -1748,8 +1747,8 @@ static int generateBuildIDs(FileList fl) - } - elf_end (elf); - } -+ close (fd); - } -- close (fd); - } - } - --- -2.9.3 - diff --git a/0008-Fix-behavior-when-_build_id_links-is-undefined.patch b/0008-Fix-behavior-when-_build_id_links-is-undefined.patch new file mode 100644 index 0000000..4d54ee7 --- /dev/null +++ b/0008-Fix-behavior-when-_build_id_links-is-undefined.patch @@ -0,0 +1,31 @@ +From a040e812b39d1fcc6aa69ca6aa5ff2fe4316a018 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 3 Oct 2016 12:36:46 +0300 +Subject: [PATCH 08/49] Fix behavior when %_build_id_links is undefined + +Commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 tries to behave sanely +and use compat setting when %_build_id_links is undefined, but +rpmExpand() never returns NULL so the original check is incorrect. +Check for empty string instead. + +(cherry picked from commit 2ea72daabe3f0c4bef628d5a16768f293ffab3df) +--- + build/files.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build/files.c b/build/files.c +index eb398562a..6215bf85c 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1648,7 +1648,7 @@ static int generateBuildIDs(FileList fl) + /* How are we supposed to create the build-id links? */ + char *build_id_links_macro = rpmExpand("%{?_build_id_links}", NULL); + int build_id_links; +- if (build_id_links_macro == NULL) { ++ if (*build_id_links_macro == '\0') { + rpmlog(RPMLOG_WARNING, + _("_build_id_links macro not set, assuming 'compat'\n")); + build_id_links = BUILD_IDS_COMPAT; +-- +2.13.2 + diff --git a/0008-configure.ac-use-LIBDW-always-conditionally.patch b/0008-configure.ac-use-LIBDW-always-conditionally.patch deleted file mode 100644 index 1c80ca9..0000000 --- a/0008-configure.ac-use-LIBDW-always-conditionally.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 1e38abe3e6697efcf55663060533e286e1e77ae4 Mon Sep 17 00:00:00 2001 -Message-Id: <1e38abe3e6697efcf55663060533e286e1e77ae4.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Igor Gnatenko -Date: Wed, 10 Aug 2016 13:58:30 +0200 -Subject: [PATCH 08/11] configure.ac: use LIBDW always conditionally - -References: https://bugzilla.redhat.com/show_bug.cgi?id=1365278 -Reported-and-tested-by: Neal Gompa -Signed-off-by: Igor Gnatenko ---- - configure.ac | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 08eceeb..5dd2bb6 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -368,7 +368,8 @@ AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) - - #================= - # Check for elfutils libdw library with dwelf_elf_gnu_build_id. --AS_IF([test "$WITH_LIBELF" = yes],[ -+WITH_LIBDW_LIB= -+AS_IF([test "$WITH_LIBELF" != yes],[ - AC_CHECK_HEADERS([elfutils/libdwelf.h],[ - AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ - AC_DEFINE(HAVE_LIBDW, 1, -@@ -377,9 +378,9 @@ AS_IF([test "$WITH_LIBELF" = yes],[ - WITH_LIBDW=yes - ]) - ]) -- AC_SUBST(WITH_LIBDW_LIB) -- AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) - ]) -+AC_SUBST(WITH_LIBDW_LIB) -+AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) - - #================= - # Process --with/without-external-db --- -2.9.3 - diff --git a/0009-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch b/0009-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch new file mode 100644 index 0000000..cc9c765 --- /dev/null +++ b/0009-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch @@ -0,0 +1,142 @@ +From 932c2170e961d393569992b2f9c3ab8ee415f01b Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Wed, 9 Nov 2016 09:16:48 +0200 +Subject: [PATCH 09/49] Fix debuginfo etc when subpackages have different + versions (RhBug:1051407) + +Rpm has always been a bit dazed and confused when it comes to specs +with sub-packages having different version etc from the main package. +Many things work fine in that case .. except .. when they dont. Debuginfo +picking up wrong versions (RhBug:1051407) is just one example, there +are countless more in bugzilla wrt buildroot paths and whatnot. +The simple and sane solution would be not piling on them macros +from sub-packages, but that would surely break somebodys precious +spec tricks. + +The ugly but brutally simple and compatible solution to this all is to +create separate set of macros when on the main package, this lets users +in and out of rpm pick which one (latest or main) they want. To hopefully +avoid stomping on anybodys toes, use uppercasing for the macro name (other +variants like %pkg_release are awfully commonly used). Pile 'em on, yay! + +(cherry picked from commit ccdb1aa5c675d917b1ba8d026c44fd95bab79e6c) + +Conflicts: + build/parsePreamble.c + macros.in +--- + build/files.c | 2 +- + build/parsePreamble.c | 11 ++++++++++- + macros.in | 18 +++++++++--------- + 3 files changed, 20 insertions(+), 11 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 6215bf85c..2ede463a1 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1797,7 +1797,7 @@ static int generateBuildIDs(FileList fl) + int unique_debug_names = + rpmExpandNumeric("%{?_unique_debug_names}"); + if (unique_debug_names == 1) +- vra = rpmExpand("-%{version}-%{release}.%{_arch}", NULL); ++ vra = rpmExpand("-%{VERSION}-%{RELEASE}.%{_arch}", NULL); + } + + /* Now add a subdir and symlink for each buildid found. */ +diff --git a/build/parsePreamble.c b/build/parsePreamble.c +index 933f7340f..6be440369 100644 +--- a/build/parsePreamble.c ++++ b/build/parsePreamble.c +@@ -909,8 +909,17 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, + goto exit; + } + +- if (macro) ++ if (macro) { + addMacro(spec->macros, macro, NULL, field, RMIL_SPEC); ++ /* Add a separate uppercase macro for tags from the main package */ ++ if (pkg == spec->packages) { ++ char *m = xstrdup(macro); ++ for (char *p = m; *p; ++p) ++ *p = rtoupper(*p); ++ addMacro(spec->macros, m, NULL, field, RMIL_SPEC); ++ free(m); ++ } ++ } + rc = RPMRC_OK; + exit: + return rc; +diff --git a/macros.in b/macros.in +index 68bf39194..4d9028254 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{version}-%{release}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ + %{nil} + + # Template for debug information sub-package. +@@ -232,7 +232,7 @@ package or when debugging this package.\ + %_buildrootdir %{_topdir}/BUILDROOT + + # Build root path, where %install installs the package during build. +-%buildroot %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch} ++%buildroot %{_buildrootdir}/%{NAME}-%{VERSION}-%{RELEASE}.%{_arch} + + # Directory where temporaray files can be created. + %_tmppath %{_var}/tmp +@@ -484,7 +484,7 @@ package or when debugging this package.\ + + # 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 ++# --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 + +@@ -705,9 +705,9 @@ package or when debugging this package.\ + export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\ + RPM_DOC_DIR=\"%{_docdir}\"\ + export RPM_DOC_DIR\ +- RPM_PACKAGE_NAME=\"%{name}\"\ +- RPM_PACKAGE_VERSION=\"%{version}\"\ +- RPM_PACKAGE_RELEASE=\"%{release}\"\ ++ RPM_PACKAGE_NAME=\"%{NAME}\"\ ++ RPM_PACKAGE_VERSION=\"%{VERSION}\"\ ++ RPM_PACKAGE_RELEASE=\"%{RELEASE}\"\ + export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\ + LANG=C\ + export LANG\ +@@ -1146,7 +1146,7 @@ done \ + %__scm_setup_hg(q)\ + %{__hg} init %{-q} .\ + %{__hg} add %{-q} .\ +-%{__hg} commit %{-q} --user "%{__scm_author}" -m "%{name}-%{version} base" ++%{__hg} commit %{-q} --user "%{__scm_author}" -m "%{NAME}-%{VERSION} base" + + %__scm_apply_hg(qp:m:)\ + %{__hg} import - %{-p:-p%{-p*}} %{-q} -m %{-m*} --user "%{__scm_author}" +@@ -1158,7 +1158,7 @@ done \ + %{__git} config user.email "%{__scm_usermail}"\ + %{__git} add .\ + %{__git} commit %{-q} -a\\\ +- --author "%{__scm_author}" -m "%{name}-%{version} base" ++ --author "%{__scm_author}" -m "%{NAME}-%{VERSION} base" + + %__scm_apply_git(qp:m:)\ + %{__git} apply --index %{-p:-p%{-p*}} -\ +@@ -1181,7 +1181,7 @@ done \ + %{__bzr} init %{-q}\ + %{__bzr} whoami --branch "%{__scm_author}"\ + %{__bzr} add .\ +-%{__bzr} commit %{-q} -m "%{name}-%{version} base" ++%{__bzr} commit %{-q} -m "%{NAME}-%{VERSION} base" + + # bzr doesn't seem to have its own command to apply patches? + %__scm_apply_bzr(qp:m:)\ +-- +2.13.2 + diff --git a/0009-Fix-libdw-configure-check.patch b/0009-Fix-libdw-configure-check.patch deleted file mode 100644 index 8228921..0000000 --- a/0009-Fix-libdw-configure-check.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 15617bfa3d12ebe3927b130a88df6dd12ee8d0f9 Mon Sep 17 00:00:00 2001 -Message-Id: <15617bfa3d12ebe3927b130a88df6dd12ee8d0f9.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Wed, 24 Aug 2016 17:06:34 +0200 -Subject: [PATCH 09/11] Fix libdw configure check. - -commit a82119 "configure.ac: use LIBDW always conditionally" contained -a typo that caused WITH_LIBDW_LIB never to be set when you were using -libelf. Fixed by reverting the "!=" to "=" again. - -Signed-off-by: Mark Wielaard ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 5dd2bb6..4baa3f1 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -369,7 +369,7 @@ AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) - #================= - # Check for elfutils libdw library with dwelf_elf_gnu_build_id. - WITH_LIBDW_LIB= --AS_IF([test "$WITH_LIBELF" != yes],[ -+AS_IF([test "$WITH_LIBELF" = yes],[ - AC_CHECK_HEADERS([elfutils/libdwelf.h],[ - AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ - AC_DEFINE(HAVE_LIBDW, 1, --- -2.9.3 - diff --git a/0010-Only-process-regular-files-when-generating-build-ids.patch b/0010-Only-process-regular-files-when-generating-build-ids.patch new file mode 100644 index 0000000..e5905ab --- /dev/null +++ b/0010-Only-process-regular-files-when-generating-build-ids.patch @@ -0,0 +1,52 @@ +From 29f756e3fba09f6a66515970978367829862f35c Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 5 Jan 2017 12:13:54 +0200 +Subject: [PATCH 10/49] Only process regular files when generating build-ids + +Versioned shared libraries typically have several symlinks pointing +to them directly and indirectly. When %_build_id_links is set to compat or +separate this causes bogus warnings about duplicate build-ids. + +It looks commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 intends to skip +symlinks since it filters on S_ISREG(), but since uses fstat() +on already open()'ed file it ends up stat()'ing the symlink target. +Flip stat() + open() around and use lstat() instead to fix it. + +(cherry picked from commit 1ce844ab263bf49ee6d5145ed09e73f2c17924cc) +--- + build/files.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 2ede463a1..ca041764f 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1678,11 +1678,10 @@ static int generateBuildIDs(FileList fl) + int needMain = 0; + int needDbg = 0; + for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { +- int fd; +- fd = open (flp->diskPath, O_RDONLY); +- if (fd >= 0) { +- struct stat sbuf; +- if (fstat (fd, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { ++ struct stat sbuf; ++ if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { ++ int fd = open (flp->diskPath, O_RDONLY); ++ if (fd >= 0) { + Elf *elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf != NULL && elf_kind(elf) == ELF_K_ELF) { + const void *build_id; +@@ -1748,8 +1747,8 @@ static int generateBuildIDs(FileList fl) + } + elf_end (elf); + } ++ close (fd); + } +- close (fd); + } + } + +-- +2.13.2 + diff --git a/0010-debugedit-Support-String-Line-table-rewriting-for-la.patch b/0010-debugedit-Support-String-Line-table-rewriting-for-la.patch deleted file mode 100644 index 566af7a..0000000 --- a/0010-debugedit-Support-String-Line-table-rewriting-for-la.patch +++ /dev/null @@ -1,2105 +0,0 @@ -From 481a17c207809d10efcc87c1f831c5eef83c069f Mon Sep 17 00:00:00 2001 -Message-Id: <481a17c207809d10efcc87c1f831c5eef83c069f.1488964568.git.pmatilai@redhat.com> -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Fri, 17 Feb 2017 14:13:57 +0100 -Subject: [PATCH 10/11] debugedit: Support String/Line table rewriting for - larger/smaller paths. - -debugedit --base to --dest rewriting of debug source file paths only -supported dest paths that were smaller or equal than the base path -(and the size should differ more than 1 character for correct debug lines). -All paths were changed "in place". Which could in theory mess up debug str -sharing. - -This rewrite supports base and dest strings of any size (some limitations, -see below). This is done by reconstructing the debug_str and debug_line -tables and updating the references in the debug_info attributes pointing -to these tables. Plus, if necessary (only for ET_REL kernel modules), -updating any relocations for the debug_info and debug_line sections. - -This has the nice benefit of merging any duplicate strings in the -debug_str table which might resulting on slightly smaller files. -kernel modules are ET_REL files that often contain a lot of duplicate -strings. - -The rewrite uses elfutils (either libebl or libdw) to reconstruct the -debug_str table. Since we are changing some section sizes now we cannot -just use mmap and rawdata to poke the values, but need to read in and -write out the changed sections. This does take a bit more memory because -we now also need to keep track of all string/line references. - -There are still some limitations (already in the original debugedit) -not fixed by this rewrite: -- DW_AT_comp_dir in .debug_info using DW_FORM_string can not be made - larger. We only warn about that now instead of failing. The only - producer of DW_FORM_string comp_dirs is binutils gas. It seems simpler - to fix gas than to try to support resizing the debug_info section. -- A DW_AT_name on a DW_TAG_compile_unit is only rewritten for DW_FORM_strp - not for DW_FORM_string. Probably no problem in practice since this - wasn't supported originally either. -- The debug_line program isn't scanned for DW_LNE_define_file which - could in theory define an absolute path that might need rewriting. - Again probably not a problem because this wasn't supported before - and there are no know producers for this construct. - -To support the upcoming DWARFv5 in gcc 7 (not on by default), we will -need to add support for the new debug_line format and scan the new -debug_macro section that can have references to the debug_str table. - -Signed-off-by: Mark Wielaard ---- - Makefile.am | 8 +- - configure.ac | 6 + - tools/debugedit.c | 1569 ++++++++++++++++++++++++++++++++++++++++++++--------- - 3 files changed, 1330 insertions(+), 253 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 6b37b58..1b77730 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -156,13 +156,18 @@ rpm2archive_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ @WITH_ARCHIV - - if LIBELF - if LIBDWARF -+if LIBDW - rpmconfig_SCRIPTS += scripts/find-debuginfo.sh - - rpmlibexec_PROGRAMS += debugedit - debugedit_SOURCES = tools/debugedit.c tools/hashtab.c tools/hashtab.h - debugedit_LDADD = rpmio/librpmio.la - debugedit_LDADD += @WITH_LIBELF_LIB@ @WITH_POPT_LIB@ -- -+if HAVE_LIBDW_STRTAB -+debugedit_LDADD += @WITH_LIBDW_LIB@ -+else -+debugedit_LDADD += @WITH_LIBDW_LIB@ -lebl -+endif - rpmlibexec_PROGRAMS += elfdeps - elfdeps_SOURCES = tools/elfdeps.c - elfdeps_LDADD = rpmio/librpmio.la -@@ -173,6 +178,7 @@ sepdebugcrcfix_SOURCES = tools/sepdebugcrcfix.c - sepdebugcrcfix_LDADD = @WITH_LIBELF_LIB@ - endif - endif -+endif - - rpmlibexec_PROGRAMS += rpmdeps - rpmdeps_SOURCES = tools/rpmdeps.c -diff --git a/configure.ac b/configure.ac -index 4baa3f1..743fe08 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -369,18 +369,24 @@ AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) - #================= - # Check for elfutils libdw library with dwelf_elf_gnu_build_id. - WITH_LIBDW_LIB= -+HAVE_LIBDW_STRTAB= - AS_IF([test "$WITH_LIBELF" = yes],[ - AC_CHECK_HEADERS([elfutils/libdwelf.h],[ -+ # dwelf_elf_gnu_build_id was introduced in elfutils 0.159 - AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ - AC_DEFINE(HAVE_LIBDW, 1, - [Define to 1 if you have elfutils libdw library]) - WITH_LIBDW_LIB="-ldw" - WITH_LIBDW=yes -+ # If possible we also want the strtab functions from elfutils 0.167. -+ # But we can fall back on the (unsupported) ebl alternatives if not. -+ AC_CHECK_LIB(dw, dwelf_strtab_init, [HAVE_LIBDW_STRTAB=yes]) - ]) - ]) - ]) - AC_SUBST(WITH_LIBDW_LIB) - AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) -+AM_CONDITIONAL(HAVE_LIBDW_STRTAB,[test "$HAVE_LIBDW_STRTAB" = yes]) - - #================= - # Process --with/without-external-db -diff --git a/tools/debugedit.c b/tools/debugedit.c -index c0147f0..4798c63 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -1,6 +1,7 @@ --/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016 Red Hat, Inc. -+/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016, 2017 Red Hat, Inc. - Written by Alexander Larsson , 2002 - Based on code by Jakub Jelinek , 2001. -+ String/Line table rewriting by Mark Wielaard , 2017. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -@@ -30,6 +31,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -39,6 +41,35 @@ - #include - #include - -+/* Unfortunately strtab manipulation functions were only officially added -+ to elfutils libdw in 0.167. Before that there were internal unsupported -+ ebl variants. While libebl.h isn't supported we'll try to use it anyway -+ if the elfutils we build against is too old. */ -+#include -+#if _ELFUTILS_PREREQ (0, 167) -+#include -+typedef Dwelf_Strent Strent; -+typedef Dwelf_Strtab Strtab; -+#define strtab_init dwelf_strtab_init -+#define strtab_add(X,Y) dwelf_strtab_add(X,Y) -+#define strtab_add_len(X,Y,Z) dwelf_strtab_add_len(X,Y,Z) -+#define strtab_free dwelf_strtab_free -+#define strtab_finalize dwelf_strtab_finalize -+#define strent_offset dwelf_strent_off -+#else -+#include -+typedef struct Ebl_Strent Strent; -+typedef struct Ebl_Strtab Strtab; -+#define strtab_init ebl_strtabinit -+#define strtab_add(X,Y) ebl_strtabadd(X,Y,0) -+#define strtab_add_len(X,Y,Z) ebl_strtabadd(X,Y,Z) -+#define strtab_free ebl_strtabfree -+#define strtab_finalize ebl_strtabfinalize -+#define strent_offset ebl_strtaboffset -+#endif -+ -+#include -+ - #include - #include - #include "tools/hashtab.h" -@@ -56,6 +87,99 @@ int list_file_fd = -1; - int do_build_id = 0; - char *build_id_seed = NULL; - -+/* We go over the debug sections in two phases. In phase zero we keep -+ track of any needed changes and collect strings, indexes and -+ sizes. In phase one we do the actual replacements updating the -+ strings, indexes and writing out new debug sections. The following -+ keep track of various changes that might be needed. */ -+ -+/* Whether we need to do any literal string (DW_FORM_string) replacements -+ in debug_info. */ -+static bool need_string_replacement = false; -+/* Whether we need to do any updates of the string indexes (DW_FORM_strp) -+ in debug_info for string indexes. */ -+static bool need_strp_update = false; -+/* If the debug_line changes size we will need to update the -+ DW_AT_stmt_list attributes indexes in the debug_info. */ -+static bool need_stmt_update = false; -+ -+/* Storage for dynamically allocated strings to put into string -+ table. Keep together in memory blocks of 16K. */ -+#define STRMEMSIZE (16 * 1024) -+struct strmemblock -+{ -+ struct strmemblock *next; -+ char memory[0]; -+}; -+ -+/* We keep track of each index in the original string table and the -+ associated entry in the new table so we don't insert identical -+ strings into the new string table. If constructed correctly the -+ original strtab shouldn't contain duplicate strings anyway. Any -+ actual identical strings could be deduplicated, but searching for -+ and comparing the indexes is much faster than comparing strings -+ (and we don't have to construct replacement strings). */ -+struct stridxentry -+{ -+ uint32_t idx; /* Original index in the string table. */ -+ Strent *entry; /* Entry in the new table. */ -+}; -+ -+/* Storage for new string table entries. Keep together in memory to -+ quickly search through them with tsearch. */ -+#define STRIDXENTRIES ((16 * 1024) / sizeof (struct stridxentry)) -+struct strentblock -+{ -+ struct strentblock *next; -+ struct stridxentry entry[0]; -+}; -+ -+/* All data to keep track of the existing and new string table. */ -+struct strings -+{ -+ Strtab *str_tab; /* The new string table. */ -+ char *str_buf; /* New Elf_Data d_buf. */ -+ struct strmemblock *blocks; /* The first strmemblock. */ -+ struct strmemblock *last_block; /* The currently used strmemblock. */ -+ size_t stridx; /* Next free byte in last block. */ -+ struct strentblock *entries; /* The first string index block. */ -+ struct strentblock *last_entries; /* The currently used strentblock. */ -+ size_t entryidx; /* Next free entry in the last block. */ -+ void *strent_root; /* strent binary search tree root. */ -+}; -+ -+struct line_table -+{ -+ size_t old_idx; /* Original offset. */ -+ size_t new_idx; /* Offset in new debug_line section. */ -+ ssize_t size_diff; /* Difference in (header) size. */ -+ bool replace_dirs; /* Whether to replace any dir paths. */ -+ bool replace_files; /* Whether to replace any file paths. */ -+ -+ /* Header fields. */ -+ uint32_t unit_length; -+ uint16_t version; -+ uint32_t header_length; -+ uint8_t min_instr_len; -+ uint8_t max_op_per_instr; /* Only if version >= 4 */ -+ uint8_t default_is_stmt; -+ int8_t line_base; -+ uint8_t line_range; -+ uint8_t opcode_base; -+}; -+ -+struct debug_lines -+{ -+ struct line_table *table; /* Malloc/Realloced. */ -+ size_t size; /* Total number of line_tables. -+ Updated by get_line_table. */ -+ size_t used; /* Used number of line_tables. -+ Updated by get_line_table. */ -+ size_t debug_lines_len; /* Total size of new debug_line section. -+ updated by edit_dwarf2_line. */ -+ char *line_buf; /* New Elf_Data d_buf. */ -+}; -+ - typedef struct - { - Elf *elf; -@@ -63,15 +187,42 @@ typedef struct - Elf_Scn **scn; - const char *filename; - int lastscn; -+ size_t phnum; -+ struct strings strings; -+ struct debug_lines lines; - GElf_Shdr shdr[0]; - } DSO; - -+static void -+setup_lines (struct debug_lines *lines) -+{ -+ lines->table = NULL; -+ lines->size = 0; -+ lines->used = 0; -+ lines->debug_lines_len = 0; -+ lines->line_buf = NULL; -+} -+ -+static void -+destroy_lines (struct debug_lines *lines) -+{ -+ free (lines->table); -+ free (lines->line_buf); -+} -+ - typedef struct - { - unsigned char *ptr; - uint32_t addend; -+ int ndx; - } REL; - -+typedef struct -+{ -+ Elf64_Addr r_offset; -+ int ndx; -+} LINE_REL; -+ - #define read_uleb128(ptr) ({ \ - unsigned int ret = 0; \ - unsigned int c; \ -@@ -88,9 +239,23 @@ typedef struct - ret; \ - }) - -+#define write_uleb128(ptr,val) ({ \ -+ uint32_t valv = (val); \ -+ do \ -+ { \ -+ unsigned char c = valv & 0x7f; \ -+ valv >>= 7; \ -+ if (valv) \ -+ c |= 0x80; \ -+ *ptr++ = c; \ -+ } \ -+ while (valv); \ -+}) -+ - static uint16_t (*do_read_16) (unsigned char *ptr); - static uint32_t (*do_read_32) (unsigned char *ptr); --static void (*write_32) (unsigned char *ptr, GElf_Addr val); -+static void (*do_write_16) (unsigned char *ptr, uint16_t val); -+static void (*do_write_32) (unsigned char *ptr, uint32_t val); - - static int ptr_size; - static int cu_version; -@@ -129,7 +294,7 @@ strptr (DSO *dso, int sec, off_t offset) - if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size) - { - data = NULL; -- while ((data = elf_rawdata (scn, data)) != NULL) -+ while ((data = elf_getdata (scn, data)) != NULL) - { - if (data->d_buf - && offset >= data->d_off -@@ -142,7 +307,7 @@ strptr (DSO *dso, int sec, off_t offset) - } - - --#define read_1(ptr) *ptr++ -+#define read_8(ptr) *ptr++ - - #define read_16(ptr) ({ \ - uint16_t ret = do_read_16 (ptr); \ -@@ -183,28 +348,73 @@ int reltype; - }) - - static void --dwarf2_write_le32 (unsigned char *p, GElf_Addr val) -+dwarf2_write_le16 (unsigned char *p, uint16_t v) - { -- uint32_t v = (uint32_t) val; -+ p[0] = v; -+ p[1] = v >> 8; -+} - -+static void -+dwarf2_write_le32 (unsigned char *p, uint32_t v) -+{ - p[0] = v; - p[1] = v >> 8; - p[2] = v >> 16; - p[3] = v >> 24; - } - -- - static void --dwarf2_write_be32 (unsigned char *p, GElf_Addr val) -+dwarf2_write_be16 (unsigned char *p, uint16_t v) - { -- uint32_t v = (uint32_t) val; -+ p[1] = v; -+ p[0] = v >> 8; -+} - -+static void -+dwarf2_write_be32 (unsigned char *p, uint32_t v) -+{ - p[3] = v; - p[2] = v >> 8; - p[1] = v >> 16; - p[0] = v >> 24; - } - -+#define write_8(ptr,val) ({ \ -+ *ptr++ = (val); \ -+}) -+ -+#define write_16(ptr,val) ({ \ -+ do_write_16 (ptr,val); \ -+ ptr += 2; \ -+}) -+ -+#define write_32(ptr,val) ({ \ -+ do_write_32 (ptr,val); \ -+ ptr += 4; \ -+}) -+ -+/* relocated writes can only be called immediately after -+ do_read_32_relocated. ptr must be equal to relptr->ptr (or -+ relend). Might just update the addend. So relocations need to be -+ updated at the end. */ -+ -+#define do_write_32_relocated(ptr,val) ({ \ -+ if (relptr && relptr < relend && relptr->ptr == ptr) \ -+ { \ -+ if (reltype == SHT_REL) \ -+ do_write_32 (ptr, val - relptr->addend); \ -+ else \ -+ relptr->addend = val; \ -+ } \ -+ else \ -+ do_write_32 (ptr,val); \ -+}) -+ -+#define write_32_relocated(ptr,val) ({ \ -+ do_write_32_relocated (ptr,val); \ -+ ptr += 4; \ -+}) -+ - static struct - { - const char *name; -@@ -448,90 +658,638 @@ canonicalize_path (const char *s, char *d) - return rv; - } - -+/* Returns the rest of PATH if it starts with DIR_PREFIX, skipping any -+ / path separators, or NULL if PATH doesn't start with -+ DIR_PREFIX. Might return the empty string if PATH equals DIR_PREFIX -+ (modulo trailing slashes). Never returns path starting with '/'. */ -+static const char * -+skip_dir_prefix (const char *path, const char *dir_prefix) -+{ -+ size_t prefix_len = strlen (dir_prefix); -+ if (strncmp (path, dir_prefix, prefix_len) == 0) -+ { -+ path += prefix_len; -+ while (IS_DIR_SEPARATOR (path[0])) -+ path++; -+ return path; -+ } -+ -+ return 0; -+} -+ -+/* Most strings will be in the existing debug string table. But to -+ replace the base/dest directory prefix we need some new storage. -+ Keep new strings somewhat close together for faster comparison and -+ copying. SIZE should be at least one (and includes space for the -+ zero terminator). The returned pointer points to uninitialized -+ data. */ -+static char * -+new_string_storage (struct strings *strings, size_t size) -+{ -+ assert (size > 0); -+ -+ /* If the string is extra long just create a whole block for -+ it. Normally strings are much smaller than STRMEMSIZE. */ -+ if (strings->last_block == NULL -+ || size > STRMEMSIZE -+ || strings->stridx > STRMEMSIZE -+ || (STRMEMSIZE - strings->stridx) < size) -+ { -+ struct strmemblock *newblock = malloc (sizeof (struct strmemblock) -+ + MAX (STRMEMSIZE, size)); -+ if (newblock == NULL) -+ return NULL; -+ -+ newblock->next = NULL; -+ -+ if (strings->blocks == NULL) -+ strings->blocks = newblock; -+ -+ if (strings->last_block != NULL) -+ strings->last_block->next = newblock; -+ -+ strings->last_block = newblock; -+ strings->stridx = 0; -+ } -+ -+ size_t stridx = strings->stridx; -+ strings->stridx += size + 1; -+ return &strings->last_block->memory[stridx]; -+} -+ -+/* Comparison function used for tsearch. */ - static int --has_prefix (const char *str, -- const char *prefix) -+strent_compare (const void *a, const void *b) - { -- size_t str_len; -- size_t prefix_len; -+ struct stridxentry *entry_a = (struct stridxentry *)a; -+ struct stridxentry *entry_b = (struct stridxentry *)b; -+ size_t idx_a = entry_a->idx; -+ size_t idx_b = entry_b->idx; - -- str_len = strlen (str); -- prefix_len = strlen (prefix); -+ if (idx_a < idx_b) -+ return -1; - -- if (str_len < prefix_len) -- return 0; -+ if (idx_a > idx_b) -+ return 1; - -- return strncmp (str, prefix, prefix_len) == 0; -+ return 0; - } - --static int dirty_elf; -+/* Allocates and inserts a new entry for the old index if not yet -+ seen. Returns a stridxentry if the given index has not yet been -+ seen and needs to be filled in with the associated string (either -+ the original string or the replacement string). Returns NULL if the -+ idx is already known. Use in phase 0 to add all strings seen. In -+ phase 1 use string_find_entry instead to get existing entries. */ -+static struct stridxentry * -+string_find_new_entry (struct strings *strings, size_t old_idx) -+{ -+ /* Use next entry in the pool for lookup so we can use it directly -+ if this is a new index. */ -+ struct stridxentry *entry; -+ -+ /* Keep entries close together to make key comparison fast. */ -+ if (strings->last_entries == NULL || strings->entryidx >= STRIDXENTRIES) -+ { -+ size_t entriessz = (sizeof (struct strentblock) -+ + (STRIDXENTRIES * sizeof (struct stridxentry))); -+ struct strentblock *newentries = malloc (entriessz); -+ if (newentries == NULL) -+ error (1, errno, "Couldn't allocate new string entries block"); -+ else -+ { -+ if (strings->entries == NULL) -+ strings->entries = newentries; -+ -+ if (strings->last_entries != NULL) -+ strings->last_entries->next = newentries; -+ -+ strings->last_entries = newentries; -+ strings->last_entries->next = NULL; -+ strings->entryidx = 0; -+ } -+ } -+ -+ entry = &strings->last_entries->entry[strings->entryidx]; -+ entry->idx = old_idx; -+ struct stridxentry **tres = tsearch (entry, &strings->strent_root, -+ strent_compare); -+ if (tres == NULL) -+ error (1, ENOMEM, "Couldn't insert new strtab idx"); -+ else if (*tres == entry) -+ { -+ /* idx not yet seen, must add actual str. */ -+ strings->entryidx++; -+ return entry; -+ } -+ -+ return NULL; /* We already know about this idx, entry already complete. */ -+} -+ -+static struct stridxentry * -+string_find_entry (struct strings *strings, size_t old_idx) -+{ -+ struct stridxentry **ret; -+ struct stridxentry key; -+ key.idx = old_idx; -+ ret = tfind (&key, &strings->strent_root, strent_compare); -+ assert (ret != NULL); /* Can only happen for a bad/non-existing old_idx. */ -+ return *ret; -+} -+ -+/* Adds a string_idx_entry given an index into the old/existing string -+ table. Should be used in phase 0. Does nothing if the index was -+ already registered. Otherwise it checks the string associated with -+ the index. If the old string doesn't start with base_dir an entry -+ will be recorded for the index with the same string. Otherwise a -+ string will be recorded where the base_dir prefix will be replaced -+ by dest_dir. Returns true if this is a not yet seen index and there -+ a replacement file string has been recorded for it, otherwise -+ returns false. */ -+static bool -+record_file_string_entry_idx (struct strings *strings, size_t old_idx) -+{ -+ bool ret = false; -+ struct stridxentry *entry = string_find_new_entry (strings, old_idx); -+ if (entry != NULL) -+ { -+ Strent *strent; -+ const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx; -+ const char *file = skip_dir_prefix (old_str, base_dir); -+ if (file == NULL) -+ { -+ /* Just record the existing string. */ -+ strent = strtab_add_len (strings->str_tab, old_str, -+ strlen (old_str) + 1); -+ } -+ else -+ { -+ /* Create and record the altered file path. */ -+ size_t dest_len = strlen (dest_dir); -+ size_t file_len = strlen (file); -+ size_t nsize = dest_len + 1; /* + '\0' */ -+ if (file_len > 0) -+ nsize += 1 + file_len; /* + '/' */ -+ char *nname = new_string_storage (strings, nsize); -+ if (nname == NULL) -+ error (1, ENOMEM, "Couldn't allocate new string storage"); -+ memcpy (nname, dest_dir, dest_len); -+ if (file_len > 0) -+ { -+ nname[dest_len] = '/'; -+ memcpy (nname + dest_len + 1, file, file_len + 1); -+ } -+ else -+ nname[dest_len] = '\0'; -+ -+ strent = strtab_add_len (strings->str_tab, nname, nsize); -+ ret = true; -+ } -+ if (strent == NULL) -+ error (1, ENOMEM, "Could not create new string table entry"); -+ else -+ entry->entry = strent; -+ } -+ -+ return ret; -+} -+ -+/* Same as record_new_string_file_string_entry_idx but doesn't replace -+ base_dir with dest_dir, just records the existing string associated -+ with the index. */ - static void --dirty_section (unsigned int sec) -+record_existing_string_entry_idx (struct strings *strings, size_t old_idx) - { -- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); -- dirty_elf = 1; -+ struct stridxentry *entry = string_find_new_entry (strings, old_idx); -+ if (entry != NULL) -+ { -+ const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx; -+ Strent *strent = strtab_add_len (strings->str_tab, -+ str, strlen (str) + 1); -+ if (strent == NULL) -+ error (1, ENOMEM, "Could not create new string table entry"); -+ else -+ entry->entry = strent; -+ } - } - --static int --edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) -+static void -+setup_strings (struct strings *strings) - { -- unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir; -- unsigned char **dirt; -- unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size; -- unsigned char *endcu, *endprol; -- unsigned char opcode_base; -- uint32_t value, dirt_cnt; -- size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); -- size_t abs_file_cnt = 0, abs_dir_cnt = 0; -+ strings->str_tab = strtab_init (false); -+ strings->str_buf = NULL; -+ strings->blocks = NULL; -+ strings->last_block = NULL; -+ strings->entries = NULL; -+ strings->last_entries = NULL; -+ strings->strent_root = NULL; -+} - -- if (phase != 0) -- return 0; -+/* Noop for tdestroy. */ -+static void free_node (void *p __attribute__((__unused__))) { } - -- /* XXX: RhBug:929365, should we error out instead of ignoring? */ -+static void -+destroy_strings (struct strings *strings) -+{ -+ struct strmemblock *smb = strings->blocks; -+ while (smb != NULL) -+ { -+ void *old = smb; -+ smb = smb->next; -+ free (old); -+ } -+ -+ struct strentblock *emb = strings->entries; -+ while (emb != NULL) -+ { -+ void *old = emb; -+ emb = emb->next; -+ free (old); -+ } -+ -+ strtab_free (strings->str_tab); -+ tdestroy (strings->strent_root, &free_node); -+ free (strings->str_buf); -+} -+ -+/* The minimum number of line tables we pre-allocate. */ -+#define MIN_LINE_TABLES 64 -+ -+/* Gets a line_table at offset. Returns true if not yet know and -+ successfully read, false otherwise. Sets *table to NULL and -+ outputs a warning if there was a problem reading the table at the -+ given offset. */ -+static bool -+get_line_table (DSO *dso, size_t off, struct line_table **table) -+{ -+ struct debug_lines *lines = &dso->lines; -+ /* Assume there aren't that many, just do a linear search. The -+ array is probably already sorted because the stmt_lists are -+ probably inserted in order. But we cannot rely on that (maybe we -+ should check that to make searching quicker if possible?). Once -+ we have all line tables for phase 1 (rewriting) we do explicitly -+ sort the array.*/ -+ for (int i = 0; i < lines->used; i++) -+ if (lines->table[i].old_idx == off) -+ { -+ *table = &lines->table[i]; -+ return false; -+ } -+ -+ if (lines->size == lines->used) -+ { -+ struct line_table *new_table = realloc (lines->table, -+ (sizeof (struct line_table) -+ * (lines->size -+ + MIN_LINE_TABLES))); -+ if (new_table == NULL) -+ { -+ error (0, ENOMEM, "Couldn't add more debug_line tables"); -+ *table = NULL; -+ return false; -+ } -+ lines->table = new_table; -+ lines->size += MIN_LINE_TABLES; -+ } -+ -+ struct line_table *t = &lines->table[lines->used]; -+ *table = NULL; -+ -+ t->old_idx = off; -+ t->size_diff = 0; -+ t->replace_dirs = false; -+ t->replace_files = false; -+ -+ unsigned char *ptr = debug_sections[DEBUG_LINE].data; -+ unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size; - if (ptr == NULL) -- return 0; -+ { -+ error (0, 0, "%s: No .line_table section", dso->filename); -+ return false; -+ } - -+ if (off > debug_sections[DEBUG_LINE].size) -+ { -+ error (0, 0, "%s: Invalid .line_table offset 0x%zx", -+ dso->filename, off); -+ return false; -+ } - ptr += off; - -- endcu = ptr + 4; -- endcu += read_32 (ptr); -+ /* unit_length */ -+ unsigned char *endcu = ptr + 4; -+ t->unit_length = read_32 (ptr); -+ endcu += t->unit_length; - if (endcu == ptr + 0xffffffff) - { - error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); -- return 1; -+ return false; - } - - if (endcu > endsec) - { - error (0, 0, "%s: .debug_line CU does not fit into section", - dso->filename); -- return 1; -+ return false; - } - -- value = read_16 (ptr); -- if (value != 2 && value != 3 && value != 4) -+ /* version */ -+ t->version = read_16 (ptr); -+ if (t->version != 2 && t->version != 3 && t->version != 4) - { - error (0, 0, "%s: DWARF version %d unhandled", dso->filename, -- value); -- return 1; -+ t->version); -+ return false; - } - -- endprol = ptr + 4; -- endprol += read_32 (ptr); -+ /* header_length */ -+ unsigned char *endprol = ptr + 4; -+ t->header_length = read_32 (ptr); -+ endprol += t->header_length; - if (endprol > endcu) - { - error (0, 0, "%s: .debug_line CU prologue does not fit into CU", - dso->filename); -- return 1; -+ return false; -+ } -+ -+ /* min instr len */ -+ t->min_instr_len = *ptr++; -+ -+ /* max op per instr, if version >= 4 */ -+ if (t->version >= 4) -+ t->max_op_per_instr = *ptr++; -+ -+ /* default is stmt */ -+ t->default_is_stmt = *ptr++; -+ -+ /* line base */ -+ t->line_base = (*(int8_t *)ptr++); -+ -+ /* line range */ -+ t->line_range = *ptr++; -+ -+ /* opcode base */ -+ t->opcode_base = *ptr++; -+ -+ if (ptr + t->opcode_base - 1 >= endcu) -+ { -+ error (0, 0, "%s: .debug_line opcode table does not fit into CU", -+ dso->filename); -+ return false; - } -+ lines->used++; -+ *table = t; -+ return true; -+} - -- opcode_base = ptr[4 + (value >= 4)]; -- ptr = dir = ptr + 4 + (value >= 4) + opcode_base; -+static int dirty_elf; -+static void -+dirty_section (unsigned int sec) -+{ -+ elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); -+ dirty_elf = 1; -+} -+ -+static int -+line_table_cmp (const void *a, const void *b) -+{ -+ struct line_table *ta = (struct line_table *) a; -+ struct line_table *tb = (struct line_table *) b; -+ -+ if (ta->old_idx < tb->old_idx) -+ return -1; -+ -+ if (ta->old_idx > tb->old_idx) -+ return 1; -+ -+ return 0; -+} -+ -+ -+/* Called after phase zero (which records all adjustments needed for -+ the line tables referenced from debug_info) and before phase one -+ starts (phase one will adjust the .debug_line section stmt -+ references using the updated data structures). */ -+static void -+edit_dwarf2_line (DSO *dso) -+{ -+ Elf_Data *linedata = debug_sections[DEBUG_LINE].elf_data; -+ int linendx = debug_sections[DEBUG_LINE].sec; -+ Elf_Scn *linescn = dso->scn[linendx]; -+ unsigned char *old_buf = linedata->d_buf; -+ -+ /* Out with the old. */ -+ linedata->d_size = 0; -+ -+ /* In with the new. */ -+ linedata = elf_newdata (linescn); -+ -+ dso->lines.line_buf = malloc (dso->lines.debug_lines_len); -+ if (dso->lines.line_buf == NULL) -+ error (1, ENOMEM, "No memory for new .debug_line table (0x%zx bytes)", -+ dso->lines.debug_lines_len); -+ -+ linedata->d_size = dso->lines.debug_lines_len; -+ linedata->d_buf = dso->lines.line_buf; -+ debug_sections[DEBUG_LINE].size = linedata->d_size; -+ -+ /* Make sure the line tables are sorted on the old index. */ -+ qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table), -+ line_table_cmp); -+ -+ unsigned char *ptr = linedata->d_buf; -+ for (int ldx = 0; ldx < dso->lines.used; ldx++) -+ { -+ struct line_table *t = &dso->lines.table[ldx]; -+ unsigned char *optr = old_buf + t->old_idx; -+ t->new_idx = ptr - (unsigned char *) linedata->d_buf; -+ -+ /* Just copy the whole table if nothing needs replacing. */ -+ if (! t->replace_dirs && ! t->replace_files) -+ { -+ assert (t->size_diff == 0); -+ memcpy (ptr, optr, t->unit_length + 4); -+ ptr += t->unit_length + 4; -+ continue; -+ } -+ -+ /* Header fields. */ -+ write_32 (ptr, t->unit_length + t->size_diff); -+ write_16 (ptr, t->version); -+ write_32 (ptr, t->header_length + t->size_diff); -+ write_8 (ptr, t->min_instr_len); -+ if (t->version >= 4) -+ write_8 (ptr, t->max_op_per_instr); -+ write_8 (ptr, t->default_is_stmt); -+ write_8 (ptr, t->line_base); -+ write_8 (ptr, t->line_range); -+ write_8 (ptr, t->opcode_base); -+ -+ optr += (4 /* unit len */ -+ + 2 /* version */ -+ + 4 /* header len */ -+ + 1 /* min instr len */ -+ + (t->version >= 4) /* max op per instr, if version >= 4 */ -+ + 1 /* default is stmt */ -+ + 1 /* line base */ -+ + 1 /* line range */ -+ + 1); /* opcode base */ -+ -+ /* opcode len table. */ -+ memcpy (ptr, optr, t->opcode_base - 1); -+ optr += t->opcode_base - 1; -+ ptr += t->opcode_base - 1; -+ -+ /* directory table. We need to find the end (start of file -+ table) anyway, so loop over all dirs, even if replace_dirs is -+ false. */ -+ while (*optr != 0) -+ { -+ const char *dir = (const char *) optr; -+ const char *file_path = NULL; -+ if (t->replace_dirs) -+ { -+ file_path = skip_dir_prefix (dir, base_dir); -+ if (file_path != NULL) -+ { -+ size_t dest_len = strlen (dest_dir); -+ size_t file_len = strlen (file_path); -+ memcpy (ptr, dest_dir, dest_len); -+ ptr += dest_len; -+ if (file_len > 0) -+ { -+ *ptr++ = '/'; -+ memcpy (ptr, file_path, file_len); -+ ptr += file_len; -+ } -+ *ptr++ = '\0'; -+ } -+ } -+ if (file_path == NULL) -+ { -+ size_t dir_len = strlen (dir); -+ memcpy (ptr, dir, dir_len + 1); -+ ptr += dir_len + 1; -+ } -+ -+ optr = (unsigned char *) strchr (dir, 0) + 1; -+ } -+ optr++; -+ *ptr++ = '\0'; -+ -+ /* file table */ -+ if (t->replace_files) -+ { -+ while (*optr != 0) -+ { -+ const char *file = (const char *) optr; -+ const char *file_path = NULL; -+ if (t->replace_dirs) -+ { -+ file_path = skip_dir_prefix (file, base_dir); -+ if (file_path != NULL) -+ { -+ size_t dest_len = strlen (dest_dir); -+ size_t file_len = strlen (file_path); -+ memcpy (ptr, dest_dir, dest_len); -+ ptr += dest_len; -+ if (file_len > 0) -+ { -+ *ptr++ = '/'; -+ memcpy (ptr, file_path, file_len); -+ ptr += file_len; -+ } -+ *ptr++ = '\0'; -+ } -+ } -+ if (file_path == NULL) -+ { -+ size_t file_len = strlen (file); -+ memcpy (ptr, file, file_len + 1); -+ ptr += file_len + 1; -+ } -+ -+ optr = (unsigned char *) strchr (file, 0) + 1; -+ -+ /* dir idx, time, len */ -+ uint32_t dir_idx = read_uleb128 (optr); -+ write_uleb128 (ptr, dir_idx); -+ uint32_t time = read_uleb128 (optr); -+ write_uleb128 (ptr, time); -+ uint32_t len = read_uleb128 (optr); -+ write_uleb128 (ptr, len); -+ } -+ optr++; -+ *ptr++ = '\0'; -+ } -+ -+ /* line number program (and file table if not copied above). */ -+ size_t remaining = (t->unit_length + 4 -+ - (optr - (old_buf + t->old_idx))); -+ memcpy (ptr, optr, remaining); -+ ptr += remaining; -+ } -+} -+ -+/* Called during phase zero for each debug_line table referenced from -+ .debug_info. Outputs all source files seen and records any -+ adjustments needed in the debug_list data structures. Returns true -+ if line_table needs to be rewrite either the dir or file paths. */ -+static bool -+read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) -+{ -+ unsigned char *ptr, *dir; -+ unsigned char **dirt; -+ uint32_t value, dirt_cnt; -+ size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); -+ struct line_table *table; -+ -+ if (get_line_table (dso, off, &table) == false -+ || table == NULL) -+ { -+ if (table != NULL) -+ error (0, 0, ".debug_line offset 0x%x referenced multiple times", -+ off); -+ return false; -+ } -+ -+ /* Skip to the directory table. The rest of the header has already -+ been read and checked by get_line_table. */ -+ ptr = debug_sections[DEBUG_LINE].data + off; -+ ptr += (4 /* unit len */ -+ + 2 /* version */ -+ + 4 /* header len */ -+ + 1 /* min instr len */ -+ + (table->version >= 4) /* max op per instr, if version >= 4 */ -+ + 1 /* default is stmt */ -+ + 1 /* line base */ -+ + 1 /* line range */ -+ + 1 /* opcode base */ -+ + table->opcode_base - 1); /* opcode len table */ -+ dir = ptr; - - /* dir table: */ - value = 1; - while (*ptr != 0) - { -+ if (base_dir && dest_dir) -+ { -+ /* Do we need to replace any of the dirs? Calculate new size. */ -+ const char *file_path = skip_dir_prefix ((const char *)ptr, -+ base_dir); -+ if (file_path != NULL) -+ { -+ size_t old_size = strlen ((const char *)ptr) + 1; -+ size_t file_len = strlen (file_path); -+ size_t new_size = strlen (dest_dir) + 1; -+ if (file_len > 0) -+ new_size += 1 + file_len; -+ table->size_diff += (new_size - old_size); -+ table->replace_dirs = true; -+ } -+ } -+ - ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1; - ++value; - } -@@ -561,21 +1319,34 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) - { - error (0, 0, "%s: Wrong directory table index %u", - dso->filename, value); -- return 1; -+ return false; - } - file_len = strlen (file); -+ if (base_dir && dest_dir) -+ { -+ /* Do we need to replace any of the files? Calculate new size. */ -+ const char *file_path = skip_dir_prefix (file, base_dir); -+ if (file_path != NULL) -+ { -+ size_t old_size = file_len + 1; -+ size_t file_len = strlen (file_path); -+ size_t new_size = strlen (dest_dir) + 1; -+ if (file_len > 0) -+ new_size += 1 + file_len; -+ table->size_diff += (new_size - old_size); -+ table->replace_files = true; -+ } -+ } - dir_len = strlen ((char *)dirt[value]); - s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1); - if (s == NULL) - { - error (0, ENOMEM, "%s: Reading file table", dso->filename); -- return 1; -+ return false; - } - if (*file == '/') - { - memcpy (s, file, file_len + 1); -- if (dest_dir && has_prefix (file, base_dir)) -- ++abs_file_cnt; - } - else if (*dirt[value] == '/') - { -@@ -599,13 +1370,15 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) - canonicalize_path (s, s); - if (list_file_fd != -1) - { -- char *p = NULL; -+ const char *p = NULL; - if (base_dir == NULL) - p = s; -- else if (has_prefix (s, base_dir)) -- p = s + strlen (base_dir); -- else if (has_prefix (s, dest_dir)) -- p = s + strlen (dest_dir); -+ else -+ { -+ p = skip_dir_prefix (s, base_dir); -+ if (p == NULL && dest_dir != NULL) -+ p = skip_dir_prefix (s, dest_dir); -+ } - - if (p) - { -@@ -626,112 +1399,28 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) - read_uleb128 (ptr); - read_uleb128 (ptr); - } -- ++ptr; -- -- if (dest_dir) -- { -- unsigned char *srcptr, *buf = NULL; -- size_t base_len = strlen (base_dir); -- size_t dest_len = strlen (dest_dir); -- size_t shrank = 0; -- -- if (dest_len == base_len) -- abs_file_cnt = 0; -- if (abs_file_cnt) -- { -- srcptr = buf = malloc (ptr - dir); -- memcpy (srcptr, dir, ptr - dir); -- ptr = dir; -- } -- else -- ptr = srcptr = dir; -- while (*srcptr != 0) -- { -- size_t len = strlen ((char *)srcptr) + 1; -- const unsigned char *readptr = srcptr; -- -- char *orig = strdup ((const char *) srcptr); -- -- if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir)) -- { -- if (dest_len < base_len) -- ++abs_dir_cnt; -- memcpy (ptr, dest_dir, dest_len); -- ptr += dest_len; -- readptr += base_len; -- } -- srcptr += len; - -- shrank += srcptr - readptr; -- canonicalize_path ((char *)readptr, (char *)ptr); -- len = strlen ((char *)ptr) + 1; -- shrank -= len; -- ptr += len; -- -- if (memcmp (orig, ptr - len, len)) -- dirty_section (DEBUG_STR); -- free (orig); -- } -- -- if (shrank > 0) -- { -- if (--shrank == 0) -- error (EXIT_FAILURE, 0, -- "canonicalization unexpectedly shrank by one character"); -- else -- { -- memset (ptr, 'X', shrank); -- ptr += shrank; -- *ptr++ = '\0'; -- } -- } -- -- if (abs_dir_cnt + abs_file_cnt != 0) -- { -- size_t len = (abs_dir_cnt + abs_file_cnt) * (base_len - dest_len); -- -- if (len == 1) -- error (EXIT_FAILURE, 0, "-b arg has to be either the same length as -d arg, or more than 1 char longer"); -- memset (ptr, 'X', len - 1); -- ptr += len - 1; -- *ptr++ = '\0'; -- } -- *ptr++ = '\0'; -- ++srcptr; -- -- while (*srcptr != 0) -- { -- size_t len = strlen ((char *)srcptr) + 1; -+ dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff; -+ return table->replace_dirs || table->replace_files; -+} - -- if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir)) -- { -- memcpy (ptr, dest_dir, dest_len); -- if (dest_len < base_len) -- { -- memmove (ptr + dest_len, srcptr + base_len, -- len - base_len); -- ptr += dest_len - base_len; -- } -- dirty_section (DEBUG_STR); -- } -- else if (ptr != srcptr) -- memmove (ptr, srcptr, len); -- srcptr += len; -- ptr += len; -- dir = srcptr; -- read_uleb128 (srcptr); -- read_uleb128 (srcptr); -- read_uleb128 (srcptr); -- if (ptr != dir) -- memmove (ptr, dir, srcptr - dir); -- ptr += srcptr - dir; -- } -- *ptr = '\0'; -- free (buf); -- } -- return 0; -+/* Called during phase one, after the table has been sorted. */ -+static size_t -+find_new_list_offs (struct debug_lines *lines, size_t idx) -+{ -+ struct line_table key; -+ key.old_idx = idx; -+ struct line_table *table = bsearch (&key, lines->table, -+ lines->used, -+ sizeof (struct line_table), -+ line_table_cmp); -+ return table->new_idx; - } - -+/* This scans the attributes of one DIE described by the given abbrev_tag. -+ PTR points to the data in the debug_info. It will be advanced till all -+ abbrev data is consumed. In phase zero data is collected, in phase one -+ data might be replaced/updated. */ - static unsigned char * - edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - { -@@ -747,20 +1436,36 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - { - uint32_t form = t->attr[i].form; - size_t len = 0; -- size_t base_len, dest_len; -- - while (1) - { -+ /* Whether we already handled a string as file for this -+ attribute. If we did then we don't need to handle/record -+ it again when handling the DW_FORM_strp later. */ -+ bool handled_strp = false; -+ -+ /* A stmt_list points into the .debug_line section. In -+ phase zero record all offsets. Then in phase one replace -+ them with the new offsets if we rewrote the line -+ tables. */ - if (t->attr[i].attr == DW_AT_stmt_list) - { - if (form == DW_FORM_data4 - || form == DW_FORM_sec_offset) - { - list_offs = do_read_32_relocated (ptr); -- found_list_offs = 1; -+ if (phase == 0) -+ found_list_offs = 1; -+ else if (need_stmt_update) /* phase one */ -+ { -+ size_t idx, new_idx; -+ idx = do_read_32_relocated (ptr); -+ new_idx = find_new_list_offs (&dso->lines, idx); -+ do_write_32_relocated (ptr, new_idx); -+ } - } - } - -+ /* DW_AT_comp_dir is the current working directory. */ - if (t->attr[i].attr == DW_AT_comp_dir) - { - if (form == DW_FORM_string) -@@ -768,44 +1473,65 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - free (comp_dir); - comp_dir = strdup ((char *)ptr); - -- if (phase == 1 && dest_dir && has_prefix ((char *)ptr, base_dir)) -+ if (dest_dir) - { -- base_len = strlen (base_dir); -- dest_len = strlen (dest_dir); -- -- memcpy (ptr, dest_dir, dest_len); -- if (dest_len < base_len) -+ /* In phase zero we are just collecting dir/file -+ names and check whether any need to be -+ adjusted. If so, in phase one we replace -+ those dir/files. */ -+ const char *file = skip_dir_prefix (comp_dir, base_dir); -+ if (file != NULL && phase == 0) -+ need_string_replacement = true; -+ else if (file != NULL && phase == 1) - { -- memset(ptr + dest_len, '/', -- base_len - dest_len); -- -+ size_t orig_len = strlen (comp_dir); -+ size_t dest_len = strlen (dest_dir); -+ size_t file_len = strlen (file); -+ size_t new_len = dest_len; -+ if (file_len > 0) -+ new_len += 1 + file_len; /* + '/' */ -+ -+ /* We don't want to rewrite the whole -+ debug_info section, so we only replace -+ the comp_dir with something equal or -+ smaller, possibly adding some slashes -+ at the end of the new compdir. This -+ normally doesn't happen since most -+ producers will use DW_FORM_strp which is -+ more efficient. */ -+ if (orig_len < new_len) -+ fprintf (stderr, "Warning, not replacing comp_dir " -+ "'%s' prefix ('%s' -> '%s') encoded as " -+ "DW_FORM_string. " -+ "Replacement too large.\n", -+ comp_dir, base_dir, dest_dir); -+ else -+ { -+ /* Add one or more slashes in between to -+ fill up all space (replacement must be -+ of the same length). */ -+ memcpy (ptr, dest_dir, dest_len); -+ memset (ptr + dest_len, '/', -+ orig_len - new_len + 1); -+ } - } -- dirty_section (DEBUG_INFO); - } - } - else if (form == DW_FORM_strp && - debug_sections[DEBUG_STR].data) - { -- char *dir; -- -- dir = (char *) debug_sections[DEBUG_STR].data -- + do_read_32_relocated (ptr); -+ const char *dir; -+ size_t idx = do_read_32_relocated (ptr); -+ dir = (char *) debug_sections[DEBUG_STR].data + idx; - - free (comp_dir); - comp_dir = strdup (dir); - -- if (phase == 1 && dest_dir && has_prefix (dir, base_dir)) -+ if (dest_dir != NULL && phase == 0) - { -- base_len = strlen (base_dir); -- dest_len = strlen (dest_dir); -- -- memcpy (dir, dest_dir, dest_len); -- if (dest_len < base_len) -- { -- memmove (dir + dest_len, dir + base_len, -- strlen (dir + base_len) + 1); -- } -- dirty_section (DEBUG_STR); -+ if (record_file_string_entry_idx (&dso->strings, idx)) -+ need_strp_update = true; -+ handled_strp = true; - } - } - } -@@ -815,10 +1541,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - && form == DW_FORM_strp - && debug_sections[DEBUG_STR].data) - { -+ /* DW_AT_name is the primary file for this compile -+ unit. If starting with / it is a full path name. -+ Note that we don't handle DW_FORM_string in this -+ case. */ - char *name; -- -- name = (char *) debug_sections[DEBUG_STR].data -- + do_read_32_relocated (ptr); -+ size_t idx = do_read_32_relocated (ptr); -+ name = (char *) debug_sections[DEBUG_STR].data + idx; - if (*name == '/' && comp_dir == NULL) - { - char *enddir = strrchr (name, '/'); -@@ -833,18 +1562,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - comp_dir = strdup ("/"); - } - -- if (phase == 1 && dest_dir && has_prefix (name, base_dir)) -+ /* First pass (0) records the new name to be -+ added to the debug string pool, the second -+ pass (1) stores it (the new index). */ -+ if (dest_dir && phase == 0) - { -- base_len = strlen (base_dir); -- dest_len = strlen (dest_dir); -- -- memcpy (name, dest_dir, dest_len); -- if (dest_len < base_len) -- { -- memmove (name + dest_len, name + base_len, -- strlen (name + base_len) + 1); -- } -- dirty_section (DEBUG_STR); -+ if (record_file_string_entry_idx (&dso->strings, idx)) -+ need_strp_update = true; -+ handled_strp = true; - } - } - -@@ -886,6 +1611,29 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - read_uleb128 (ptr); - break; - case DW_FORM_strp: -+ /* In the first pass we collect all strings, in the -+ second we put the new references back (if there are -+ any changes). */ -+ if (phase == 0) -+ { -+ /* handled_strp is set for attributes refering to -+ files. If it is set the string is already -+ recorded. */ -+ if (! handled_strp) -+ { -+ size_t idx = do_read_32_relocated (ptr); -+ record_existing_string_entry_idx (&dso->strings, idx); -+ } -+ } -+ else if (need_strp_update) /* && phase == 1 */ -+ { -+ struct stridxentry *entry; -+ size_t idx, new_idx; -+ idx = do_read_32_relocated (ptr); -+ entry = string_find_entry (&dso->strings, idx); -+ new_idx = strent_offset (entry->entry); -+ do_write_32_relocated (ptr, new_idx); -+ } - ptr += 4; - break; - case DW_FORM_string: -@@ -930,14 +1678,17 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - CU current dir subdirectories. */ - if (comp_dir && list_file_fd != -1) - { -- char *p; -+ const char *p = NULL; - size_t size; - -- if (base_dir && has_prefix (comp_dir, base_dir)) -- p = comp_dir + strlen (base_dir); -- else if (dest_dir && has_prefix (comp_dir, dest_dir)) -- p = comp_dir + strlen (dest_dir); -- else -+ if (base_dir) -+ { -+ p = skip_dir_prefix (comp_dir, base_dir); -+ if (p == NULL && dest_dir != NULL) -+ p = skip_dir_prefix (comp_dir, dest_dir); -+ } -+ -+ if (p == NULL) - p = comp_dir; - - size = strlen (p) + 1; -@@ -951,8 +1702,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - } - } - -- if (found_list_offs) -- edit_dwarf2_line (dso, list_offs, comp_dir, phase); -+ /* In phase zero we collect all file names (we need the comp_dir for -+ that). Note that calculating the new size and offsets is done -+ separately (at the end of phase zero after all CUs have been -+ scanned in dwarf2_edit). */ -+ if (phase == 0 && found_list_offs -+ && read_dwarf2_line (dso, list_offs, comp_dir)) -+ need_stmt_update = true; - - free (comp_dir); - -@@ -974,6 +1730,20 @@ rel_cmp (const void *a, const void *b) - } - - static int -+line_rel_cmp (const void *a, const void *b) -+{ -+ LINE_REL *rela = (LINE_REL *) a, *relb = (LINE_REL *) b; -+ -+ if (rela->r_offset < relb->r_offset) -+ return -1; -+ -+ if (rela->r_offset > relb->r_offset) -+ return 1; -+ -+ return 0; -+} -+ -+static int - edit_dwarf2 (DSO *dso) - { - Elf_Data *data; -@@ -1009,9 +1779,9 @@ edit_dwarf2 (DSO *dso) - } - - scn = dso->scn[i]; -- data = elf_rawdata (scn, NULL); -+ data = elf_getdata (scn, NULL); - assert (data != NULL && data->d_buf != NULL); -- assert (elf_rawdata (scn, data) == NULL); -+ assert (elf_getdata (scn, data) == NULL); - assert (data->d_off == 0); - assert (data->d_size == dso->shdr[i].sh_size); - debug_sections[j].data = data->d_buf; -@@ -1050,13 +1820,15 @@ edit_dwarf2 (DSO *dso) - { - do_read_16 = buf_read_ule16; - do_read_32 = buf_read_ule32; -- write_32 = dwarf2_write_le32; -+ do_write_16 = dwarf2_write_le16; -+ do_write_32 = dwarf2_write_le32; - } - else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) - { - do_read_16 = buf_read_ube16; - do_read_32 = buf_read_ube32; -- write_32 = dwarf2_write_be32; -+ do_write_16 = dwarf2_write_be16; -+ do_write_32 = dwarf2_write_be32; - } - else - { -@@ -1179,6 +1951,7 @@ edit_dwarf2 (DSO *dso) - relend->ptr = debug_sections[DEBUG_INFO].data - + (rela.r_offset - base); - relend->addend = rela.r_addend; -+ relend->ndx = ndx; - ++relend; - } - if (relbuf == relend) -@@ -1193,6 +1966,13 @@ edit_dwarf2 (DSO *dso) - - for (phase = 0; phase < 2; phase++) - { -+ /* If we don't need to update anyhing, skip phase 1. */ -+ if (phase == 1 -+ && !need_strp_update -+ && !need_string_replacement -+ && !need_stmt_update) -+ break; -+ - ptr = debug_sections[DEBUG_INFO].data; - relptr = relbuf; - endsec = ptr + debug_sections[DEBUG_INFO].size; -@@ -1240,7 +2020,7 @@ edit_dwarf2 (DSO *dso) - - if (ptr_size == 0) - { -- ptr_size = read_1 (ptr); -+ ptr_size = read_8 (ptr); - if (ptr_size != 4 && ptr_size != 8) - { - error (0, 0, "%s: Invalid DWARF pointer size %d", -@@ -1248,7 +2028,7 @@ edit_dwarf2 (DSO *dso) - return 1; - } - } -- else if (read_1 (ptr) != ptr_size) -+ else if (read_8 (ptr) != ptr_size) - { - error (0, 0, "%s: DWARF pointer size differs between CUs", - dso->filename); -@@ -1281,7 +2061,185 @@ edit_dwarf2 (DSO *dso) - - htab_delete (abbrev); - } -+ -+ /* We might have to recalculate/rewrite the debug_line -+ section. We need to do that before going into phase one -+ so we have all new offsets. We do this separately from -+ scanning the dirs/file names because the DW_AT_stmt_lists -+ might not be in order or skip some padding we might have -+ to (re)move. */ -+ if (phase == 0 && need_stmt_update) -+ { -+ edit_dwarf2_line (dso); -+ -+ /* The line table programs will be moved -+ forward/backwards a bit in the new data. Update the -+ debug_line relocations to the new offsets. */ -+ int rndx = debug_sections[DEBUG_LINE].relsec; -+ if (rndx != 0) -+ { -+ LINE_REL *rbuf; -+ size_t rels; -+ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL); -+ int rtype = dso->shdr[rndx].sh_type; -+ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize; -+ rbuf = malloc (rels * sizeof (LINE_REL)); -+ if (rbuf == NULL) -+ error (1, errno, "%s: Could not allocate line relocations", -+ dso->filename); -+ -+ /* Sort them by offset into section. */ -+ for (size_t i = 0; i < rels; i++) -+ { -+ if (rtype == SHT_RELA) -+ { -+ GElf_Rela rela; -+ if (gelf_getrela (rdata, i, &rela) == NULL) -+ error (1, 0, "Couldn't get relocation: %s", -+ elf_errmsg (-1)); -+ rbuf[i].r_offset = rela.r_offset; -+ rbuf[i].ndx = i; -+ } -+ else -+ { -+ GElf_Rel rel; -+ if (gelf_getrel (rdata, i, &rel) == NULL) -+ error (1, 0, "Couldn't get relocation: %s", -+ elf_errmsg (-1)); -+ rbuf[i].r_offset = rel.r_offset; -+ rbuf[i].ndx = i; -+ } -+ } -+ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp); -+ -+ size_t lndx = 0; -+ for (size_t i = 0; i < rels; i++) -+ { -+ /* These relocations only happen in ET_REL files -+ and are section offsets. */ -+ GElf_Addr r_offset; -+ size_t ndx = rbuf[i].ndx; -+ -+ GElf_Rel rel; -+ GElf_Rela rela; -+ if (rtype == SHT_RELA) -+ { -+ if (gelf_getrela (rdata, ndx, &rela) == NULL) -+ error (1, 0, "Couldn't get relocation: %s", -+ elf_errmsg (-1)); -+ r_offset = rela.r_offset; -+ } -+ else -+ { -+ if (gelf_getrel (rdata, ndx, &rel) == NULL) -+ error (1, 0, "Couldn't get relocation: %s", -+ elf_errmsg (-1)); -+ r_offset = rel.r_offset; -+ } -+ -+ while (r_offset > (dso->lines.table[lndx].old_idx -+ + 4 -+ + dso->lines.table[lndx].unit_length) -+ && lndx < dso->lines.used) -+ lndx++; -+ -+ if (lndx >= dso->lines.used) -+ error (1, 0, -+ ".debug_line relocation offset out of range"); -+ -+ /* Offset (pointing into the line program) moves -+ from old to new index including the header -+ size diff. */ -+ r_offset += ((dso->lines.table[lndx].new_idx -+ - dso->lines.table[lndx].old_idx) -+ + dso->lines.table[lndx].size_diff); -+ -+ if (rtype == SHT_RELA) -+ { -+ rela.r_offset = r_offset; -+ if (gelf_update_rela (rdata, ndx, &rela) == 0) -+ error (1, 0, "Couldn't update relocation: %s", -+ elf_errmsg (-1)); -+ } -+ else -+ { -+ rel.r_offset = r_offset; -+ if (gelf_update_rel (rdata, ndx, &rel) == 0) -+ error (1, 0, "Couldn't update relocation: %s", -+ elf_errmsg (-1)); -+ } -+ } -+ -+ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY); -+ free (rbuf); -+ } -+ } -+ -+ /* Same for the debug_str section. Make sure everything is -+ in place for phase 1 updating of debug_info -+ references. */ -+ if (phase == 0 && need_strp_update) -+ { -+ Strtab *strtab = dso->strings.str_tab; -+ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; -+ int strndx = debug_sections[DEBUG_STR].sec; -+ Elf_Scn *strscn = dso->scn[strndx]; -+ -+ /* Out with the old. */ -+ strdata->d_size = 0; -+ /* In with the new. */ -+ strdata = elf_newdata (strscn); -+ -+ /* We really should check whether we had enough memory, -+ but the old ebl version will just abort on out of -+ memory... */ -+ strtab_finalize (strtab, strdata); -+ debug_sections[DEBUG_STR].size = strdata->d_size; -+ dso->strings.str_buf = strdata->d_buf; -+ } -+ -+ } -+ -+ /* After phase 1 we might have rewritten the debug_info with -+ new strp, strings and/or linep offsets. */ -+ if (need_strp_update || need_string_replacement || need_stmt_update) -+ dirty_section (DEBUG_INFO); -+ -+ /* Update any debug_info relocations addends we might have touched. */ -+ if (relbuf != NULL && reltype == SHT_RELA) -+ { -+ Elf_Data *symdata; -+ int relsec_ndx = debug_sections[DEBUG_INFO].relsec; -+ data = elf_getdata (dso->scn[relsec_ndx], NULL); -+ symdata = elf_getdata (dso->scn[dso->shdr[relsec_ndx].sh_link], -+ NULL); -+ -+ relptr = relbuf; -+ while (relptr < relend) -+ { -+ GElf_Sym sym; -+ GElf_Rela rela; -+ int ndx = relptr->ndx; -+ -+ if (gelf_getrela (data, ndx, &rela) == NULL) -+ error (1, 0, "Couldn't get relocation: %s", -+ elf_errmsg (-1)); -+ -+ if (gelf_getsym (symdata, GELF_R_SYM (rela.r_info), -+ &sym) == NULL) -+ error (1, 0, "Couldn't get symbol: %s", elf_errmsg (-1)); -+ -+ rela.r_addend = relptr->addend - sym.st_value; -+ -+ if (gelf_update_rela (data, ndx, &rela) == 0) -+ error (1, 0, "Couldn't update relocations: %s", -+ elf_errmsg (-1)); -+ -+ ++relptr; -+ } -+ elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); - } -+ - free (relbuf); - } - -@@ -1310,8 +2268,9 @@ fdopen_dso (int fd, const char *name) - GElf_Ehdr ehdr; - int i; - DSO *dso = NULL; -+ size_t phnum; - -- elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL); -+ elf = elf_begin (fd, ELF_C_RDWR, NULL); - if (elf == NULL) - { - error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1)); -@@ -1348,10 +2307,20 @@ fdopen_dso (int fd, const char *name) - goto error_out; - } - -- elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT); -+ if (elf_getphdrnum (elf, &phnum) != 0) -+ { -+ error (0, 0, "Couldn't get number of phdrs: %s", elf_errmsg (-1)); -+ goto error_out; -+ } -+ -+ /* If there are phdrs we want to maintain the layout of the -+ allocated sections in the file. */ -+ if (phnum != 0) -+ elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT); - - memset (dso, 0, sizeof(DSO)); - dso->elf = elf; -+ dso->phnum = phnum; - dso->ehdr = ehdr; - dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20]; - -@@ -1362,12 +2331,16 @@ fdopen_dso (int fd, const char *name) - } - - dso->filename = (const char *) strdup (name); -+ setup_strings (&dso->strings); -+ setup_lines (&dso->lines); - return dso; - - error_out: - if (dso) - { - free ((char *) dso->filename); -+ destroy_strings (&dso->strings); -+ destroy_lines (&dso->lines); - free (dso); - } - if (elf) -@@ -1406,13 +2379,6 @@ handle_build_id (DSO *dso, Elf_Data *build_id, - if (!dirty_elf && build_id_seed == NULL) - goto print; - -- if (elf_update (dso->elf, ELF_C_NULL) < 0) -- { -- fprintf (stderr, "Failed to update file: %s\n", -- elf_errmsg (elf_errno ())); -- exit (1); -- } -- - /* Clear the old bits so they do not affect the new hash. */ - memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size); - -@@ -1475,7 +2441,7 @@ handle_build_id (DSO *dso, Elf_Data *build_id, - - if (u.shdr.sh_type != SHT_NOBITS) - { -- Elf_Data *d = elf_rawdata (dso->scn[i], NULL); -+ Elf_Data *d = elf_getdata (dso->scn[i], NULL); - if (d == NULL) - goto bad; - rpmDigestUpdate(ctx, d->d_buf, d->d_size); -@@ -1509,7 +2475,6 @@ main (int argc, char *argv[]) - int nextopt; - const char **args; - struct stat stat_buf; -- char *p; - Elf_Data *build_id = NULL; - size_t build_id_offset = 0, build_id_size = 0; - -@@ -1541,11 +2506,6 @@ main (int argc, char *argv[]) - fprintf (stderr, "You must specify a base dir if you specify a dest dir\n"); - exit (1); - } -- if (strlen (dest_dir) > strlen (base_dir)) -- { -- fprintf (stderr, "Dest dir longer than base dir is not supported\n"); -- exit (1); -- } - } - - if (build_id_seed != NULL && do_build_id == 0) -@@ -1561,30 +2521,13 @@ main (int argc, char *argv[]) - exit (1); - } - -- /* Ensure clean paths, users can muck with these */ -+ /* Ensure clean paths, users can muck with these. Also removes any -+ trailing '/' from the paths. */ - if (base_dir) - canonicalize_path(base_dir, base_dir); - if (dest_dir) - canonicalize_path(dest_dir, dest_dir); - -- /* Make sure there are trailing slashes in dirs */ -- if (base_dir != NULL && base_dir[strlen (base_dir)-1] != '/') -- { -- p = malloc (strlen (base_dir) + 2); -- strcpy (p, base_dir); -- strcat (p, "/"); -- free (base_dir); -- base_dir = p; -- } -- if (dest_dir != NULL && dest_dir[strlen (dest_dir)-1] != '/') -- { -- p = malloc (strlen (dest_dir) + 2); -- strcpy (p, dest_dir); -- strcat (p, "/"); -- free (dest_dir); -- dest_dir = p; -- } -- - if (list_file != NULL) - { - list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644); -@@ -1641,7 +2584,7 @@ main (int argc, char *argv[]) - && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC)) - { - /* Look for a build-ID note here. */ -- Elf_Data *data = elf_rawdata (elf_getscn (dso->elf, i), NULL); -+ Elf_Data *data = elf_getdata (elf_getscn (dso->elf, i), NULL); - Elf32_Nhdr nh; - Elf_Data dst = - { -@@ -1679,6 +2622,123 @@ main (int argc, char *argv[]) - } - } - -+ /* We might have changed the size of some debug sections. If so make -+ sure the section headers are updated and the data offsets are -+ correct. We set ELF_F_LAYOUT above because we don't want libelf -+ to move any allocated sections around itself if there are any -+ phdrs. Which means we are reponsible for setting the section size -+ and offset fields. Plus the shdr offsets. We don't want to change -+ anything for the phdrs allocated sections. Keep the offset of -+ allocated sections so they are at the same place in the file. Add -+ unallocated ones after the allocated ones. */ -+ if (dso->phnum != 0 && (need_strp_update || need_stmt_update)) -+ { -+ Elf *elf = dso->elf; -+ GElf_Off last_offset; -+ /* We position everything after the phdrs (which normally would -+ be at the start of the ELF file after the ELF header. */ -+ last_offset = (dso->ehdr.e_phoff + gelf_fsize (elf, ELF_T_PHDR, -+ dso->phnum, EV_CURRENT)); -+ -+ /* First find the last allocated section. */ -+ Elf_Scn *scn = NULL; -+ while ((scn = elf_nextscn (elf, scn)) != NULL) -+ { -+ GElf_Shdr shdr_mem; -+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); -+ if (shdr == NULL) -+ error (1, 0, "Couldn't get shdr: %s\n", elf_errmsg (-1)); -+ -+ /* Any sections we have changed aren't allocated sections, -+ so we don't need to lookup any changed section sizes. */ -+ if ((shdr->sh_flags & SHF_ALLOC) != 0) -+ { -+ GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS -+ ? shdr->sh_size : 0); -+ if (last_offset < off) -+ last_offset = off; -+ } -+ } -+ -+ /* Now adjust any sizes and offsets for the unallocated sections. */ -+ scn = NULL; -+ while ((scn = elf_nextscn (elf, scn)) != NULL) -+ { -+ GElf_Shdr shdr_mem; -+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); -+ if (shdr == NULL) -+ error (1, 0, "Couldn't get shdr: %s\n", elf_errmsg (-1)); -+ -+ /* A bug in elfutils before 0.169 means we have to write out -+ all section data, even when nothing changed. -+ https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ -+#if !_ELFUTILS_PREREQ (0, 169) -+ if (shdr->sh_type != SHT_NOBITS) -+ { -+ Elf_Data *d = elf_getdata (scn, NULL); -+ elf_flagdata (d, ELF_C_SET, ELF_F_DIRTY); -+ } -+#endif -+ if ((shdr->sh_flags & SHF_ALLOC) == 0) -+ { -+ GElf_Off sec_offset = shdr->sh_offset; -+ GElf_Xword sec_size = shdr->sh_size; -+ -+ /* We might have changed the size (and content) of the -+ debug_str or debug_line section. */ -+ size_t secnum = elf_ndxscn (scn); -+ if (secnum == debug_sections[DEBUG_STR].sec) -+ sec_size = debug_sections[DEBUG_STR].size; -+ if (secnum == debug_sections[DEBUG_LINE].sec) -+ sec_size = debug_sections[DEBUG_LINE].size; -+ -+ /* Zero means one. No alignment constraints. */ -+ size_t addralign = shdr->sh_addralign ?: 1; -+ last_offset = (last_offset + addralign - 1) & ~(addralign - 1); -+ sec_offset = last_offset; -+ if (shdr->sh_type != SHT_NOBITS) -+ last_offset += sec_size; -+ -+ if (shdr->sh_size != sec_size -+ || shdr->sh_offset != sec_offset) -+ { -+ /* Make sure unchanged section data is written out -+ at the new location. */ -+ if (shdr->sh_offset != sec_offset -+ && shdr->sh_type != SHT_NOBITS) -+ { -+ Elf_Data *d = elf_getdata (scn, NULL); -+ elf_flagdata (d, ELF_C_SET, ELF_F_DIRTY); -+ } -+ -+ shdr->sh_size = sec_size; -+ shdr->sh_offset = sec_offset; -+ if (gelf_update_shdr (scn, shdr) == 0) -+ error (1, 0, "Couldn't update shdr: %s\n", -+ elf_errmsg (-1)); -+ } -+ } -+ } -+ -+ /* Position the shdrs after the last (unallocated) section. */ -+ const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT); -+ GElf_Off new_offset = ((last_offset + offsize - 1) -+ & ~((GElf_Off) (offsize - 1))); -+ if (dso->ehdr.e_shoff != new_offset) -+ { -+ dso->ehdr.e_shoff = new_offset; -+ if (gelf_update_ehdr (elf, &dso->ehdr) == 0) -+ error (1, 0, "Couldn't update ehdr: %s\n", elf_errmsg (-1)); -+ } -+ } -+ -+ if (elf_update (dso->elf, ELF_C_NULL) < 0) -+ { -+ fprintf (stderr, "Failed to update file: %s\n", -+ elf_errmsg (elf_errno ())); -+ exit (1); -+ } -+ - if (do_build_id && build_id != NULL) - handle_build_id (dso, build_id, build_id_offset, build_id_size); - -@@ -1697,6 +2757,11 @@ main (int argc, char *argv[]) - /* Restore old access rights */ - chmod (file, stat_buf.st_mode); - -+ free ((char *) dso->filename); -+ destroy_strings (&dso->strings); -+ destroy_lines (&dso->lines); -+ free (dso); -+ - poptFreeContext (optCon); - - return 0; --- -2.9.3 - diff --git a/0011-Add-option-to-have-unique-debug-source-dirs-across-v.patch b/0011-Add-option-to-have-unique-debug-source-dirs-across-v.patch deleted file mode 100644 index df328a5..0000000 --- a/0011-Add-option-to-have-unique-debug-source-dirs-across-v.patch +++ /dev/null @@ -1,290 +0,0 @@ -From cf12c3f2c985fcaf94bb5e2b24178290f5ef09ed Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -References: <189b4f88c8e100155ec23a1e0b214bdc8473532a.1488964568.git.pmatilai@redhat.com> -From: Mark Wielaard -Date: Tue, 28 Feb 2017 20:45:24 +0100 -Subject: [PATCH 11/11] Add option to have unique debug source dirs across - version/release/arch. - -Introduce a new macro _unique_debug_srcs that when set will pass ---unique-debug-src-base "%{name}" to find-debuginfo.sh which will -move sources into a unique "--." directory -under /usr/src/debug/ and makes debugedit rewrite the source paths -in the debuginfo to use that unique directory name. - -Traditionally the debug src dir was named after the builddir which -was defined through the %setup macro which used the -n name argument -to define the builddir name and source archive to use. The builddir -might not be unique though between package versions. - -Now that debugedit doesn't have strict base and dest dir length -restrictions for rewriting the source dir paths this can now be made -more flexible. - -The added testcases show the difference between the old and new way. -The hello2.spec file defines the name of the package as hello2, but -uses the %setup marcro with -n hello-1.0 to use the hello-1.0.tar.gz -archive. This would traditionally result in a hello-1.0 builddir -which would be moved under /usr/src/debug. Possibly conflicting -with any other package (version) that used the same builddir name. -When defining _unique_debug_srcs to 1 that builddir will be moved -to --. instead (hello2-1.0-1.). - -The testcases check that both the actual package source filess under -/usr/debug/src/ and the source paths as found in the .debug files are -under the traditional or new unique directory names depending on whether -the new _unique_debug_srcs macro is defined. - -Signed-off-by: Mark Wielaard ---- - macros.in | 8 ++++- - scripts/find-debuginfo.sh | 35 ++++++++++++++++++--- - tests/rpmbuild.at | 80 +++++++++++++++++++++++++++++++++++++++++++++++ - tests/rpmbuildid.at | 5 +++ - 4 files changed, 123 insertions(+), 5 deletions(-) - -diff --git a/macros.in b/macros.in -index 4d90282..e48ef60 100644 ---- a/macros.in -+++ b/macros.in -@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ - %{nil} - - # Template for debug information sub-package. -@@ -495,6 +495,12 @@ package or when debugging this package.\ - # Requires _unique_build_ids. - %_unique_debug_names 1 - -+# Whether the /usr/debug/src/ directories should be unique between -+# package version, release and architecture. If set to 1 this will pass -+# --unique-debug-src-base "%{name}" to find-debuginfo.sh to name the -+# directory under /usr/debug/src as --. -+%_unique_debug_srcs 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 3653c48..1420ef6 100644 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -67,6 +67,9 @@ ver_rel= - # Arch given by --unique-debug-arch - unique_debug_arch= - -+# Base given by --unique-debug-src-base -+unique_debug_src_base= -+ - BUILDDIR=. - out=debugfiles.list - nout=0 -@@ -94,6 +97,10 @@ while [ $# -gt 0 ]; do - unique_debug_arch=$2 - shift - ;; -+ --unique-debug-src-base) -+ unique_debug_src_base=$2 -+ shift -+ ;; - -g) - strip_g=true - ;; -@@ -137,6 +144,11 @@ if test -z "$ver_rel" -a -n "$unique_debug_arch"; then - exit 2 - fi - -+if test -z "$unique_debug_arch" -a -n "$unique_debug_src_base"; then -+ echo >&2 "*** ERROR: --unique-debug-src-base (${unique_debug_src_base}) needs --unique-debug-arch (${unique_debug_arch})" -+ exit 2 -+fi -+ - i=0 - while ((i < nout)); do - outs[$i]="$BUILDDIR/${outs[$i]}" -@@ -291,7 +303,14 @@ while read nlinks inum f; do - 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 \ -+ # See also cpio SOURCEFILE copy. Directories must match up. -+ debug_base_name="$RPM_BUILD_DIR" -+ debug_dest_name="/usr/src/debug" -+ if [ ! -z "$unique_debug_src_base" ]; then -+ debug_base_name="$BUILDDIR" -+ debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" -+ fi -+ id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ - -i $build_id_seed -l "$SOURCEFILE" "$f") || exit - if [ $nlinks -gt 1 ]; then - eval linkedid_$inum=\$id -@@ -388,11 +407,19 @@ do - done - - if [ -s "$SOURCEFILE" ]; then -- mkdir -p "${RPM_BUILD_ROOT}/usr/src/debug" -+ # See also debugedit invocation. Directories must match up. -+ debug_base_name="$RPM_BUILD_DIR" -+ debug_dest_name="/usr/src/debug" -+ if [ ! -z "$unique_debug_src_base" ]; then -+ debug_base_name="$BUILDDIR" -+ debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" -+ fi -+ -+ mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" - LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(|)$' | -- (cd "$RPM_BUILD_DIR"; cpio -pd0mL "${RPM_BUILD_ROOT}/usr/src/debug") -+ (cd "${debug_base_name}"; cpio -pd0mL "${RPM_BUILD_ROOT}${debug_dest_name}") - # stupid cpio creates new directories in mode 0700, fixup -- find "${RPM_BUILD_ROOT}/usr/src/debug" -type d -print0 | -+ find "${RPM_BUILD_ROOT}${debug_dest_name}" -type d -print0 | - xargs --no-run-if-empty -0 chmod a+rx - fi - -diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at -index 0a2c01e..a46822f 100644 ---- a/tests/rpmbuild.at -+++ b/tests/rpmbuild.at -@@ -399,6 +399,7 @@ 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_debug_names" \ -+ --undefine "_unique_debug_srcs" \ - -ba "${abs_srcdir}"/data/SPECS/hello2.spec - - # The debuginfo package should contain a .debug file for each binary -@@ -701,3 +702,82 @@ readelf -S ./usr/lib/debug/usr/local/bin/hello2*.debug \ - [], - [ignore]) - AT_CLEANUP -+ -+# ------------------------------ -+# Check that a debug source is in a "unique" directory when requested. -+AT_SETUP([rpmbuild debuginfo unique debug src dir]) -+AT_KEYWORDS([build] [debuginfo]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Build a package that has some debuginfo -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Note that the spec defines hello2 as name, but the source is hello-1.0. -+# Disable dwz to make debuginfo path rewrite checking easier. -+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 "_find_debuginfo_dwz_opts" \ -+ --define "_unique_debug_srcs 1" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2.spec -+ -+# Unpack the debuginfo rpms so we can check the .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# Check that the source path is "unique" -+# Drop the final arch prefix to make the test arch-independent. -+ls ./usr/src/debug/ | cut -f1,2 -d\. -+ -+# Check that the source path has been rewritten in the .debug file. -+# Drop the final arch prefix to make the test arch-independent. -+readelf --debug-dump=info ./usr/lib/debug/usr/local/bin/hello2*.debug \ -+ | grep comp_dir | cut -f5- -d/ | cut -f1,2 -d\. -+], -+[0], -+[hello2-1.0-1 -+hello2-1.0-1 -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ -+# Check that a debug source is NOT in a "unique" directory when not requested. -+# It will be in the "build directory" name under /usr/src/debug. -+AT_SETUP([rpmbuild debuginfo no unique debug src dir]) -+AT_KEYWORDS([build] [debuginfo]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Build a package that has some debuginfo -+cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES -+ -+# Note that the spec defines hello2 as name, but the source is hello-1.0. -+# Disable dwz to make debuginfo path rewrite checking easier. -+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 "_find_debuginfo_dwz_opts" \ -+ --undefine "_unique_debug_srcs" \ -+ -ba "${abs_srcdir}"/data/SPECS/hello2.spec -+ -+# Unpack the debuginfo rpms so we can check the .debug files. -+rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ -+ | cpio -diu --quiet -+ -+# Check that the source path is "unique" -+ls ./usr/src/debug/ -+ -+# Check that the source path has been rewritten in the .debug file. -+readelf --debug-dump=info ./usr/lib/debug/usr/local/bin/hello2*.debug \ -+ | grep comp_dir | cut -f5- -d/ -+], -+[0], -+[hello-1.0 -+hello-1.0 -+], -+[ignore]) -+AT_CLEANUP -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -index ede1181..15c0620 100644 ---- a/tests/rpmbuildid.at -+++ b/tests/rpmbuildid.at -@@ -71,6 +71,7 @@ run rpmbuild \ - --rcfile=${abs_top_builddir}/rpmrc \ - --define="_build_id_links alldebug" \ - --undefine "_unique_debug_names" \ -+ --undefine "_unique_debug_srcs" \ - --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec - - # There should be zero build-id files in the main package -@@ -257,6 +258,7 @@ run rpmbuild \ - --rcfile=${abs_top_builddir}/rpmrc \ - --define="_build_id_links separate" \ - --undefine "_unique_debug_names" \ -+ --undefine "_unique_debug_srcs" \ - --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec - - # There should be one build-id files in the main and debuginfo package -@@ -441,6 +443,7 @@ run rpmbuild \ - --rcfile=${abs_top_builddir}/rpmrc \ - --define="_build_id_links compat" \ - --undefine "_unique_debug_names" \ -+ --undefine "_unique_debug_srcs" \ - --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec - - # There should be one build-id files in the main and debuginfo package. -@@ -1125,6 +1128,7 @@ run rpmbuild --quiet \ - --rcfile=${abs_top_builddir}/rpmrc \ - --undefine="_unique_build_ids" \ - --undefine="_unique_debug_names" \ -+ --undefine="_unique_debug_srcs" \ - -ba "${abs_srcdir}"/data/SPECS/hello.spec - - rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ -@@ -1145,6 +1149,7 @@ run rpmbuild --quiet \ - --rcfile=${abs_top_builddir}/rpmrc \ - --undefine="_unique_build_ids" \ - --undefine="_unique_debug_names" \ -+ --undefine="_unique_debug_srcs" \ - -ba "${abs_srcdir}"/data/SPECS/hello-r2.spec - - rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ --- -2.9.3 - diff --git a/0011-configure.ac-use-LIBDW-always-conditionally.patch b/0011-configure.ac-use-LIBDW-always-conditionally.patch new file mode 100644 index 0000000..12bf77b --- /dev/null +++ b/0011-configure.ac-use-LIBDW-always-conditionally.patch @@ -0,0 +1,43 @@ +From 1b34b839b788264ffcd3ab90a0612cad3b843f7f Mon Sep 17 00:00:00 2001 +From: Igor Gnatenko +Date: Wed, 10 Aug 2016 13:58:30 +0200 +Subject: [PATCH 11/49] configure.ac: use LIBDW always conditionally + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1365278 +Reported-and-tested-by: Neal Gompa +Signed-off-by: Igor Gnatenko + +(cherry picked from commit a82119bf352400ee891105820b804bf946d5c6ee) +--- + configure.ac | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 8890c3c32..33c8f344f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -361,7 +361,8 @@ AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) + + #================= + # Check for elfutils libdw library with dwelf_elf_gnu_build_id. +-AS_IF([test "$WITH_LIBELF" = yes],[ ++WITH_LIBDW_LIB= ++AS_IF([test "$WITH_LIBELF" != yes],[ + AC_CHECK_HEADERS([elfutils/libdwelf.h],[ + AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ + AC_DEFINE(HAVE_LIBDW, 1, +@@ -370,9 +371,9 @@ AS_IF([test "$WITH_LIBELF" = yes],[ + WITH_LIBDW=yes + ]) + ]) +- AC_SUBST(WITH_LIBDW_LIB) +- AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) + ]) ++AC_SUBST(WITH_LIBDW_LIB) ++AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) + + #================= + # Process --with/without-external-db +-- +2.13.2 + diff --git a/0012-Fix-libdw-configure-check.patch b/0012-Fix-libdw-configure-check.patch new file mode 100644 index 0000000..3dd3bf9 --- /dev/null +++ b/0012-Fix-libdw-configure-check.patch @@ -0,0 +1,31 @@ +From f41a0a8c6839e3962e10a7bd3aad39127a764748 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 24 Aug 2016 17:06:34 +0200 +Subject: [PATCH 12/49] Fix libdw configure check. + +commit a82119 "configure.ac: use LIBDW always conditionally" contained +a typo that caused WITH_LIBDW_LIB never to be set when you were using +libelf. Fixed by reverting the "!=" to "=" again. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 10633641ec17081cca6332c3fb4abeea3df4059f) +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 33c8f344f..9596a97b3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -362,7 +362,7 @@ AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) + #================= + # Check for elfutils libdw library with dwelf_elf_gnu_build_id. + WITH_LIBDW_LIB= +-AS_IF([test "$WITH_LIBELF" != yes],[ ++AS_IF([test "$WITH_LIBELF" = yes],[ + AC_CHECK_HEADERS([elfutils/libdwelf.h],[ + AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ + AC_DEFINE(HAVE_LIBDW, 1, +-- +2.13.2 + diff --git a/0012-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch b/0012-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch deleted file mode 100644 index 31c8df0..0000000 --- a/0012-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch +++ /dev/null @@ -1,52 +0,0 @@ -From bbeaacd32e74b11264082407e520438373527740 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Thu, 9 Mar 2017 09:30:17 +0100 -Subject: [PATCH] generateBuildIDs: Don't warn or error for object files - without build-id. - -Only loadable ELF images (executables, shared libraries, kernel modules) -should have build-ids. So don't warn or error out when an object file is -found without one. - -Signed-off-by: Mark Wielaard ---- - build/files.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/build/files.c b/build/files.c -index cbcc0a9..26f53bd 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1709,8 +1709,10 @@ static int generateBuildIDs(FileList fl) - if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { - int fd = open (flp->diskPath, O_RDONLY); - if (fd >= 0) { -+ GElf_Ehdr ehdr; - Elf *elf = elf_begin (fd, ELF_C_READ, NULL); -- if (elf != NULL && elf_kind(elf) == ELF_K_ELF) { -+ if (elf != NULL && elf_kind(elf) == ELF_K_ELF -+ && gelf_getehdr(elf, &ehdr) != NULL) { - const void *build_id; - ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id); - /* len == -1 means error. Zero means no -@@ -1759,9 +1761,14 @@ static int generateBuildIDs(FileList fl) - _("error reading build-id in %s: %s\n"), - flp->diskPath, elf_errmsg (-1)); - } else if (len == 0) { -- rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, -- _("Missing build-id in %s\n"), -- flp->diskPath); -+ /* Only ET_EXEC, ET_DYN or kernel modules -+ have build-ids. */ -+ if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN -+ || (ehdr.e_type == ET_REL -+ && rpmFileHasSuffix (flp->diskPath, ".ko"))) -+ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, -+ _("Missing build-id in %s\n"), -+ flp->diskPath); - } else { - rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, - (len < 16 --- -1.8.3.1 - diff --git a/0013-debugedit-Support-String-Line-table-rewriting-for-la.patch b/0013-debugedit-Support-String-Line-table-rewriting-for-la.patch new file mode 100644 index 0000000..bff97f4 --- /dev/null +++ b/0013-debugedit-Support-String-Line-table-rewriting-for-la.patch @@ -0,0 +1,2103 @@ +From ddb7c4abddd746d7ec354fb89be16a2411a92cba Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Mon, 27 Feb 2017 16:28:18 +0100 +Subject: [PATCH 13/49] debugedit: Support String/Line table rewriting for + larger/smaller paths. + +debugedit --base to --dest rewriting of debug source file paths only +supported dest paths that were smaller or equal than the base path +(and the size should differ more than 1 character for correct debug lines). +All paths were changed "in place". Which could in theory mess up debug str +sharing. + +This rewrite supports base and dest strings of any size (some limitations, +see below). This is done by reconstructing the debug_str and debug_line +tables and updating the references in the debug_info attributes pointing +to these tables. Plus, if necessary (only for ET_REL kernel modules), +updating any relocations for the debug_info and debug_line sections. + +This has the nice benefit of merging any duplicate strings in the +debug_str table which might resulting on slightly smaller files. +kernel modules are ET_REL files that often contain a lot of duplicate +strings. + +The rewrite uses elfutils (either libebl or libdw) to reconstruct the +debug_str table. Since we are changing some section sizes now we cannot +just use mmap and rawdata to poke the values, but need to read in and +write out the changed sections. This does take a bit more memory because +we now also need to keep track of all string/line references. + +There are still some limitations (already in the original debugedit) +not fixed by this rewrite: +- DW_AT_comp_dir in .debug_info using DW_FORM_string can not be made + larger. We only warn about that now instead of failing. The only + producer of DW_FORM_string comp_dirs is binutils gas. It seems simpler + to fix gas than to try to support resizing the debug_info section. +- A DW_AT_name on a DW_TAG_compile_unit is only rewritten for DW_FORM_strp + not for DW_FORM_string. Probably no problem in practice since this + wasn't supported originally either. +- The debug_line program isn't scanned for DW_LNE_define_file which + could in theory define an absolute path that might need rewriting. + Again probably not a problem because this wasn't supported before + and there are no know producers for this construct. + +To support the upcoming DWARFv5 in gcc 7 (not on by default), we will +need to add support for the new debug_line format and scan the new +debug_macro section that can have references to the debug_str table. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 88989572fff1f31e0c4f972a6895585e4742ef4b) +--- + Makefile.am | 8 +- + configure.ac | 6 + + tools/debugedit.c | 1569 ++++++++++++++++++++++++++++++++++++++++++++--------- + 3 files changed, 1330 insertions(+), 253 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 6b37b5898..1b77730aa 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -156,13 +156,18 @@ rpm2archive_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ @WITH_ARCHIV + + if LIBELF + if LIBDWARF ++if LIBDW + rpmconfig_SCRIPTS += scripts/find-debuginfo.sh + + rpmlibexec_PROGRAMS += debugedit + debugedit_SOURCES = tools/debugedit.c tools/hashtab.c tools/hashtab.h + debugedit_LDADD = rpmio/librpmio.la + debugedit_LDADD += @WITH_LIBELF_LIB@ @WITH_POPT_LIB@ +- ++if HAVE_LIBDW_STRTAB ++debugedit_LDADD += @WITH_LIBDW_LIB@ ++else ++debugedit_LDADD += @WITH_LIBDW_LIB@ -lebl ++endif + rpmlibexec_PROGRAMS += elfdeps + elfdeps_SOURCES = tools/elfdeps.c + elfdeps_LDADD = rpmio/librpmio.la +@@ -173,6 +178,7 @@ sepdebugcrcfix_SOURCES = tools/sepdebugcrcfix.c + sepdebugcrcfix_LDADD = @WITH_LIBELF_LIB@ + endif + endif ++endif + + rpmlibexec_PROGRAMS += rpmdeps + rpmdeps_SOURCES = tools/rpmdeps.c +diff --git a/configure.ac b/configure.ac +index 9596a97b3..e6362535b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -362,18 +362,24 @@ AM_CONDITIONAL(WITH_ARCHIVE,[test "$with_archive" = yes]) + #================= + # Check for elfutils libdw library with dwelf_elf_gnu_build_id. + WITH_LIBDW_LIB= ++HAVE_LIBDW_STRTAB= + AS_IF([test "$WITH_LIBELF" = yes],[ + AC_CHECK_HEADERS([elfutils/libdwelf.h],[ ++ # dwelf_elf_gnu_build_id was introduced in elfutils 0.159 + AC_CHECK_LIB(dw, dwelf_elf_gnu_build_id, [ + AC_DEFINE(HAVE_LIBDW, 1, + [Define to 1 if you have elfutils libdw library]) + WITH_LIBDW_LIB="-ldw" + WITH_LIBDW=yes ++ # If possible we also want the strtab functions from elfutils 0.167. ++ # But we can fall back on the (unsupported) ebl alternatives if not. ++ AC_CHECK_LIB(dw, dwelf_strtab_init, [HAVE_LIBDW_STRTAB=yes]) + ]) + ]) + ]) + AC_SUBST(WITH_LIBDW_LIB) + AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) ++AM_CONDITIONAL(HAVE_LIBDW_STRTAB,[test "$HAVE_LIBDW_STRTAB" = yes]) + + #================= + # Process --with/without-external-db +diff --git a/tools/debugedit.c b/tools/debugedit.c +index c0147f086..4798c6370 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1,6 +1,7 @@ +-/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016 Red Hat, Inc. ++/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016, 2017 Red Hat, Inc. + Written by Alexander Larsson , 2002 + Based on code by Jakub Jelinek , 2001. ++ String/Line table rewriting by Mark Wielaard , 2017. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -30,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,6 +41,35 @@ + #include + #include + ++/* Unfortunately strtab manipulation functions were only officially added ++ to elfutils libdw in 0.167. Before that there were internal unsupported ++ ebl variants. While libebl.h isn't supported we'll try to use it anyway ++ if the elfutils we build against is too old. */ ++#include ++#if _ELFUTILS_PREREQ (0, 167) ++#include ++typedef Dwelf_Strent Strent; ++typedef Dwelf_Strtab Strtab; ++#define strtab_init dwelf_strtab_init ++#define strtab_add(X,Y) dwelf_strtab_add(X,Y) ++#define strtab_add_len(X,Y,Z) dwelf_strtab_add_len(X,Y,Z) ++#define strtab_free dwelf_strtab_free ++#define strtab_finalize dwelf_strtab_finalize ++#define strent_offset dwelf_strent_off ++#else ++#include ++typedef struct Ebl_Strent Strent; ++typedef struct Ebl_Strtab Strtab; ++#define strtab_init ebl_strtabinit ++#define strtab_add(X,Y) ebl_strtabadd(X,Y,0) ++#define strtab_add_len(X,Y,Z) ebl_strtabadd(X,Y,Z) ++#define strtab_free ebl_strtabfree ++#define strtab_finalize ebl_strtabfinalize ++#define strent_offset ebl_strtaboffset ++#endif ++ ++#include ++ + #include + #include + #include "tools/hashtab.h" +@@ -56,6 +87,99 @@ int list_file_fd = -1; + int do_build_id = 0; + char *build_id_seed = NULL; + ++/* We go over the debug sections in two phases. In phase zero we keep ++ track of any needed changes and collect strings, indexes and ++ sizes. In phase one we do the actual replacements updating the ++ strings, indexes and writing out new debug sections. The following ++ keep track of various changes that might be needed. */ ++ ++/* Whether we need to do any literal string (DW_FORM_string) replacements ++ in debug_info. */ ++static bool need_string_replacement = false; ++/* Whether we need to do any updates of the string indexes (DW_FORM_strp) ++ in debug_info for string indexes. */ ++static bool need_strp_update = false; ++/* If the debug_line changes size we will need to update the ++ DW_AT_stmt_list attributes indexes in the debug_info. */ ++static bool need_stmt_update = false; ++ ++/* Storage for dynamically allocated strings to put into string ++ table. Keep together in memory blocks of 16K. */ ++#define STRMEMSIZE (16 * 1024) ++struct strmemblock ++{ ++ struct strmemblock *next; ++ char memory[0]; ++}; ++ ++/* We keep track of each index in the original string table and the ++ associated entry in the new table so we don't insert identical ++ strings into the new string table. If constructed correctly the ++ original strtab shouldn't contain duplicate strings anyway. Any ++ actual identical strings could be deduplicated, but searching for ++ and comparing the indexes is much faster than comparing strings ++ (and we don't have to construct replacement strings). */ ++struct stridxentry ++{ ++ uint32_t idx; /* Original index in the string table. */ ++ Strent *entry; /* Entry in the new table. */ ++}; ++ ++/* Storage for new string table entries. Keep together in memory to ++ quickly search through them with tsearch. */ ++#define STRIDXENTRIES ((16 * 1024) / sizeof (struct stridxentry)) ++struct strentblock ++{ ++ struct strentblock *next; ++ struct stridxentry entry[0]; ++}; ++ ++/* All data to keep track of the existing and new string table. */ ++struct strings ++{ ++ Strtab *str_tab; /* The new string table. */ ++ char *str_buf; /* New Elf_Data d_buf. */ ++ struct strmemblock *blocks; /* The first strmemblock. */ ++ struct strmemblock *last_block; /* The currently used strmemblock. */ ++ size_t stridx; /* Next free byte in last block. */ ++ struct strentblock *entries; /* The first string index block. */ ++ struct strentblock *last_entries; /* The currently used strentblock. */ ++ size_t entryidx; /* Next free entry in the last block. */ ++ void *strent_root; /* strent binary search tree root. */ ++}; ++ ++struct line_table ++{ ++ size_t old_idx; /* Original offset. */ ++ size_t new_idx; /* Offset in new debug_line section. */ ++ ssize_t size_diff; /* Difference in (header) size. */ ++ bool replace_dirs; /* Whether to replace any dir paths. */ ++ bool replace_files; /* Whether to replace any file paths. */ ++ ++ /* Header fields. */ ++ uint32_t unit_length; ++ uint16_t version; ++ uint32_t header_length; ++ uint8_t min_instr_len; ++ uint8_t max_op_per_instr; /* Only if version >= 4 */ ++ uint8_t default_is_stmt; ++ int8_t line_base; ++ uint8_t line_range; ++ uint8_t opcode_base; ++}; ++ ++struct debug_lines ++{ ++ struct line_table *table; /* Malloc/Realloced. */ ++ size_t size; /* Total number of line_tables. ++ Updated by get_line_table. */ ++ size_t used; /* Used number of line_tables. ++ Updated by get_line_table. */ ++ size_t debug_lines_len; /* Total size of new debug_line section. ++ updated by edit_dwarf2_line. */ ++ char *line_buf; /* New Elf_Data d_buf. */ ++}; ++ + typedef struct + { + Elf *elf; +@@ -63,15 +187,42 @@ typedef struct + Elf_Scn **scn; + const char *filename; + int lastscn; ++ size_t phnum; ++ struct strings strings; ++ struct debug_lines lines; + GElf_Shdr shdr[0]; + } DSO; + ++static void ++setup_lines (struct debug_lines *lines) ++{ ++ lines->table = NULL; ++ lines->size = 0; ++ lines->used = 0; ++ lines->debug_lines_len = 0; ++ lines->line_buf = NULL; ++} ++ ++static void ++destroy_lines (struct debug_lines *lines) ++{ ++ free (lines->table); ++ free (lines->line_buf); ++} ++ + typedef struct + { + unsigned char *ptr; + uint32_t addend; ++ int ndx; + } REL; + ++typedef struct ++{ ++ Elf64_Addr r_offset; ++ int ndx; ++} LINE_REL; ++ + #define read_uleb128(ptr) ({ \ + unsigned int ret = 0; \ + unsigned int c; \ +@@ -88,9 +239,23 @@ typedef struct + ret; \ + }) + ++#define write_uleb128(ptr,val) ({ \ ++ uint32_t valv = (val); \ ++ do \ ++ { \ ++ unsigned char c = valv & 0x7f; \ ++ valv >>= 7; \ ++ if (valv) \ ++ c |= 0x80; \ ++ *ptr++ = c; \ ++ } \ ++ while (valv); \ ++}) ++ + static uint16_t (*do_read_16) (unsigned char *ptr); + static uint32_t (*do_read_32) (unsigned char *ptr); +-static void (*write_32) (unsigned char *ptr, GElf_Addr val); ++static void (*do_write_16) (unsigned char *ptr, uint16_t val); ++static void (*do_write_32) (unsigned char *ptr, uint32_t val); + + static int ptr_size; + static int cu_version; +@@ -129,7 +294,7 @@ strptr (DSO *dso, int sec, off_t offset) + if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size) + { + data = NULL; +- while ((data = elf_rawdata (scn, data)) != NULL) ++ while ((data = elf_getdata (scn, data)) != NULL) + { + if (data->d_buf + && offset >= data->d_off +@@ -142,7 +307,7 @@ strptr (DSO *dso, int sec, off_t offset) + } + + +-#define read_1(ptr) *ptr++ ++#define read_8(ptr) *ptr++ + + #define read_16(ptr) ({ \ + uint16_t ret = do_read_16 (ptr); \ +@@ -183,28 +348,73 @@ int reltype; + }) + + static void +-dwarf2_write_le32 (unsigned char *p, GElf_Addr val) ++dwarf2_write_le16 (unsigned char *p, uint16_t v) + { +- uint32_t v = (uint32_t) val; ++ p[0] = v; ++ p[1] = v >> 8; ++} + ++static void ++dwarf2_write_le32 (unsigned char *p, uint32_t v) ++{ + p[0] = v; + p[1] = v >> 8; + p[2] = v >> 16; + p[3] = v >> 24; + } + +- + static void +-dwarf2_write_be32 (unsigned char *p, GElf_Addr val) ++dwarf2_write_be16 (unsigned char *p, uint16_t v) + { +- uint32_t v = (uint32_t) val; ++ p[1] = v; ++ p[0] = v >> 8; ++} + ++static void ++dwarf2_write_be32 (unsigned char *p, uint32_t v) ++{ + p[3] = v; + p[2] = v >> 8; + p[1] = v >> 16; + p[0] = v >> 24; + } + ++#define write_8(ptr,val) ({ \ ++ *ptr++ = (val); \ ++}) ++ ++#define write_16(ptr,val) ({ \ ++ do_write_16 (ptr,val); \ ++ ptr += 2; \ ++}) ++ ++#define write_32(ptr,val) ({ \ ++ do_write_32 (ptr,val); \ ++ ptr += 4; \ ++}) ++ ++/* relocated writes can only be called immediately after ++ do_read_32_relocated. ptr must be equal to relptr->ptr (or ++ relend). Might just update the addend. So relocations need to be ++ updated at the end. */ ++ ++#define do_write_32_relocated(ptr,val) ({ \ ++ if (relptr && relptr < relend && relptr->ptr == ptr) \ ++ { \ ++ if (reltype == SHT_REL) \ ++ do_write_32 (ptr, val - relptr->addend); \ ++ else \ ++ relptr->addend = val; \ ++ } \ ++ else \ ++ do_write_32 (ptr,val); \ ++}) ++ ++#define write_32_relocated(ptr,val) ({ \ ++ do_write_32_relocated (ptr,val); \ ++ ptr += 4; \ ++}) ++ + static struct + { + const char *name; +@@ -448,90 +658,638 @@ canonicalize_path (const char *s, char *d) + return rv; + } + ++/* Returns the rest of PATH if it starts with DIR_PREFIX, skipping any ++ / path separators, or NULL if PATH doesn't start with ++ DIR_PREFIX. Might return the empty string if PATH equals DIR_PREFIX ++ (modulo trailing slashes). Never returns path starting with '/'. */ ++static const char * ++skip_dir_prefix (const char *path, const char *dir_prefix) ++{ ++ size_t prefix_len = strlen (dir_prefix); ++ if (strncmp (path, dir_prefix, prefix_len) == 0) ++ { ++ path += prefix_len; ++ while (IS_DIR_SEPARATOR (path[0])) ++ path++; ++ return path; ++ } ++ ++ return 0; ++} ++ ++/* Most strings will be in the existing debug string table. But to ++ replace the base/dest directory prefix we need some new storage. ++ Keep new strings somewhat close together for faster comparison and ++ copying. SIZE should be at least one (and includes space for the ++ zero terminator). The returned pointer points to uninitialized ++ data. */ ++static char * ++new_string_storage (struct strings *strings, size_t size) ++{ ++ assert (size > 0); ++ ++ /* If the string is extra long just create a whole block for ++ it. Normally strings are much smaller than STRMEMSIZE. */ ++ if (strings->last_block == NULL ++ || size > STRMEMSIZE ++ || strings->stridx > STRMEMSIZE ++ || (STRMEMSIZE - strings->stridx) < size) ++ { ++ struct strmemblock *newblock = malloc (sizeof (struct strmemblock) ++ + MAX (STRMEMSIZE, size)); ++ if (newblock == NULL) ++ return NULL; ++ ++ newblock->next = NULL; ++ ++ if (strings->blocks == NULL) ++ strings->blocks = newblock; ++ ++ if (strings->last_block != NULL) ++ strings->last_block->next = newblock; ++ ++ strings->last_block = newblock; ++ strings->stridx = 0; ++ } ++ ++ size_t stridx = strings->stridx; ++ strings->stridx += size + 1; ++ return &strings->last_block->memory[stridx]; ++} ++ ++/* Comparison function used for tsearch. */ + static int +-has_prefix (const char *str, +- const char *prefix) ++strent_compare (const void *a, const void *b) + { +- size_t str_len; +- size_t prefix_len; ++ struct stridxentry *entry_a = (struct stridxentry *)a; ++ struct stridxentry *entry_b = (struct stridxentry *)b; ++ size_t idx_a = entry_a->idx; ++ size_t idx_b = entry_b->idx; + +- str_len = strlen (str); +- prefix_len = strlen (prefix); ++ if (idx_a < idx_b) ++ return -1; + +- if (str_len < prefix_len) +- return 0; ++ if (idx_a > idx_b) ++ return 1; + +- return strncmp (str, prefix, prefix_len) == 0; ++ return 0; + } + +-static int dirty_elf; ++/* Allocates and inserts a new entry for the old index if not yet ++ seen. Returns a stridxentry if the given index has not yet been ++ seen and needs to be filled in with the associated string (either ++ the original string or the replacement string). Returns NULL if the ++ idx is already known. Use in phase 0 to add all strings seen. In ++ phase 1 use string_find_entry instead to get existing entries. */ ++static struct stridxentry * ++string_find_new_entry (struct strings *strings, size_t old_idx) ++{ ++ /* Use next entry in the pool for lookup so we can use it directly ++ if this is a new index. */ ++ struct stridxentry *entry; ++ ++ /* Keep entries close together to make key comparison fast. */ ++ if (strings->last_entries == NULL || strings->entryidx >= STRIDXENTRIES) ++ { ++ size_t entriessz = (sizeof (struct strentblock) ++ + (STRIDXENTRIES * sizeof (struct stridxentry))); ++ struct strentblock *newentries = malloc (entriessz); ++ if (newentries == NULL) ++ error (1, errno, "Couldn't allocate new string entries block"); ++ else ++ { ++ if (strings->entries == NULL) ++ strings->entries = newentries; ++ ++ if (strings->last_entries != NULL) ++ strings->last_entries->next = newentries; ++ ++ strings->last_entries = newentries; ++ strings->last_entries->next = NULL; ++ strings->entryidx = 0; ++ } ++ } ++ ++ entry = &strings->last_entries->entry[strings->entryidx]; ++ entry->idx = old_idx; ++ struct stridxentry **tres = tsearch (entry, &strings->strent_root, ++ strent_compare); ++ if (tres == NULL) ++ error (1, ENOMEM, "Couldn't insert new strtab idx"); ++ else if (*tres == entry) ++ { ++ /* idx not yet seen, must add actual str. */ ++ strings->entryidx++; ++ return entry; ++ } ++ ++ return NULL; /* We already know about this idx, entry already complete. */ ++} ++ ++static struct stridxentry * ++string_find_entry (struct strings *strings, size_t old_idx) ++{ ++ struct stridxentry **ret; ++ struct stridxentry key; ++ key.idx = old_idx; ++ ret = tfind (&key, &strings->strent_root, strent_compare); ++ assert (ret != NULL); /* Can only happen for a bad/non-existing old_idx. */ ++ return *ret; ++} ++ ++/* Adds a string_idx_entry given an index into the old/existing string ++ table. Should be used in phase 0. Does nothing if the index was ++ already registered. Otherwise it checks the string associated with ++ the index. If the old string doesn't start with base_dir an entry ++ will be recorded for the index with the same string. Otherwise a ++ string will be recorded where the base_dir prefix will be replaced ++ by dest_dir. Returns true if this is a not yet seen index and there ++ a replacement file string has been recorded for it, otherwise ++ returns false. */ ++static bool ++record_file_string_entry_idx (struct strings *strings, size_t old_idx) ++{ ++ bool ret = false; ++ struct stridxentry *entry = string_find_new_entry (strings, old_idx); ++ if (entry != NULL) ++ { ++ Strent *strent; ++ const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx; ++ const char *file = skip_dir_prefix (old_str, base_dir); ++ if (file == NULL) ++ { ++ /* Just record the existing string. */ ++ strent = strtab_add_len (strings->str_tab, old_str, ++ strlen (old_str) + 1); ++ } ++ else ++ { ++ /* Create and record the altered file path. */ ++ size_t dest_len = strlen (dest_dir); ++ size_t file_len = strlen (file); ++ size_t nsize = dest_len + 1; /* + '\0' */ ++ if (file_len > 0) ++ nsize += 1 + file_len; /* + '/' */ ++ char *nname = new_string_storage (strings, nsize); ++ if (nname == NULL) ++ error (1, ENOMEM, "Couldn't allocate new string storage"); ++ memcpy (nname, dest_dir, dest_len); ++ if (file_len > 0) ++ { ++ nname[dest_len] = '/'; ++ memcpy (nname + dest_len + 1, file, file_len + 1); ++ } ++ else ++ nname[dest_len] = '\0'; ++ ++ strent = strtab_add_len (strings->str_tab, nname, nsize); ++ ret = true; ++ } ++ if (strent == NULL) ++ error (1, ENOMEM, "Could not create new string table entry"); ++ else ++ entry->entry = strent; ++ } ++ ++ return ret; ++} ++ ++/* Same as record_new_string_file_string_entry_idx but doesn't replace ++ base_dir with dest_dir, just records the existing string associated ++ with the index. */ + static void +-dirty_section (unsigned int sec) ++record_existing_string_entry_idx (struct strings *strings, size_t old_idx) + { +- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); +- dirty_elf = 1; ++ struct stridxentry *entry = string_find_new_entry (strings, old_idx); ++ if (entry != NULL) ++ { ++ const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx; ++ Strent *strent = strtab_add_len (strings->str_tab, ++ str, strlen (str) + 1); ++ if (strent == NULL) ++ error (1, ENOMEM, "Could not create new string table entry"); ++ else ++ entry->entry = strent; ++ } + } + +-static int +-edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) ++static void ++setup_strings (struct strings *strings) + { +- unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir; +- unsigned char **dirt; +- unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size; +- unsigned char *endcu, *endprol; +- unsigned char opcode_base; +- uint32_t value, dirt_cnt; +- size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); +- size_t abs_file_cnt = 0, abs_dir_cnt = 0; ++ strings->str_tab = strtab_init (false); ++ strings->str_buf = NULL; ++ strings->blocks = NULL; ++ strings->last_block = NULL; ++ strings->entries = NULL; ++ strings->last_entries = NULL; ++ strings->strent_root = NULL; ++} + +- if (phase != 0) +- return 0; ++/* Noop for tdestroy. */ ++static void free_node (void *p __attribute__((__unused__))) { } + +- /* XXX: RhBug:929365, should we error out instead of ignoring? */ ++static void ++destroy_strings (struct strings *strings) ++{ ++ struct strmemblock *smb = strings->blocks; ++ while (smb != NULL) ++ { ++ void *old = smb; ++ smb = smb->next; ++ free (old); ++ } ++ ++ struct strentblock *emb = strings->entries; ++ while (emb != NULL) ++ { ++ void *old = emb; ++ emb = emb->next; ++ free (old); ++ } ++ ++ strtab_free (strings->str_tab); ++ tdestroy (strings->strent_root, &free_node); ++ free (strings->str_buf); ++} ++ ++/* The minimum number of line tables we pre-allocate. */ ++#define MIN_LINE_TABLES 64 ++ ++/* Gets a line_table at offset. Returns true if not yet know and ++ successfully read, false otherwise. Sets *table to NULL and ++ outputs a warning if there was a problem reading the table at the ++ given offset. */ ++static bool ++get_line_table (DSO *dso, size_t off, struct line_table **table) ++{ ++ struct debug_lines *lines = &dso->lines; ++ /* Assume there aren't that many, just do a linear search. The ++ array is probably already sorted because the stmt_lists are ++ probably inserted in order. But we cannot rely on that (maybe we ++ should check that to make searching quicker if possible?). Once ++ we have all line tables for phase 1 (rewriting) we do explicitly ++ sort the array.*/ ++ for (int i = 0; i < lines->used; i++) ++ if (lines->table[i].old_idx == off) ++ { ++ *table = &lines->table[i]; ++ return false; ++ } ++ ++ if (lines->size == lines->used) ++ { ++ struct line_table *new_table = realloc (lines->table, ++ (sizeof (struct line_table) ++ * (lines->size ++ + MIN_LINE_TABLES))); ++ if (new_table == NULL) ++ { ++ error (0, ENOMEM, "Couldn't add more debug_line tables"); ++ *table = NULL; ++ return false; ++ } ++ lines->table = new_table; ++ lines->size += MIN_LINE_TABLES; ++ } ++ ++ struct line_table *t = &lines->table[lines->used]; ++ *table = NULL; ++ ++ t->old_idx = off; ++ t->size_diff = 0; ++ t->replace_dirs = false; ++ t->replace_files = false; ++ ++ unsigned char *ptr = debug_sections[DEBUG_LINE].data; ++ unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size; + if (ptr == NULL) +- return 0; ++ { ++ error (0, 0, "%s: No .line_table section", dso->filename); ++ return false; ++ } + ++ if (off > debug_sections[DEBUG_LINE].size) ++ { ++ error (0, 0, "%s: Invalid .line_table offset 0x%zx", ++ dso->filename, off); ++ return false; ++ } + ptr += off; + +- endcu = ptr + 4; +- endcu += read_32 (ptr); ++ /* unit_length */ ++ unsigned char *endcu = ptr + 4; ++ t->unit_length = read_32 (ptr); ++ endcu += t->unit_length; + if (endcu == ptr + 0xffffffff) + { + error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); +- return 1; ++ return false; + } + + if (endcu > endsec) + { + error (0, 0, "%s: .debug_line CU does not fit into section", + dso->filename); +- return 1; ++ return false; + } + +- value = read_16 (ptr); +- if (value != 2 && value != 3 && value != 4) ++ /* version */ ++ t->version = read_16 (ptr); ++ if (t->version != 2 && t->version != 3 && t->version != 4) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, +- value); +- return 1; ++ t->version); ++ return false; + } + +- endprol = ptr + 4; +- endprol += read_32 (ptr); ++ /* header_length */ ++ unsigned char *endprol = ptr + 4; ++ t->header_length = read_32 (ptr); ++ endprol += t->header_length; + if (endprol > endcu) + { + error (0, 0, "%s: .debug_line CU prologue does not fit into CU", + dso->filename); +- return 1; ++ return false; ++ } ++ ++ /* min instr len */ ++ t->min_instr_len = *ptr++; ++ ++ /* max op per instr, if version >= 4 */ ++ if (t->version >= 4) ++ t->max_op_per_instr = *ptr++; ++ ++ /* default is stmt */ ++ t->default_is_stmt = *ptr++; ++ ++ /* line base */ ++ t->line_base = (*(int8_t *)ptr++); ++ ++ /* line range */ ++ t->line_range = *ptr++; ++ ++ /* opcode base */ ++ t->opcode_base = *ptr++; ++ ++ if (ptr + t->opcode_base - 1 >= endcu) ++ { ++ error (0, 0, "%s: .debug_line opcode table does not fit into CU", ++ dso->filename); ++ return false; + } ++ lines->used++; ++ *table = t; ++ return true; ++} + +- opcode_base = ptr[4 + (value >= 4)]; +- ptr = dir = ptr + 4 + (value >= 4) + opcode_base; ++static int dirty_elf; ++static void ++dirty_section (unsigned int sec) ++{ ++ elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); ++ dirty_elf = 1; ++} ++ ++static int ++line_table_cmp (const void *a, const void *b) ++{ ++ struct line_table *ta = (struct line_table *) a; ++ struct line_table *tb = (struct line_table *) b; ++ ++ if (ta->old_idx < tb->old_idx) ++ return -1; ++ ++ if (ta->old_idx > tb->old_idx) ++ return 1; ++ ++ return 0; ++} ++ ++ ++/* Called after phase zero (which records all adjustments needed for ++ the line tables referenced from debug_info) and before phase one ++ starts (phase one will adjust the .debug_line section stmt ++ references using the updated data structures). */ ++static void ++edit_dwarf2_line (DSO *dso) ++{ ++ Elf_Data *linedata = debug_sections[DEBUG_LINE].elf_data; ++ int linendx = debug_sections[DEBUG_LINE].sec; ++ Elf_Scn *linescn = dso->scn[linendx]; ++ unsigned char *old_buf = linedata->d_buf; ++ ++ /* Out with the old. */ ++ linedata->d_size = 0; ++ ++ /* In with the new. */ ++ linedata = elf_newdata (linescn); ++ ++ dso->lines.line_buf = malloc (dso->lines.debug_lines_len); ++ if (dso->lines.line_buf == NULL) ++ error (1, ENOMEM, "No memory for new .debug_line table (0x%zx bytes)", ++ dso->lines.debug_lines_len); ++ ++ linedata->d_size = dso->lines.debug_lines_len; ++ linedata->d_buf = dso->lines.line_buf; ++ debug_sections[DEBUG_LINE].size = linedata->d_size; ++ ++ /* Make sure the line tables are sorted on the old index. */ ++ qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table), ++ line_table_cmp); ++ ++ unsigned char *ptr = linedata->d_buf; ++ for (int ldx = 0; ldx < dso->lines.used; ldx++) ++ { ++ struct line_table *t = &dso->lines.table[ldx]; ++ unsigned char *optr = old_buf + t->old_idx; ++ t->new_idx = ptr - (unsigned char *) linedata->d_buf; ++ ++ /* Just copy the whole table if nothing needs replacing. */ ++ if (! t->replace_dirs && ! t->replace_files) ++ { ++ assert (t->size_diff == 0); ++ memcpy (ptr, optr, t->unit_length + 4); ++ ptr += t->unit_length + 4; ++ continue; ++ } ++ ++ /* Header fields. */ ++ write_32 (ptr, t->unit_length + t->size_diff); ++ write_16 (ptr, t->version); ++ write_32 (ptr, t->header_length + t->size_diff); ++ write_8 (ptr, t->min_instr_len); ++ if (t->version >= 4) ++ write_8 (ptr, t->max_op_per_instr); ++ write_8 (ptr, t->default_is_stmt); ++ write_8 (ptr, t->line_base); ++ write_8 (ptr, t->line_range); ++ write_8 (ptr, t->opcode_base); ++ ++ optr += (4 /* unit len */ ++ + 2 /* version */ ++ + 4 /* header len */ ++ + 1 /* min instr len */ ++ + (t->version >= 4) /* max op per instr, if version >= 4 */ ++ + 1 /* default is stmt */ ++ + 1 /* line base */ ++ + 1 /* line range */ ++ + 1); /* opcode base */ ++ ++ /* opcode len table. */ ++ memcpy (ptr, optr, t->opcode_base - 1); ++ optr += t->opcode_base - 1; ++ ptr += t->opcode_base - 1; ++ ++ /* directory table. We need to find the end (start of file ++ table) anyway, so loop over all dirs, even if replace_dirs is ++ false. */ ++ while (*optr != 0) ++ { ++ const char *dir = (const char *) optr; ++ const char *file_path = NULL; ++ if (t->replace_dirs) ++ { ++ file_path = skip_dir_prefix (dir, base_dir); ++ if (file_path != NULL) ++ { ++ size_t dest_len = strlen (dest_dir); ++ size_t file_len = strlen (file_path); ++ memcpy (ptr, dest_dir, dest_len); ++ ptr += dest_len; ++ if (file_len > 0) ++ { ++ *ptr++ = '/'; ++ memcpy (ptr, file_path, file_len); ++ ptr += file_len; ++ } ++ *ptr++ = '\0'; ++ } ++ } ++ if (file_path == NULL) ++ { ++ size_t dir_len = strlen (dir); ++ memcpy (ptr, dir, dir_len + 1); ++ ptr += dir_len + 1; ++ } ++ ++ optr = (unsigned char *) strchr (dir, 0) + 1; ++ } ++ optr++; ++ *ptr++ = '\0'; ++ ++ /* file table */ ++ if (t->replace_files) ++ { ++ while (*optr != 0) ++ { ++ const char *file = (const char *) optr; ++ const char *file_path = NULL; ++ if (t->replace_dirs) ++ { ++ file_path = skip_dir_prefix (file, base_dir); ++ if (file_path != NULL) ++ { ++ size_t dest_len = strlen (dest_dir); ++ size_t file_len = strlen (file_path); ++ memcpy (ptr, dest_dir, dest_len); ++ ptr += dest_len; ++ if (file_len > 0) ++ { ++ *ptr++ = '/'; ++ memcpy (ptr, file_path, file_len); ++ ptr += file_len; ++ } ++ *ptr++ = '\0'; ++ } ++ } ++ if (file_path == NULL) ++ { ++ size_t file_len = strlen (file); ++ memcpy (ptr, file, file_len + 1); ++ ptr += file_len + 1; ++ } ++ ++ optr = (unsigned char *) strchr (file, 0) + 1; ++ ++ /* dir idx, time, len */ ++ uint32_t dir_idx = read_uleb128 (optr); ++ write_uleb128 (ptr, dir_idx); ++ uint32_t time = read_uleb128 (optr); ++ write_uleb128 (ptr, time); ++ uint32_t len = read_uleb128 (optr); ++ write_uleb128 (ptr, len); ++ } ++ optr++; ++ *ptr++ = '\0'; ++ } ++ ++ /* line number program (and file table if not copied above). */ ++ size_t remaining = (t->unit_length + 4 ++ - (optr - (old_buf + t->old_idx))); ++ memcpy (ptr, optr, remaining); ++ ptr += remaining; ++ } ++} ++ ++/* Called during phase zero for each debug_line table referenced from ++ .debug_info. Outputs all source files seen and records any ++ adjustments needed in the debug_list data structures. Returns true ++ if line_table needs to be rewrite either the dir or file paths. */ ++static bool ++read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) ++{ ++ unsigned char *ptr, *dir; ++ unsigned char **dirt; ++ uint32_t value, dirt_cnt; ++ size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); ++ struct line_table *table; ++ ++ if (get_line_table (dso, off, &table) == false ++ || table == NULL) ++ { ++ if (table != NULL) ++ error (0, 0, ".debug_line offset 0x%x referenced multiple times", ++ off); ++ return false; ++ } ++ ++ /* Skip to the directory table. The rest of the header has already ++ been read and checked by get_line_table. */ ++ ptr = debug_sections[DEBUG_LINE].data + off; ++ ptr += (4 /* unit len */ ++ + 2 /* version */ ++ + 4 /* header len */ ++ + 1 /* min instr len */ ++ + (table->version >= 4) /* max op per instr, if version >= 4 */ ++ + 1 /* default is stmt */ ++ + 1 /* line base */ ++ + 1 /* line range */ ++ + 1 /* opcode base */ ++ + table->opcode_base - 1); /* opcode len table */ ++ dir = ptr; + + /* dir table: */ + value = 1; + while (*ptr != 0) + { ++ if (base_dir && dest_dir) ++ { ++ /* Do we need to replace any of the dirs? Calculate new size. */ ++ const char *file_path = skip_dir_prefix ((const char *)ptr, ++ base_dir); ++ if (file_path != NULL) ++ { ++ size_t old_size = strlen ((const char *)ptr) + 1; ++ size_t file_len = strlen (file_path); ++ size_t new_size = strlen (dest_dir) + 1; ++ if (file_len > 0) ++ new_size += 1 + file_len; ++ table->size_diff += (new_size - old_size); ++ table->replace_dirs = true; ++ } ++ } ++ + ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1; + ++value; + } +@@ -561,21 +1319,34 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) + { + error (0, 0, "%s: Wrong directory table index %u", + dso->filename, value); +- return 1; ++ return false; + } + file_len = strlen (file); ++ if (base_dir && dest_dir) ++ { ++ /* Do we need to replace any of the files? Calculate new size. */ ++ const char *file_path = skip_dir_prefix (file, base_dir); ++ if (file_path != NULL) ++ { ++ size_t old_size = file_len + 1; ++ size_t file_len = strlen (file_path); ++ size_t new_size = strlen (dest_dir) + 1; ++ if (file_len > 0) ++ new_size += 1 + file_len; ++ table->size_diff += (new_size - old_size); ++ table->replace_files = true; ++ } ++ } + dir_len = strlen ((char *)dirt[value]); + s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1); + if (s == NULL) + { + error (0, ENOMEM, "%s: Reading file table", dso->filename); +- return 1; ++ return false; + } + if (*file == '/') + { + memcpy (s, file, file_len + 1); +- if (dest_dir && has_prefix (file, base_dir)) +- ++abs_file_cnt; + } + else if (*dirt[value] == '/') + { +@@ -599,13 +1370,15 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) + canonicalize_path (s, s); + if (list_file_fd != -1) + { +- char *p = NULL; ++ const char *p = NULL; + if (base_dir == NULL) + p = s; +- else if (has_prefix (s, base_dir)) +- p = s + strlen (base_dir); +- else if (has_prefix (s, dest_dir)) +- p = s + strlen (dest_dir); ++ else ++ { ++ p = skip_dir_prefix (s, base_dir); ++ if (p == NULL && dest_dir != NULL) ++ p = skip_dir_prefix (s, dest_dir); ++ } + + if (p) + { +@@ -626,112 +1399,28 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) + read_uleb128 (ptr); + read_uleb128 (ptr); + } +- ++ptr; +- +- if (dest_dir) +- { +- unsigned char *srcptr, *buf = NULL; +- size_t base_len = strlen (base_dir); +- size_t dest_len = strlen (dest_dir); +- size_t shrank = 0; +- +- if (dest_len == base_len) +- abs_file_cnt = 0; +- if (abs_file_cnt) +- { +- srcptr = buf = malloc (ptr - dir); +- memcpy (srcptr, dir, ptr - dir); +- ptr = dir; +- } +- else +- ptr = srcptr = dir; +- while (*srcptr != 0) +- { +- size_t len = strlen ((char *)srcptr) + 1; +- const unsigned char *readptr = srcptr; +- +- char *orig = strdup ((const char *) srcptr); +- +- if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir)) +- { +- if (dest_len < base_len) +- ++abs_dir_cnt; +- memcpy (ptr, dest_dir, dest_len); +- ptr += dest_len; +- readptr += base_len; +- } +- srcptr += len; + +- shrank += srcptr - readptr; +- canonicalize_path ((char *)readptr, (char *)ptr); +- len = strlen ((char *)ptr) + 1; +- shrank -= len; +- ptr += len; +- +- if (memcmp (orig, ptr - len, len)) +- dirty_section (DEBUG_STR); +- free (orig); +- } +- +- if (shrank > 0) +- { +- if (--shrank == 0) +- error (EXIT_FAILURE, 0, +- "canonicalization unexpectedly shrank by one character"); +- else +- { +- memset (ptr, 'X', shrank); +- ptr += shrank; +- *ptr++ = '\0'; +- } +- } +- +- if (abs_dir_cnt + abs_file_cnt != 0) +- { +- size_t len = (abs_dir_cnt + abs_file_cnt) * (base_len - dest_len); +- +- if (len == 1) +- error (EXIT_FAILURE, 0, "-b arg has to be either the same length as -d arg, or more than 1 char longer"); +- memset (ptr, 'X', len - 1); +- ptr += len - 1; +- *ptr++ = '\0'; +- } +- *ptr++ = '\0'; +- ++srcptr; +- +- while (*srcptr != 0) +- { +- size_t len = strlen ((char *)srcptr) + 1; ++ dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff; ++ return table->replace_dirs || table->replace_files; ++} + +- if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir)) +- { +- memcpy (ptr, dest_dir, dest_len); +- if (dest_len < base_len) +- { +- memmove (ptr + dest_len, srcptr + base_len, +- len - base_len); +- ptr += dest_len - base_len; +- } +- dirty_section (DEBUG_STR); +- } +- else if (ptr != srcptr) +- memmove (ptr, srcptr, len); +- srcptr += len; +- ptr += len; +- dir = srcptr; +- read_uleb128 (srcptr); +- read_uleb128 (srcptr); +- read_uleb128 (srcptr); +- if (ptr != dir) +- memmove (ptr, dir, srcptr - dir); +- ptr += srcptr - dir; +- } +- *ptr = '\0'; +- free (buf); +- } +- return 0; ++/* Called during phase one, after the table has been sorted. */ ++static size_t ++find_new_list_offs (struct debug_lines *lines, size_t idx) ++{ ++ struct line_table key; ++ key.old_idx = idx; ++ struct line_table *table = bsearch (&key, lines->table, ++ lines->used, ++ sizeof (struct line_table), ++ line_table_cmp); ++ return table->new_idx; + } + ++/* This scans the attributes of one DIE described by the given abbrev_tag. ++ PTR points to the data in the debug_info. It will be advanced till all ++ abbrev data is consumed. In phase zero data is collected, in phase one ++ data might be replaced/updated. */ + static unsigned char * + edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + { +@@ -747,20 +1436,36 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + { + uint32_t form = t->attr[i].form; + size_t len = 0; +- size_t base_len, dest_len; +- + while (1) + { ++ /* Whether we already handled a string as file for this ++ attribute. If we did then we don't need to handle/record ++ it again when handling the DW_FORM_strp later. */ ++ bool handled_strp = false; ++ ++ /* A stmt_list points into the .debug_line section. In ++ phase zero record all offsets. Then in phase one replace ++ them with the new offsets if we rewrote the line ++ tables. */ + if (t->attr[i].attr == DW_AT_stmt_list) + { + if (form == DW_FORM_data4 + || form == DW_FORM_sec_offset) + { + list_offs = do_read_32_relocated (ptr); +- found_list_offs = 1; ++ if (phase == 0) ++ found_list_offs = 1; ++ else if (need_stmt_update) /* phase one */ ++ { ++ size_t idx, new_idx; ++ idx = do_read_32_relocated (ptr); ++ new_idx = find_new_list_offs (&dso->lines, idx); ++ do_write_32_relocated (ptr, new_idx); ++ } + } + } + ++ /* DW_AT_comp_dir is the current working directory. */ + if (t->attr[i].attr == DW_AT_comp_dir) + { + if (form == DW_FORM_string) +@@ -768,44 +1473,65 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + free (comp_dir); + comp_dir = strdup ((char *)ptr); + +- if (phase == 1 && dest_dir && has_prefix ((char *)ptr, base_dir)) ++ if (dest_dir) + { +- base_len = strlen (base_dir); +- dest_len = strlen (dest_dir); +- +- memcpy (ptr, dest_dir, dest_len); +- if (dest_len < base_len) ++ /* In phase zero we are just collecting dir/file ++ names and check whether any need to be ++ adjusted. If so, in phase one we replace ++ those dir/files. */ ++ const char *file = skip_dir_prefix (comp_dir, base_dir); ++ if (file != NULL && phase == 0) ++ need_string_replacement = true; ++ else if (file != NULL && phase == 1) + { +- memset(ptr + dest_len, '/', +- base_len - dest_len); +- ++ size_t orig_len = strlen (comp_dir); ++ size_t dest_len = strlen (dest_dir); ++ size_t file_len = strlen (file); ++ size_t new_len = dest_len; ++ if (file_len > 0) ++ new_len += 1 + file_len; /* + '/' */ ++ ++ /* We don't want to rewrite the whole ++ debug_info section, so we only replace ++ the comp_dir with something equal or ++ smaller, possibly adding some slashes ++ at the end of the new compdir. This ++ normally doesn't happen since most ++ producers will use DW_FORM_strp which is ++ more efficient. */ ++ if (orig_len < new_len) ++ fprintf (stderr, "Warning, not replacing comp_dir " ++ "'%s' prefix ('%s' -> '%s') encoded as " ++ "DW_FORM_string. " ++ "Replacement too large.\n", ++ comp_dir, base_dir, dest_dir); ++ else ++ { ++ /* Add one or more slashes in between to ++ fill up all space (replacement must be ++ of the same length). */ ++ memcpy (ptr, dest_dir, dest_len); ++ memset (ptr + dest_len, '/', ++ orig_len - new_len + 1); ++ } + } +- dirty_section (DEBUG_INFO); + } + } + else if (form == DW_FORM_strp && + debug_sections[DEBUG_STR].data) + { +- char *dir; +- +- dir = (char *) debug_sections[DEBUG_STR].data +- + do_read_32_relocated (ptr); ++ const char *dir; ++ size_t idx = do_read_32_relocated (ptr); ++ dir = (char *) debug_sections[DEBUG_STR].data + idx; + + free (comp_dir); + comp_dir = strdup (dir); + +- if (phase == 1 && dest_dir && has_prefix (dir, base_dir)) ++ if (dest_dir != NULL && phase == 0) + { +- base_len = strlen (base_dir); +- dest_len = strlen (dest_dir); +- +- memcpy (dir, dest_dir, dest_len); +- if (dest_len < base_len) +- { +- memmove (dir + dest_len, dir + base_len, +- strlen (dir + base_len) + 1); +- } +- dirty_section (DEBUG_STR); ++ if (record_file_string_entry_idx (&dso->strings, idx)) ++ need_strp_update = true; ++ handled_strp = true; + } + } + } +@@ -815,10 +1541,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + && form == DW_FORM_strp + && debug_sections[DEBUG_STR].data) + { ++ /* DW_AT_name is the primary file for this compile ++ unit. If starting with / it is a full path name. ++ Note that we don't handle DW_FORM_string in this ++ case. */ + char *name; +- +- name = (char *) debug_sections[DEBUG_STR].data +- + do_read_32_relocated (ptr); ++ size_t idx = do_read_32_relocated (ptr); ++ name = (char *) debug_sections[DEBUG_STR].data + idx; + if (*name == '/' && comp_dir == NULL) + { + char *enddir = strrchr (name, '/'); +@@ -833,18 +1562,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + comp_dir = strdup ("/"); + } + +- if (phase == 1 && dest_dir && has_prefix (name, base_dir)) ++ /* First pass (0) records the new name to be ++ added to the debug string pool, the second ++ pass (1) stores it (the new index). */ ++ if (dest_dir && phase == 0) + { +- base_len = strlen (base_dir); +- dest_len = strlen (dest_dir); +- +- memcpy (name, dest_dir, dest_len); +- if (dest_len < base_len) +- { +- memmove (name + dest_len, name + base_len, +- strlen (name + base_len) + 1); +- } +- dirty_section (DEBUG_STR); ++ if (record_file_string_entry_idx (&dso->strings, idx)) ++ need_strp_update = true; ++ handled_strp = true; + } + } + +@@ -886,6 +1611,29 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + read_uleb128 (ptr); + break; + case DW_FORM_strp: ++ /* In the first pass we collect all strings, in the ++ second we put the new references back (if there are ++ any changes). */ ++ if (phase == 0) ++ { ++ /* handled_strp is set for attributes refering to ++ files. If it is set the string is already ++ recorded. */ ++ if (! handled_strp) ++ { ++ size_t idx = do_read_32_relocated (ptr); ++ record_existing_string_entry_idx (&dso->strings, idx); ++ } ++ } ++ else if (need_strp_update) /* && phase == 1 */ ++ { ++ struct stridxentry *entry; ++ size_t idx, new_idx; ++ idx = do_read_32_relocated (ptr); ++ entry = string_find_entry (&dso->strings, idx); ++ new_idx = strent_offset (entry->entry); ++ do_write_32_relocated (ptr, new_idx); ++ } + ptr += 4; + break; + case DW_FORM_string: +@@ -930,14 +1678,17 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + CU current dir subdirectories. */ + if (comp_dir && list_file_fd != -1) + { +- char *p; ++ const char *p = NULL; + size_t size; + +- if (base_dir && has_prefix (comp_dir, base_dir)) +- p = comp_dir + strlen (base_dir); +- else if (dest_dir && has_prefix (comp_dir, dest_dir)) +- p = comp_dir + strlen (dest_dir); +- else ++ if (base_dir) ++ { ++ p = skip_dir_prefix (comp_dir, base_dir); ++ if (p == NULL && dest_dir != NULL) ++ p = skip_dir_prefix (comp_dir, dest_dir); ++ } ++ ++ if (p == NULL) + p = comp_dir; + + size = strlen (p) + 1; +@@ -951,8 +1702,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + } + } + +- if (found_list_offs) +- edit_dwarf2_line (dso, list_offs, comp_dir, phase); ++ /* In phase zero we collect all file names (we need the comp_dir for ++ that). Note that calculating the new size and offsets is done ++ separately (at the end of phase zero after all CUs have been ++ scanned in dwarf2_edit). */ ++ if (phase == 0 && found_list_offs ++ && read_dwarf2_line (dso, list_offs, comp_dir)) ++ need_stmt_update = true; + + free (comp_dir); + +@@ -974,6 +1730,20 @@ rel_cmp (const void *a, const void *b) + } + + static int ++line_rel_cmp (const void *a, const void *b) ++{ ++ LINE_REL *rela = (LINE_REL *) a, *relb = (LINE_REL *) b; ++ ++ if (rela->r_offset < relb->r_offset) ++ return -1; ++ ++ if (rela->r_offset > relb->r_offset) ++ return 1; ++ ++ return 0; ++} ++ ++static int + edit_dwarf2 (DSO *dso) + { + Elf_Data *data; +@@ -1009,9 +1779,9 @@ edit_dwarf2 (DSO *dso) + } + + scn = dso->scn[i]; +- data = elf_rawdata (scn, NULL); ++ data = elf_getdata (scn, NULL); + assert (data != NULL && data->d_buf != NULL); +- assert (elf_rawdata (scn, data) == NULL); ++ assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[i].sh_size); + debug_sections[j].data = data->d_buf; +@@ -1050,13 +1820,15 @@ edit_dwarf2 (DSO *dso) + { + do_read_16 = buf_read_ule16; + do_read_32 = buf_read_ule32; +- write_32 = dwarf2_write_le32; ++ do_write_16 = dwarf2_write_le16; ++ do_write_32 = dwarf2_write_le32; + } + else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) + { + do_read_16 = buf_read_ube16; + do_read_32 = buf_read_ube32; +- write_32 = dwarf2_write_be32; ++ do_write_16 = dwarf2_write_be16; ++ do_write_32 = dwarf2_write_be32; + } + else + { +@@ -1179,6 +1951,7 @@ edit_dwarf2 (DSO *dso) + relend->ptr = debug_sections[DEBUG_INFO].data + + (rela.r_offset - base); + relend->addend = rela.r_addend; ++ relend->ndx = ndx; + ++relend; + } + if (relbuf == relend) +@@ -1193,6 +1966,13 @@ edit_dwarf2 (DSO *dso) + + for (phase = 0; phase < 2; phase++) + { ++ /* If we don't need to update anyhing, skip phase 1. */ ++ if (phase == 1 ++ && !need_strp_update ++ && !need_string_replacement ++ && !need_stmt_update) ++ break; ++ + ptr = debug_sections[DEBUG_INFO].data; + relptr = relbuf; + endsec = ptr + debug_sections[DEBUG_INFO].size; +@@ -1240,7 +2020,7 @@ edit_dwarf2 (DSO *dso) + + if (ptr_size == 0) + { +- ptr_size = read_1 (ptr); ++ ptr_size = read_8 (ptr); + if (ptr_size != 4 && ptr_size != 8) + { + error (0, 0, "%s: Invalid DWARF pointer size %d", +@@ -1248,7 +2028,7 @@ edit_dwarf2 (DSO *dso) + return 1; + } + } +- else if (read_1 (ptr) != ptr_size) ++ else if (read_8 (ptr) != ptr_size) + { + error (0, 0, "%s: DWARF pointer size differs between CUs", + dso->filename); +@@ -1281,7 +2061,185 @@ edit_dwarf2 (DSO *dso) + + htab_delete (abbrev); + } ++ ++ /* We might have to recalculate/rewrite the debug_line ++ section. We need to do that before going into phase one ++ so we have all new offsets. We do this separately from ++ scanning the dirs/file names because the DW_AT_stmt_lists ++ might not be in order or skip some padding we might have ++ to (re)move. */ ++ if (phase == 0 && need_stmt_update) ++ { ++ edit_dwarf2_line (dso); ++ ++ /* The line table programs will be moved ++ forward/backwards a bit in the new data. Update the ++ debug_line relocations to the new offsets. */ ++ int rndx = debug_sections[DEBUG_LINE].relsec; ++ if (rndx != 0) ++ { ++ LINE_REL *rbuf; ++ size_t rels; ++ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL); ++ int rtype = dso->shdr[rndx].sh_type; ++ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize; ++ rbuf = malloc (rels * sizeof (LINE_REL)); ++ if (rbuf == NULL) ++ error (1, errno, "%s: Could not allocate line relocations", ++ dso->filename); ++ ++ /* Sort them by offset into section. */ ++ for (size_t i = 0; i < rels; i++) ++ { ++ if (rtype == SHT_RELA) ++ { ++ GElf_Rela rela; ++ if (gelf_getrela (rdata, i, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ rbuf[i].r_offset = rela.r_offset; ++ rbuf[i].ndx = i; ++ } ++ else ++ { ++ GElf_Rel rel; ++ if (gelf_getrel (rdata, i, &rel) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ rbuf[i].r_offset = rel.r_offset; ++ rbuf[i].ndx = i; ++ } ++ } ++ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp); ++ ++ size_t lndx = 0; ++ for (size_t i = 0; i < rels; i++) ++ { ++ /* These relocations only happen in ET_REL files ++ and are section offsets. */ ++ GElf_Addr r_offset; ++ size_t ndx = rbuf[i].ndx; ++ ++ GElf_Rel rel; ++ GElf_Rela rela; ++ if (rtype == SHT_RELA) ++ { ++ if (gelf_getrela (rdata, ndx, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ r_offset = rela.r_offset; ++ } ++ else ++ { ++ if (gelf_getrel (rdata, ndx, &rel) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ r_offset = rel.r_offset; ++ } ++ ++ while (r_offset > (dso->lines.table[lndx].old_idx ++ + 4 ++ + dso->lines.table[lndx].unit_length) ++ && lndx < dso->lines.used) ++ lndx++; ++ ++ if (lndx >= dso->lines.used) ++ error (1, 0, ++ ".debug_line relocation offset out of range"); ++ ++ /* Offset (pointing into the line program) moves ++ from old to new index including the header ++ size diff. */ ++ r_offset += ((dso->lines.table[lndx].new_idx ++ - dso->lines.table[lndx].old_idx) ++ + dso->lines.table[lndx].size_diff); ++ ++ if (rtype == SHT_RELA) ++ { ++ rela.r_offset = r_offset; ++ if (gelf_update_rela (rdata, ndx, &rela) == 0) ++ error (1, 0, "Couldn't update relocation: %s", ++ elf_errmsg (-1)); ++ } ++ else ++ { ++ rel.r_offset = r_offset; ++ if (gelf_update_rel (rdata, ndx, &rel) == 0) ++ error (1, 0, "Couldn't update relocation: %s", ++ elf_errmsg (-1)); ++ } ++ } ++ ++ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY); ++ free (rbuf); ++ } ++ } ++ ++ /* Same for the debug_str section. Make sure everything is ++ in place for phase 1 updating of debug_info ++ references. */ ++ if (phase == 0 && need_strp_update) ++ { ++ Strtab *strtab = dso->strings.str_tab; ++ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; ++ int strndx = debug_sections[DEBUG_STR].sec; ++ Elf_Scn *strscn = dso->scn[strndx]; ++ ++ /* Out with the old. */ ++ strdata->d_size = 0; ++ /* In with the new. */ ++ strdata = elf_newdata (strscn); ++ ++ /* We really should check whether we had enough memory, ++ but the old ebl version will just abort on out of ++ memory... */ ++ strtab_finalize (strtab, strdata); ++ debug_sections[DEBUG_STR].size = strdata->d_size; ++ dso->strings.str_buf = strdata->d_buf; ++ } ++ ++ } ++ ++ /* After phase 1 we might have rewritten the debug_info with ++ new strp, strings and/or linep offsets. */ ++ if (need_strp_update || need_string_replacement || need_stmt_update) ++ dirty_section (DEBUG_INFO); ++ ++ /* Update any debug_info relocations addends we might have touched. */ ++ if (relbuf != NULL && reltype == SHT_RELA) ++ { ++ Elf_Data *symdata; ++ int relsec_ndx = debug_sections[DEBUG_INFO].relsec; ++ data = elf_getdata (dso->scn[relsec_ndx], NULL); ++ symdata = elf_getdata (dso->scn[dso->shdr[relsec_ndx].sh_link], ++ NULL); ++ ++ relptr = relbuf; ++ while (relptr < relend) ++ { ++ GElf_Sym sym; ++ GElf_Rela rela; ++ int ndx = relptr->ndx; ++ ++ if (gelf_getrela (data, ndx, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ ++ if (gelf_getsym (symdata, GELF_R_SYM (rela.r_info), ++ &sym) == NULL) ++ error (1, 0, "Couldn't get symbol: %s", elf_errmsg (-1)); ++ ++ rela.r_addend = relptr->addend - sym.st_value; ++ ++ if (gelf_update_rela (data, ndx, &rela) == 0) ++ error (1, 0, "Couldn't update relocations: %s", ++ elf_errmsg (-1)); ++ ++ ++relptr; ++ } ++ elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); + } ++ + free (relbuf); + } + +@@ -1310,8 +2268,9 @@ fdopen_dso (int fd, const char *name) + GElf_Ehdr ehdr; + int i; + DSO *dso = NULL; ++ size_t phnum; + +- elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL); ++ elf = elf_begin (fd, ELF_C_RDWR, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1)); +@@ -1348,10 +2307,20 @@ fdopen_dso (int fd, const char *name) + goto error_out; + } + +- elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT); ++ if (elf_getphdrnum (elf, &phnum) != 0) ++ { ++ error (0, 0, "Couldn't get number of phdrs: %s", elf_errmsg (-1)); ++ goto error_out; ++ } ++ ++ /* If there are phdrs we want to maintain the layout of the ++ allocated sections in the file. */ ++ if (phnum != 0) ++ elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT); + + memset (dso, 0, sizeof(DSO)); + dso->elf = elf; ++ dso->phnum = phnum; + dso->ehdr = ehdr; + dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20]; + +@@ -1362,12 +2331,16 @@ fdopen_dso (int fd, const char *name) + } + + dso->filename = (const char *) strdup (name); ++ setup_strings (&dso->strings); ++ setup_lines (&dso->lines); + return dso; + + error_out: + if (dso) + { + free ((char *) dso->filename); ++ destroy_strings (&dso->strings); ++ destroy_lines (&dso->lines); + free (dso); + } + if (elf) +@@ -1406,13 +2379,6 @@ handle_build_id (DSO *dso, Elf_Data *build_id, + if (!dirty_elf && build_id_seed == NULL) + goto print; + +- if (elf_update (dso->elf, ELF_C_NULL) < 0) +- { +- fprintf (stderr, "Failed to update file: %s\n", +- elf_errmsg (elf_errno ())); +- exit (1); +- } +- + /* Clear the old bits so they do not affect the new hash. */ + memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size); + +@@ -1475,7 +2441,7 @@ handle_build_id (DSO *dso, Elf_Data *build_id, + + if (u.shdr.sh_type != SHT_NOBITS) + { +- Elf_Data *d = elf_rawdata (dso->scn[i], NULL); ++ Elf_Data *d = elf_getdata (dso->scn[i], NULL); + if (d == NULL) + goto bad; + rpmDigestUpdate(ctx, d->d_buf, d->d_size); +@@ -1509,7 +2475,6 @@ main (int argc, char *argv[]) + int nextopt; + const char **args; + struct stat stat_buf; +- char *p; + Elf_Data *build_id = NULL; + size_t build_id_offset = 0, build_id_size = 0; + +@@ -1541,11 +2506,6 @@ main (int argc, char *argv[]) + fprintf (stderr, "You must specify a base dir if you specify a dest dir\n"); + exit (1); + } +- if (strlen (dest_dir) > strlen (base_dir)) +- { +- fprintf (stderr, "Dest dir longer than base dir is not supported\n"); +- exit (1); +- } + } + + if (build_id_seed != NULL && do_build_id == 0) +@@ -1561,30 +2521,13 @@ main (int argc, char *argv[]) + exit (1); + } + +- /* Ensure clean paths, users can muck with these */ ++ /* Ensure clean paths, users can muck with these. Also removes any ++ trailing '/' from the paths. */ + if (base_dir) + canonicalize_path(base_dir, base_dir); + if (dest_dir) + canonicalize_path(dest_dir, dest_dir); + +- /* Make sure there are trailing slashes in dirs */ +- if (base_dir != NULL && base_dir[strlen (base_dir)-1] != '/') +- { +- p = malloc (strlen (base_dir) + 2); +- strcpy (p, base_dir); +- strcat (p, "/"); +- free (base_dir); +- base_dir = p; +- } +- if (dest_dir != NULL && dest_dir[strlen (dest_dir)-1] != '/') +- { +- p = malloc (strlen (dest_dir) + 2); +- strcpy (p, dest_dir); +- strcat (p, "/"); +- free (dest_dir); +- dest_dir = p; +- } +- + if (list_file != NULL) + { + list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644); +@@ -1641,7 +2584,7 @@ main (int argc, char *argv[]) + && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC)) + { + /* Look for a build-ID note here. */ +- Elf_Data *data = elf_rawdata (elf_getscn (dso->elf, i), NULL); ++ Elf_Data *data = elf_getdata (elf_getscn (dso->elf, i), NULL); + Elf32_Nhdr nh; + Elf_Data dst = + { +@@ -1679,6 +2622,123 @@ main (int argc, char *argv[]) + } + } + ++ /* We might have changed the size of some debug sections. If so make ++ sure the section headers are updated and the data offsets are ++ correct. We set ELF_F_LAYOUT above because we don't want libelf ++ to move any allocated sections around itself if there are any ++ phdrs. Which means we are reponsible for setting the section size ++ and offset fields. Plus the shdr offsets. We don't want to change ++ anything for the phdrs allocated sections. Keep the offset of ++ allocated sections so they are at the same place in the file. Add ++ unallocated ones after the allocated ones. */ ++ if (dso->phnum != 0 && (need_strp_update || need_stmt_update)) ++ { ++ Elf *elf = dso->elf; ++ GElf_Off last_offset; ++ /* We position everything after the phdrs (which normally would ++ be at the start of the ELF file after the ELF header. */ ++ last_offset = (dso->ehdr.e_phoff + gelf_fsize (elf, ELF_T_PHDR, ++ dso->phnum, EV_CURRENT)); ++ ++ /* First find the last allocated section. */ ++ Elf_Scn *scn = NULL; ++ while ((scn = elf_nextscn (elf, scn)) != NULL) ++ { ++ GElf_Shdr shdr_mem; ++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ++ if (shdr == NULL) ++ error (1, 0, "Couldn't get shdr: %s\n", elf_errmsg (-1)); ++ ++ /* Any sections we have changed aren't allocated sections, ++ so we don't need to lookup any changed section sizes. */ ++ if ((shdr->sh_flags & SHF_ALLOC) != 0) ++ { ++ GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS ++ ? shdr->sh_size : 0); ++ if (last_offset < off) ++ last_offset = off; ++ } ++ } ++ ++ /* Now adjust any sizes and offsets for the unallocated sections. */ ++ scn = NULL; ++ while ((scn = elf_nextscn (elf, scn)) != NULL) ++ { ++ GElf_Shdr shdr_mem; ++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ++ if (shdr == NULL) ++ error (1, 0, "Couldn't get shdr: %s\n", elf_errmsg (-1)); ++ ++ /* A bug in elfutils before 0.169 means we have to write out ++ all section data, even when nothing changed. ++ https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ ++#if !_ELFUTILS_PREREQ (0, 169) ++ if (shdr->sh_type != SHT_NOBITS) ++ { ++ Elf_Data *d = elf_getdata (scn, NULL); ++ elf_flagdata (d, ELF_C_SET, ELF_F_DIRTY); ++ } ++#endif ++ if ((shdr->sh_flags & SHF_ALLOC) == 0) ++ { ++ GElf_Off sec_offset = shdr->sh_offset; ++ GElf_Xword sec_size = shdr->sh_size; ++ ++ /* We might have changed the size (and content) of the ++ debug_str or debug_line section. */ ++ size_t secnum = elf_ndxscn (scn); ++ if (secnum == debug_sections[DEBUG_STR].sec) ++ sec_size = debug_sections[DEBUG_STR].size; ++ if (secnum == debug_sections[DEBUG_LINE].sec) ++ sec_size = debug_sections[DEBUG_LINE].size; ++ ++ /* Zero means one. No alignment constraints. */ ++ size_t addralign = shdr->sh_addralign ?: 1; ++ last_offset = (last_offset + addralign - 1) & ~(addralign - 1); ++ sec_offset = last_offset; ++ if (shdr->sh_type != SHT_NOBITS) ++ last_offset += sec_size; ++ ++ if (shdr->sh_size != sec_size ++ || shdr->sh_offset != sec_offset) ++ { ++ /* Make sure unchanged section data is written out ++ at the new location. */ ++ if (shdr->sh_offset != sec_offset ++ && shdr->sh_type != SHT_NOBITS) ++ { ++ Elf_Data *d = elf_getdata (scn, NULL); ++ elf_flagdata (d, ELF_C_SET, ELF_F_DIRTY); ++ } ++ ++ shdr->sh_size = sec_size; ++ shdr->sh_offset = sec_offset; ++ if (gelf_update_shdr (scn, shdr) == 0) ++ error (1, 0, "Couldn't update shdr: %s\n", ++ elf_errmsg (-1)); ++ } ++ } ++ } ++ ++ /* Position the shdrs after the last (unallocated) section. */ ++ const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT); ++ GElf_Off new_offset = ((last_offset + offsize - 1) ++ & ~((GElf_Off) (offsize - 1))); ++ if (dso->ehdr.e_shoff != new_offset) ++ { ++ dso->ehdr.e_shoff = new_offset; ++ if (gelf_update_ehdr (elf, &dso->ehdr) == 0) ++ error (1, 0, "Couldn't update ehdr: %s\n", elf_errmsg (-1)); ++ } ++ } ++ ++ if (elf_update (dso->elf, ELF_C_NULL) < 0) ++ { ++ fprintf (stderr, "Failed to update file: %s\n", ++ elf_errmsg (elf_errno ())); ++ exit (1); ++ } ++ + if (do_build_id && build_id != NULL) + handle_build_id (dso, build_id, build_id_offset, build_id_size); + +@@ -1697,6 +2757,11 @@ main (int argc, char *argv[]) + /* Restore old access rights */ + chmod (file, stat_buf.st_mode); + ++ free ((char *) dso->filename); ++ destroy_strings (&dso->strings); ++ destroy_lines (&dso->lines); ++ free (dso); ++ + poptFreeContext (optCon); + + return 0; +-- +2.13.2 + diff --git a/0013-missing_build_ids_terminate_build.patch b/0013-missing_build_ids_terminate_build.patch deleted file mode 100644 index 95dc37a..0000000 --- a/0013-missing_build_ids_terminate_build.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/build/files.c b/build/files.c -index 26f53bd..8b516c6 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1699,7 +1699,11 @@ static int generateBuildIDs(FileList fl) - if (build_id_links == BUILD_IDS_NONE || rc != 0) - return rc; - -- int terminate = rpmExpandNumeric("%{?_missing_build_ids_terminate_build}"); -+ /* Historically we have only checked build_ids when __debug_package -+ was defined. So don't terminate the build if __debug_package is -+ unset, even when _missing_build_ids_terminate_build is. */ -+ int terminate = (rpmExpandNumeric("%{?_missing_build_ids_terminate_build}") -+ && rpmExpandNumeric("%{?__debug_package}")); - - /* Collect and check all build-ids for ELF files in this package. */ - int needMain = 0; diff --git a/0014-Add-option-to-have-unique-debug-source-dirs-across-v.patch b/0014-Add-option-to-have-unique-debug-source-dirs-across-v.patch new file mode 100644 index 0000000..05b1625 --- /dev/null +++ b/0014-Add-option-to-have-unique-debug-source-dirs-across-v.patch @@ -0,0 +1,292 @@ +From 0febf191cc874a822f045c24587d412e4d0ec33c Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 28 Feb 2017 21:34:34 +0100 +Subject: [PATCH 14/49] Add option to have unique debug source dirs across + version/release/arch. + +Introduce a new macro _unique_debug_srcs that when set will pass +--unique-debug-src-base "%{name}" to find-debuginfo.sh which will +move sources into a unique "--." directory +under /usr/src/debug/ and makes debugedit rewrite the source paths +in the debuginfo to use that unique directory name. + +Traditionally the debug src dir was named after the builddir which +was defined through the %setup macro which used the -n name argument +to define the builddir name and source archive to use. The builddir +might not be unique though between package versions. + +Now that debugedit doesn't have strict base and dest dir length +restrictions for rewriting the source dir paths this can now be made +more flexible. + +The added testcases show the difference between the old and new way. +The hello2.spec file defines the name of the package as hello2, but +uses the %setup marcro with -n hello-1.0 to use the hello-1.0.tar.gz +archive. This would traditionally result in a hello-1.0 builddir +which would be moved under /usr/src/debug. Possibly conflicting +with any other package (version) that used the same builddir name. +When defining _unique_debug_srcs to 1 that builddir will be moved +to --. instead (hello2-1.0-1.). + +The testcases check that both the actual package source filess under +/usr/debug/src/ and the source paths as found in the .debug files are +under the traditional or new unique directory names depending on whether +the new _unique_debug_srcs macro is defined. + +Signed-off-by: Mark Wielaard +(cherry picked from commit b32e980611c45a46e95fa8864b6faf0c0d732ddb) + +Conflicts: + macros.in + scripts/find-debuginfo.sh +--- + macros.in | 8 ++++- + scripts/find-debuginfo.sh | 35 ++++++++++++++++++--- + tests/rpmbuild.at | 80 +++++++++++++++++++++++++++++++++++++++++++++++ + tests/rpmbuildid.at | 5 +++ + 4 files changed, 123 insertions(+), 5 deletions(-) + +diff --git a/macros.in b/macros.in +index 4d9028254..e48ef60c8 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ + %{nil} + + # Template for debug information sub-package. +@@ -495,6 +495,12 @@ package or when debugging this package.\ + # Requires _unique_build_ids. + %_unique_debug_names 1 + ++# Whether the /usr/debug/src/ directories should be unique between ++# package version, release and architecture. If set to 1 this will pass ++# --unique-debug-src-base "%{name}" to find-debuginfo.sh to name the ++# directory under /usr/debug/src as --. ++%_unique_debug_srcs 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 3653c4848..1420ef6cd 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -67,6 +67,9 @@ ver_rel= + # Arch given by --unique-debug-arch + unique_debug_arch= + ++# Base given by --unique-debug-src-base ++unique_debug_src_base= ++ + BUILDDIR=. + out=debugfiles.list + nout=0 +@@ -94,6 +97,10 @@ while [ $# -gt 0 ]; do + unique_debug_arch=$2 + shift + ;; ++ --unique-debug-src-base) ++ unique_debug_src_base=$2 ++ shift ++ ;; + -g) + strip_g=true + ;; +@@ -137,6 +144,11 @@ if test -z "$ver_rel" -a -n "$unique_debug_arch"; then + exit 2 + fi + ++if test -z "$unique_debug_arch" -a -n "$unique_debug_src_base"; then ++ echo >&2 "*** ERROR: --unique-debug-src-base (${unique_debug_src_base}) needs --unique-debug-arch (${unique_debug_arch})" ++ exit 2 ++fi ++ + i=0 + while ((i < nout)); do + outs[$i]="$BUILDDIR/${outs[$i]}" +@@ -291,7 +303,14 @@ while read nlinks inum f; do + 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 \ ++ # See also cpio SOURCEFILE copy. Directories must match up. ++ debug_base_name="$RPM_BUILD_DIR" ++ debug_dest_name="/usr/src/debug" ++ if [ ! -z "$unique_debug_src_base" ]; then ++ debug_base_name="$BUILDDIR" ++ debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" ++ fi ++ id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ + -i $build_id_seed -l "$SOURCEFILE" "$f") || exit + if [ $nlinks -gt 1 ]; then + eval linkedid_$inum=\$id +@@ -388,11 +407,19 @@ do + done + + if [ -s "$SOURCEFILE" ]; then +- mkdir -p "${RPM_BUILD_ROOT}/usr/src/debug" ++ # See also debugedit invocation. Directories must match up. ++ debug_base_name="$RPM_BUILD_DIR" ++ debug_dest_name="/usr/src/debug" ++ if [ ! -z "$unique_debug_src_base" ]; then ++ debug_base_name="$BUILDDIR" ++ debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" ++ fi ++ ++ mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" + LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(|)$' | +- (cd "$RPM_BUILD_DIR"; cpio -pd0mL "${RPM_BUILD_ROOT}/usr/src/debug") ++ (cd "${debug_base_name}"; cpio -pd0mL "${RPM_BUILD_ROOT}${debug_dest_name}") + # stupid cpio creates new directories in mode 0700, fixup +- find "${RPM_BUILD_ROOT}/usr/src/debug" -type d -print0 | ++ find "${RPM_BUILD_ROOT}${debug_dest_name}" -type d -print0 | + xargs --no-run-if-empty -0 chmod a+rx + fi + +diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at +index 0a2c01efe..a46822f52 100644 +--- a/tests/rpmbuild.at ++++ b/tests/rpmbuild.at +@@ -399,6 +399,7 @@ 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_debug_names" \ ++ --undefine "_unique_debug_srcs" \ + -ba "${abs_srcdir}"/data/SPECS/hello2.spec + + # The debuginfo package should contain a .debug file for each binary +@@ -701,3 +702,82 @@ readelf -S ./usr/lib/debug/usr/local/bin/hello2*.debug \ + [], + [ignore]) + AT_CLEANUP ++ ++# ------------------------------ ++# Check that a debug source is in a "unique" directory when requested. ++AT_SETUP([rpmbuild debuginfo unique debug src dir]) ++AT_KEYWORDS([build] [debuginfo]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Build a package that has some debuginfo ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Note that the spec defines hello2 as name, but the source is hello-1.0. ++# Disable dwz to make debuginfo path rewrite checking easier. ++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 "_find_debuginfo_dwz_opts" \ ++ --define "_unique_debug_srcs 1" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2.spec ++ ++# Unpack the debuginfo rpms so we can check the .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# Check that the source path is "unique" ++# Drop the final arch prefix to make the test arch-independent. ++ls ./usr/src/debug/ | cut -f1,2 -d\. ++ ++# Check that the source path has been rewritten in the .debug file. ++# Drop the final arch prefix to make the test arch-independent. ++readelf --debug-dump=info ./usr/lib/debug/usr/local/bin/hello2*.debug \ ++ | grep comp_dir | cut -f5- -d/ | cut -f1,2 -d\. ++], ++[0], ++[hello2-1.0-1 ++hello2-1.0-1 ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ ++# Check that a debug source is NOT in a "unique" directory when not requested. ++# It will be in the "build directory" name under /usr/src/debug. ++AT_SETUP([rpmbuild debuginfo no unique debug src dir]) ++AT_KEYWORDS([build] [debuginfo]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Build a package that has some debuginfo ++cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES ++ ++# Note that the spec defines hello2 as name, but the source is hello-1.0. ++# Disable dwz to make debuginfo path rewrite checking easier. ++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 "_find_debuginfo_dwz_opts" \ ++ --undefine "_unique_debug_srcs" \ ++ -ba "${abs_srcdir}"/data/SPECS/hello2.spec ++ ++# Unpack the debuginfo rpms so we can check the .debug files. ++rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \ ++ | cpio -diu --quiet ++ ++# Check that the source path is "unique" ++ls ./usr/src/debug/ ++ ++# Check that the source path has been rewritten in the .debug file. ++readelf --debug-dump=info ./usr/lib/debug/usr/local/bin/hello2*.debug \ ++ | grep comp_dir | cut -f5- -d/ ++], ++[0], ++[hello-1.0 ++hello-1.0 ++], ++[ignore]) ++AT_CLEANUP +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +index ede1181e1..15c06202f 100644 +--- a/tests/rpmbuildid.at ++++ b/tests/rpmbuildid.at +@@ -71,6 +71,7 @@ run rpmbuild \ + --rcfile=${abs_top_builddir}/rpmrc \ + --define="_build_id_links alldebug" \ + --undefine "_unique_debug_names" \ ++ --undefine "_unique_debug_srcs" \ + --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec + + # There should be zero build-id files in the main package +@@ -257,6 +258,7 @@ run rpmbuild \ + --rcfile=${abs_top_builddir}/rpmrc \ + --define="_build_id_links separate" \ + --undefine "_unique_debug_names" \ ++ --undefine "_unique_debug_srcs" \ + --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec + + # There should be one build-id files in the main and debuginfo package +@@ -441,6 +443,7 @@ run rpmbuild \ + --rcfile=${abs_top_builddir}/rpmrc \ + --define="_build_id_links compat" \ + --undefine "_unique_debug_names" \ ++ --undefine "_unique_debug_srcs" \ + --quiet -ba "${abs_srcdir}"/data/SPECS/hello.spec + + # There should be one build-id files in the main and debuginfo package. +@@ -1125,6 +1128,7 @@ run rpmbuild --quiet \ + --rcfile=${abs_top_builddir}/rpmrc \ + --undefine="_unique_build_ids" \ + --undefine="_unique_debug_names" \ ++ --undefine="_unique_debug_srcs" \ + -ba "${abs_srcdir}"/data/SPECS/hello.spec + + rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm \ +@@ -1145,6 +1149,7 @@ run rpmbuild --quiet \ + --rcfile=${abs_top_builddir}/rpmrc \ + --undefine="_unique_build_ids" \ + --undefine="_unique_debug_names" \ ++ --undefine="_unique_debug_srcs" \ + -ba "${abs_srcdir}"/data/SPECS/hello-r2.spec + + rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ +-- +2.13.2 + diff --git a/0014-generateBuildIDs-Fix-error-handling.patch b/0014-generateBuildIDs-Fix-error-handling.patch deleted file mode 100644 index 9878465..0000000 --- a/0014-generateBuildIDs-Fix-error-handling.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 7e053a6d843b141fc6b5a89d050082233ed034d6 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Thu, 9 Mar 2017 22:13:01 +0100 -Subject: [PATCH] generateBuildIDs: Fix error handling. - -commit e6bdf7 made it so that we don't give a warning or error message -for non-kernel ET_REL object files with missing or bad build-ids. But -we still (unintentionally) failed generateBuildIDs which made us skip -generating the cpioList causing an obscure failure message. - -Move the sanity check earlier so we don't process such object files at -all. And if there is any real error from generateBuildIDs give a clear -error message and explicitly set processingFailed. - -Signed-off-by: Mark Wielaard ---- - build/files.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/build/files.c b/build/files.c -index b19abf2..fef0c69 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1686,10 +1686,16 @@ static int generateBuildIDs(FileList fl) - if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { - int fd = open (flp->diskPath, O_RDONLY); - if (fd >= 0) { -+ /* Only real ELF files, that are ET_EXEC, ET_DYN or -+ kernel modules (ET_REL files with names ending in .ko) -+ should have build-ids. */ - GElf_Ehdr ehdr; - Elf *elf = elf_begin (fd, ELF_C_READ, NULL); - if (elf != NULL && elf_kind(elf) == ELF_K_ELF -- && gelf_getehdr(elf, &ehdr) != NULL) { -+ && gelf_getehdr(elf, &ehdr) != NULL -+ && (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN -+ || (ehdr.e_type == ET_REL -+ && rpmFileHasSuffix (flp->diskPath, ".ko")))) { - const void *build_id; - ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id); - /* len == -1 means error. Zero means no -@@ -1738,11 +1744,6 @@ static int generateBuildIDs(FileList fl) - _("error reading build-id in %s: %s\n"), - flp->diskPath, elf_errmsg (-1)); - } else if (len == 0) { -- /* Only ET_EXEC, ET_DYN or kernel modules -- have build-ids. */ -- if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN -- || (ehdr.e_type == ET_REL -- && rpmFileHasSuffix (flp->diskPath, ".ko"))) - rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, - _("Missing build-id in %s\n"), - flp->diskPath); -@@ -2354,8 +2355,11 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - goto exit; - - #if HAVE_LIBDW -- if (generateBuildIDs (&fl) != 0) -+ if (generateBuildIDs (&fl) != 0) { -+ rpmlog(RPMLOG_ERR, _("Generating build-id links failed\n")); -+ fl.processingFailed = 1; - goto exit; -+ } - #endif - - /* Verify that file attributes scope over hardlinks correctly. */ --- -1.8.3.1 - diff --git a/0015-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch b/0015-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch new file mode 100644 index 0000000..e6f282f --- /dev/null +++ b/0015-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch @@ -0,0 +1,53 @@ +From 590081d625b22b5845015949ecb184989377c928 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 9 Mar 2017 09:34:01 +0100 +Subject: [PATCH 15/49] generateBuildIDs: Don't warn or error for object files + without build-id. + +Only loadable ELF images (executables, shared libraries, kernel modules) +should have build-ids. So don't warn or error out when an object file is +found without one. + +Signed-off-by: Mark Wielaard +(cherry picked from commit e6bdf7a807ea5ca30bc467345dd1e07198945603) +--- + build/files.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/build/files.c b/build/files.c +index ca041764f..274b38c62 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1682,8 +1682,10 @@ static int generateBuildIDs(FileList fl) + if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { + int fd = open (flp->diskPath, O_RDONLY); + if (fd >= 0) { ++ GElf_Ehdr ehdr; + Elf *elf = elf_begin (fd, ELF_C_READ, NULL); +- if (elf != NULL && elf_kind(elf) == ELF_K_ELF) { ++ if (elf != NULL && elf_kind(elf) == ELF_K_ELF ++ && gelf_getehdr(elf, &ehdr) != NULL) { + const void *build_id; + ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id); + /* len == -1 means error. Zero means no +@@ -1732,9 +1734,14 @@ static int generateBuildIDs(FileList fl) + _("error reading build-id in %s: %s\n"), + flp->diskPath, elf_errmsg (-1)); + } else if (len == 0) { +- rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, +- _("Missing build-id in %s\n"), +- flp->diskPath); ++ /* Only ET_EXEC, ET_DYN or kernel modules ++ have build-ids. */ ++ if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN ++ || (ehdr.e_type == ET_REL ++ && rpmFileHasSuffix (flp->diskPath, ".ko"))) ++ rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, ++ _("Missing build-id in %s\n"), ++ flp->diskPath); + } else { + rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, + (len < 16 +-- +2.13.2 + diff --git a/0015-reset-buildid-file-attrs.patch b/0015-reset-buildid-file-attrs.patch deleted file mode 100644 index fcc9018..0000000 --- a/0015-reset-buildid-file-attrs.patch +++ /dev/null @@ -1,57 +0,0 @@ -diff --git a/build/files.c b/build/files.c -index 6021643..9479e6e 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1797,6 +1797,7 @@ static int generateBuildIDs(FileList fl) - char *mainiddir = NULL; - char *debugiddir = NULL; - if (rc == 0) { -+ char *attrstr; - /* Add .build-id directories to hold the subdirs/symlinks. */ - #define BUILD_ID_DIR "/usr/lib/.build-id" - #define DEBUG_ID_DIR "/usr/lib/debug/.build-id" -@@ -1804,6 +1805,18 @@ static int generateBuildIDs(FileList fl) - mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL); - debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL); - -+ /* Make sure to reset all file flags to defaults. -+ Uses parseForAttr to reset ar, arFlags, and specdFlags. -+ Note that parseForAttr pokes at the attrstr, so we cannot -+ just pass a static string. */ -+ fl->def.verifyFlags = RPMVERIFY_ALL; -+ fl->cur.verifyFlags = RPMVERIFY_ALL; -+ fl->def.specdFlags |= SPECD_VERIFY; -+ fl->cur.specdFlags |= SPECD_VERIFY; -+ attrstr = xstrdup ("%defattr(-,root,root)"); -+ parseForAttr(fl->pool, attrstr, 1, &fl->def); -+ free (attrstr); -+ - /* Supported, but questionable. */ - if (needMain && needDbg) - rpmlog(RPMLOG_WARNING, -@@ -1813,8 +1826,12 @@ static int generateBuildIDs(FileList fl) - if ((rc = rpmioMkpath(mainiddir, 0755, -1, -1)) != 0) { - rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, mainiddir); - } else { -+ rasprintf (&attrstr, "%s %s", "%attr(-,root,root) ", -+ mainiddir); -+ parseForAttr(fl->pool, attrstr, 0, &fl->cur); - fl->cur.isDir = 1; - rc = addFile(fl, mainiddir, NULL); -+ free (attrstr); - } - } - -@@ -1822,8 +1839,12 @@ static int generateBuildIDs(FileList fl) - if ((rc = rpmioMkpath(debugiddir, 0755, -1, -1)) != 0) { - rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, debugiddir); - } else { -+ rasprintf (&attrstr, "%s %s", "%attr(-,root,root) ", -+ debugiddir); -+ parseForAttr(fl->pool, attrstr, 0, &fl->cur); - fl->cur.isDir = 1; - rc = addFile(fl, debugiddir, NULL); -+ free (attrstr); - } - } - } diff --git a/0016-build-files.c-Unset-__debug_package-implies-missing-.patch b/0016-build-files.c-Unset-__debug_package-implies-missing-.patch new file mode 100644 index 0000000..99e6646 --- /dev/null +++ b/0016-build-files.c-Unset-__debug_package-implies-missing-.patch @@ -0,0 +1,36 @@ +From 5bc9efa303efe933b02cc8679ef3134668839831 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 9 Mar 2017 15:52:12 +0100 +Subject: [PATCH 16/49] build/files.c: Unset __debug_package implies missing + build-ids aren't fatal. + +Historically we have only checked build_ids when __debug_package was +defined. So don't terminate the build if __debug_package is unset, even +when _missing_build_ids_terminate_build is. Only warn. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 22260d3580fcdafa5579128401adf1a05d36f316) +--- + build/files.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/build/files.c b/build/files.c +index 274b38c62..b19abf299 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1672,7 +1672,11 @@ static int generateBuildIDs(FileList fl) + if (build_id_links == BUILD_IDS_NONE || rc != 0) + return rc; + +- int terminate = rpmExpandNumeric("%{?_missing_build_ids_terminate_build}"); ++ /* Historically we have only checked build_ids when __debug_package ++ was defined. So don't terminate the build if __debug_package is ++ unset, even when _missing_build_ids_terminate_build is. */ ++ int terminate = (rpmExpandNumeric("%{?_missing_build_ids_terminate_build}") ++ && rpmExpandNumeric("%{?__debug_package}")); + + /* Collect and check all build-ids for ELF files in this package. */ + int needMain = 0; +-- +2.13.2 + diff --git a/0016-debugedit-replace-files.patch b/0016-debugedit-replace-files.patch deleted file mode 100644 index c1d5dcb..0000000 --- a/0016-debugedit-replace-files.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/tools/debugedit.c b/tools/debugedit.c -index 4798c63..87a423f 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -1185,7 +1185,7 @@ edit_dwarf2_line (DSO *dso) - { - const char *file = (const char *) optr; - const char *file_path = NULL; -- if (t->replace_dirs) -+ if (t->replace_files) - { - file_path = skip_dir_prefix (file, base_dir); - if (file_path != NULL) diff --git a/0017-do-not-process-buildi-ds-for-noarch.patch b/0017-do-not-process-buildi-ds-for-noarch.patch deleted file mode 100644 index 76a9727..0000000 --- a/0017-do-not-process-buildi-ds-for-noarch.patch +++ /dev/null @@ -1,41 +0,0 @@ -From d406bde3e914cae2d794bbaab66aad6b7038b30e Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Fri, 17 Mar 2017 10:51:36 +0100 -Subject: [PATCH] build/files.c (processPackageFiles): Don't call - generateBuildIDs for noarch. - -We don't want to do build-id processing for noarch packages. It might be -that noarch packages do contain architecture depended files, but those are -already handled by processBinaryFiles. - -Signed-off-by: Mark Wielaard ---- - build/files.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/build/files.c b/build/files.c -index 6021643..35b2dd0 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -2384,10 +2384,14 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - goto exit; - - #if HAVE_LIBDW -- if (generateBuildIDs (&fl) != 0) { -- rpmlog(RPMLOG_ERR, _("Generating build-id links failed\n")); -- fl.processingFailed = 1; -- goto exit; -+ /* Check build-ids and add build-ids links for files to package list. */ -+ const char *arch = headerGetString(pkg->header, RPMTAG_ARCH); -+ if (!rstreq(arch, "noarch")) { -+ if (generateBuildIDs (&fl) != 0) { -+ rpmlog(RPMLOG_ERR, _("Generating build-id links failed\n")); -+ fl.processingFailed = 1; -+ goto exit; -+ } - } - #endif - --- -1.8.3.1 - diff --git a/0017-generateBuildIDs-Fix-error-handling.patch b/0017-generateBuildIDs-Fix-error-handling.patch new file mode 100644 index 0000000..b3885d3 --- /dev/null +++ b/0017-generateBuildIDs-Fix-error-handling.patch @@ -0,0 +1,70 @@ +From fa61c840ba6be18c6579b247605634c1e2a320f8 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 9 Mar 2017 22:13:01 +0100 +Subject: [PATCH 17/49] generateBuildIDs: Fix error handling. + +commit e6bdf7 made it so that we don't give a warning or error message +for non-kernel ET_REL object files with missing or bad build-ids. But +we still (unintentionally) failed generateBuildIDs which made us skip +generating the cpioList causing an obscure failure message. + +Move the sanity check earlier so we don't process such object files at +all. And if there is any real error from generateBuildIDs give a clear +error message and explicitly set processingFailed. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 5bd77379eee167fbdb8d139dc9ab2da74f2a544f) +--- + build/files.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/build/files.c b/build/files.c +index b19abf299..fef0c6960 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1686,10 +1686,16 @@ static int generateBuildIDs(FileList fl) + if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { + int fd = open (flp->diskPath, O_RDONLY); + if (fd >= 0) { ++ /* Only real ELF files, that are ET_EXEC, ET_DYN or ++ kernel modules (ET_REL files with names ending in .ko) ++ should have build-ids. */ + GElf_Ehdr ehdr; + Elf *elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf != NULL && elf_kind(elf) == ELF_K_ELF +- && gelf_getehdr(elf, &ehdr) != NULL) { ++ && gelf_getehdr(elf, &ehdr) != NULL ++ && (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN ++ || (ehdr.e_type == ET_REL ++ && rpmFileHasSuffix (flp->diskPath, ".ko")))) { + const void *build_id; + ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id); + /* len == -1 means error. Zero means no +@@ -1738,11 +1744,6 @@ static int generateBuildIDs(FileList fl) + _("error reading build-id in %s: %s\n"), + flp->diskPath, elf_errmsg (-1)); + } else if (len == 0) { +- /* Only ET_EXEC, ET_DYN or kernel modules +- have build-ids. */ +- if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN +- || (ehdr.e_type == ET_REL +- && rpmFileHasSuffix (flp->diskPath, ".ko"))) + rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, + _("Missing build-id in %s\n"), + flp->diskPath); +@@ -2354,8 +2355,11 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + goto exit; + + #if HAVE_LIBDW +- if (generateBuildIDs (&fl) != 0) ++ if (generateBuildIDs (&fl) != 0) { ++ rpmlog(RPMLOG_ERR, _("Generating build-id links failed\n")); ++ fl.processingFailed = 1; + goto exit; ++ } + #endif + + /* Verify that file attributes scope over hardlinks correctly. */ +-- +2.13.2 + diff --git a/0018-Make-sure-to-reset-file-attributes-for-generated-bui.patch b/0018-Make-sure-to-reset-file-attributes-for-generated-bui.patch new file mode 100644 index 0000000..06535cb --- /dev/null +++ b/0018-Make-sure-to-reset-file-attributes-for-generated-bui.patch @@ -0,0 +1,194 @@ +From 651264c51dfb13bf78bb969a429719f301497631 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 15 Mar 2017 20:07:29 +0100 +Subject: [PATCH 18/49] Make sure to reset file attributes for generated + build-id directories. + +[Note this patch is currently being tested in Fedora. See bug below.] + +When creating the build-id directories we should reset the file attributes +to the defaults. Otherwise if the file list contained an %attr or %defattr +the directories would come out with the wrong mode. + +Includes a testcase based on a spec by Igor Gnatenko that fails before +and Check that build-id directories are created with the right permissions +even if the spec file sets attrs explicitly. + +https://bugzilla.redhat.com/show_bug.cgi?id=1432372 + +Signed-off-by: Mark Wielaard +(cherry picked from commit b91dc6106e360f13ff365dfac247191942039152) +--- + build/files.c | 21 +++++++++++++++++++ + tests/Makefile.am | 2 ++ + tests/data/SOURCES/hello.c | 8 +++++++ + tests/data/SPECS/hello-attr-buildid.spec | 27 ++++++++++++++++++++++++ + tests/rpmbuildid.at | 36 ++++++++++++++++++++++++++++++++ + 5 files changed, 94 insertions(+) + create mode 100644 tests/data/SOURCES/hello.c + create mode 100644 tests/data/SPECS/hello-attr-buildid.spec + +diff --git a/build/files.c b/build/files.c +index fef0c6960..728a44ba2 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1770,6 +1770,7 @@ static int generateBuildIDs(FileList fl) + char *mainiddir = NULL; + char *debugiddir = NULL; + if (rc == 0) { ++ char *attrstr; + /* Add .build-id directories to hold the subdirs/symlinks. */ + #define BUILD_ID_DIR "/usr/lib/.build-id" + #define DEBUG_ID_DIR "/usr/lib/debug/.build-id" +@@ -1777,6 +1778,18 @@ static int generateBuildIDs(FileList fl) + mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL); + debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL); + ++ /* Make sure to reset all file flags to defaults. ++ Uses parseForAttr to reset ar, arFlags, and specdFlags. ++ Note that parseForAttr pokes at the attrstr, so we cannot ++ just pass a static string. */ ++ fl->def.verifyFlags = RPMVERIFY_ALL; ++ fl->cur.verifyFlags = RPMVERIFY_ALL; ++ fl->def.specdFlags |= SPECD_VERIFY; ++ fl->cur.specdFlags |= SPECD_VERIFY; ++ attrstr = xstrdup ("%defattr(-,root,root)"); ++ parseForAttr(fl->pool, attrstr, 1, &fl->def); ++ free (attrstr); ++ + /* Supported, but questionable. */ + if (needMain && needDbg) + rpmlog(RPMLOG_WARNING, +@@ -1786,8 +1799,12 @@ static int generateBuildIDs(FileList fl) + if ((rc = rpmioMkpath(mainiddir, 0755, -1, -1)) != 0) { + rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, mainiddir); + } else { ++ rasprintf (&attrstr, "%s %s", "%attr(-,root,root) ", ++ mainiddir); ++ parseForAttr(fl->pool, attrstr, 0, &fl->cur); + fl->cur.isDir = 1; + rc = addFile(fl, mainiddir, NULL); ++ free (attrstr); + } + } + +@@ -1795,8 +1812,12 @@ static int generateBuildIDs(FileList fl) + if ((rc = rpmioMkpath(debugiddir, 0755, -1, -1)) != 0) { + rpmlog(RPMLOG_ERR, "%s %s: %m\n", errdir, debugiddir); + } else { ++ rasprintf (&attrstr, "%s %s", "%attr(-,root,root) ", ++ debugiddir); ++ parseForAttr(fl->pool, attrstr, 0, &fl->cur); + fl->cur.isDir = 1; + rc = addFile(fl, debugiddir, NULL); ++ free (attrstr); + } + } + } +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 10555ce9a..d9586da1d 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -68,6 +68,8 @@ EXTRA_DIST += data/RPMS/hello-2.0-1.i686.rpm + EXTRA_DIST += data/RPMS/hello-2.0-1.x86_64.rpm + EXTRA_DIST += data/SRPMS/foo-1.0-1.src.rpm + EXTRA_DIST += data/SRPMS/hello-1.0-1.src.rpm ++EXTRA_DIST += data/SOURCES/hello.c ++EXTRA_DIST += data/SPECS/hello-attr-buildid.spec + + # testsuite voodoo + AUTOTEST = $(AUTOM4TE) --language=autotest +diff --git a/tests/data/SOURCES/hello.c b/tests/data/SOURCES/hello.c +new file mode 100644 +index 000000000..020484eed +--- /dev/null ++++ b/tests/data/SOURCES/hello.c +@@ -0,0 +1,8 @@ ++#include ++ ++int ++main (void) ++{ ++ printf ("Hello, world!\n"); ++ return 0; ++} +diff --git a/tests/data/SPECS/hello-attr-buildid.spec b/tests/data/SPECS/hello-attr-buildid.spec +new file mode 100644 +index 000000000..cdab95fff +--- /dev/null ++++ b/tests/data/SPECS/hello-attr-buildid.spec +@@ -0,0 +1,27 @@ ++Name: test ++Version: 1.0 ++Release: 1 ++Summary: Test ++ ++License: Public Domain ++URL: https://fedoraproject.org ++Source: hello.c ++ ++%description ++%{summary}. ++ ++%prep ++%autosetup -c -D -T ++cp -a %{S:0} . ++ ++%build ++gcc -g hello.c -o hello ++ ++%install ++mkdir -p %{buildroot}%{_bindir} ++install -D -p -m 0755 -t %{buildroot}%{_bindir} hello ++ ++%files ++%attr(644,root,root) %{_bindir}/hello ++ ++%changelog +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +index 15c06202f..1cae26dbf 100644 +--- a/tests/rpmbuildid.at ++++ b/tests/rpmbuildid.at +@@ -1166,3 +1166,39 @@ if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi + ], + [ignore]) + AT_CLEANUP ++ ++# ------------------------------ ++# Check that build-id directories are created with the right permissions ++# even if the spec file sets attrs explicitly. ++AT_SETUP([rpmbuild buildid attrs]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello.c ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links compat" \ ++ --define "_unique_debug_names 1" \ ++ --define "_unique_debug_srcs 1" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello-attr-buildid.spec ++ ++run rpm -qp --qf "[[%{filenames} %{filemodes:perms}\n]]" \ ++ ${abs_builddir}/testing/build/RPMS/*/test-1.0-1*rpm \ ++ | grep "build-id d" ++ ++run rpm -qp --qf "[[%{filenames} %{filemodes:perms}\n]]" \ ++ ${abs_builddir}/testing/build/RPMS/*/test-debuginfo-1.0-1*rpm \ ++ | grep "build-id d" ++], ++[0], ++[/usr/lib/.build-id drwxr-xr-x ++/usr/lib/debug/.build-id drwxr-xr-x ++], ++[ignore]) ++AT_CLEANUP +-- +2.13.2 + diff --git a/0018-update-build-id-endian.patch b/0018-update-build-id-endian.patch deleted file mode 100644 index 18690a3..0000000 --- a/0018-update-build-id-endian.patch +++ /dev/null @@ -1,91 +0,0 @@ -diff --git a/tools/debugedit.c b/tools/debugedit.c -index 4798c63..47e5bbf 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -2581,40 +2581,25 @@ main (int argc, char *argv[]) - break; - case SHT_NOTE: - if (do_build_id -- && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC)) -+ && build_id == 0 && (dso->shdr[i].sh_flags & SHF_ALLOC)) - { - /* Look for a build-ID note here. */ -+ size_t off = 0; -+ GElf_Nhdr nhdr; -+ size_t name_off; -+ size_t desc_off; - Elf_Data *data = elf_getdata (elf_getscn (dso->elf, i), NULL); -- Elf32_Nhdr nh; -- Elf_Data dst = -- { -- .d_version = EV_CURRENT, .d_type = ELF_T_NHDR, -- .d_buf = &nh, .d_size = sizeof nh -- }; -- Elf_Data src = dst; -- src.d_buf = data->d_buf; -- assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); -- while ((char *) data->d_buf + data->d_size - -- (char *) src.d_buf > (int) sizeof nh -- && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA])) -- { -- Elf32_Word len = sizeof nh + nh.n_namesz; -- len = (len + 3) & ~3; -- -- if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3 -- && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU")) -- { -- build_id = data; -- build_id_offset = (char *) src.d_buf + len - -- (char *) data->d_buf; -- build_id_size = nh.n_descsz; -- break; -- } -- -- len += nh.n_descsz; -- len = (len + 3) & ~3; -- src.d_buf = (char *) src.d_buf + len; -- } -+ while ((off = gelf_getnote (data, off, -+ &nhdr, &name_off, &desc_off)) > 0) -+ if (nhdr.n_type == NT_GNU_BUILD_ID -+ && nhdr.n_namesz == sizeof "GNU" -+ && (memcmp ((char *)data->d_buf + name_off, "GNU", -+ sizeof "GNU") == 0)) -+ { -+ build_id = data; -+ build_id_offset = desc_off; -+ build_id_size = nhdr.n_descsz; -+ } - } - break; - default: -@@ -2622,6 +2607,20 @@ main (int argc, char *argv[]) - } - } - -+ /* Normally we only need to explicitly update the section headers -+ and data when any section data changed size. But because of a bug -+ in elfutils before 0.169 we will have to update and write out all -+ section data if any data has changed (when ELF_F_LAYOUT was -+ set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ -+ bool need_update = need_strp_update || need_stmt_update; -+ -+#if !_ELFUTILS_PREREQ (0, 169) -+ /* string replacements or build_id updates don't change section size. */ -+ need_update = (need_update -+ || need_string_replacement -+ || (do_build_id && build_id != NULL)); -+#endif -+ - /* We might have changed the size of some debug sections. If so make - sure the section headers are updated and the data offsets are - correct. We set ELF_F_LAYOUT above because we don't want libelf -@@ -2631,7 +2630,7 @@ main (int argc, char *argv[]) - anything for the phdrs allocated sections. Keep the offset of - allocated sections so they are at the same place in the file. Add - unallocated ones after the allocated ones. */ -- if (dso->phnum != 0 && (need_strp_update || need_stmt_update)) -+ if (dso->phnum != 0 && need_update) - { - Elf *elf = dso->elf; - GElf_Off last_offset; diff --git a/0019-fix-sed-build-id-match-test.patch b/0019-fix-sed-build-id-match-test.patch deleted file mode 100644 index cdbf6f4..0000000 --- a/0019-fix-sed-build-id-match-test.patch +++ /dev/null @@ -1,268 +0,0 @@ -commit f0a581925ad4c948dc58cc8f9a55399ad8de351e -Author: Mark Wielaard -Date: Fri Mar 3 23:51:13 2017 +0100 - - tests/tpmbuild.at: Make file sed regexp more strict to extract BuildID. - - In some testcases we extract the BuildID with the file command. - Unfortunately the file command output changed slightly between versions. - Make the sed regexp more strict by only matching a hex-string. - Also properly "escape" [ and ] which inside an AT_CHECK should be [[ and ]]. - - Tested against file versions 5.11, 5.29 and 5.30. - - Signed-off-by: Mark Wielaard - -diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at -index a46822f..dcbdd2c 100644 ---- a/tests/rpmbuild.at -+++ b/tests/rpmbuild.at -@@ -423,11 +423,11 @@ hello2_file=./usr/local/bin/hello2 - test -f $hello_file || echo "no hello file: $hello_file" - test -f $hello2_file || echo "no hello2 file: $hello2_file" - --id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+id2=$(file $hello2_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+id1debug=$(file $hello_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+idmulti=$(file $hello_multi_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" - test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" -@@ -516,11 +516,11 @@ hello2_file=./usr/local/bin/hello2 - test -f $hello_file || echo "no hello file: $hello_file" - test -f $hello2_file || echo "no hello2 file: $hello2_file" - --id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') --idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+id2=$(file $hello2_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+id1debug=$(file $hello_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+idmulti=$(file $hello_multi_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" - test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" -commit 09b5082f1073451423c6d5ebffed781e25472fd6 -Author: Mark Wielaard -Date: Mon Mar 20 09:27:05 2017 +0100 - - tests/rpmbuildid.at: Make file sed regexp more strict to extract BuildID. - - Like commit f0a5819 for rpmbuild.at. In the case of rpmbuildid.at the - sed expression looked to work, but only matched by accident. Make the sed - regexp more strict by only matching a hex-string. And properly "escape" - [ and ] which inside an AT_CHECK should be [[ and ]]. - - Signed-off-by: Mark Wielaard - -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -index 15c0620..1c06ca1 100644 ---- a/tests/rpmbuildid.at -+++ b/tests/rpmbuildid.at -@@ -97,7 +97,7 @@ main_file=./usr/local/bin/hello - test -f "${main_file}" || echo "No main file ${main_file}" - - # Extract the build-id from the main file --id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" - test -L "$id_main_file" || echo "No build-id file $id_main_file" -@@ -120,7 +120,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello.debug - test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file --id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test ${id_main} = ${id_debug} || echo "unequal main and debug id" - -@@ -190,7 +190,7 @@ main_file=./usr/local/bin/hello - test -f "${main_file}" || echo "No main file ${main_file}" - - # Extract the build-id from the main file --id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" - test -L "$id_main_file" || echo "No build-id file $id_main_file" -@@ -213,7 +213,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug - test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file --id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test ${id_main} = ${id_debug} || echo "unequal main and debug id" - -@@ -283,7 +283,7 @@ main_file=./usr/local/bin/hello - test -f "${main_file}" || echo "No main file ${main_file}" - - # Extract the build-id from the main file --id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" - test -L "$id_main_file" || echo "No build-id file $id_main_file" -@@ -306,7 +306,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello.debug - test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file --id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test ${id_main} = ${id_debug} || echo "unequal main and debug id" - -@@ -375,7 +375,7 @@ main_file=./usr/local/bin/hello - test -f "${main_file}" || echo "No main file ${main_file}" - - # Extract the build-id from the main file --id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" - test -L "$id_main_file" || echo "No build-id file $id_main_file" -@@ -398,7 +398,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug - test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file --id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test ${id_main} = ${id_debug} || echo "unequal main and debug id" - -@@ -469,7 +469,7 @@ main_file=./usr/local/bin/hello - test -f "${main_file}" || echo "No main file ${main_file}" - - # Extract the build-id from the main file --id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" - test -L "$id_main_file" || echo "No build-id file $id_main_file" -@@ -492,7 +492,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello.debug - test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file --id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test ${id_main} = ${id_debug} || echo "unequal main and debug id" - -@@ -574,7 +574,7 @@ main_file=./usr/local/bin/hello - test -f "${main_file}" || echo "No main file ${main_file}" - - # Extract the build-id from the main file --id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" - test -L "$id_main_file" || echo "No build-id file $id_main_file" -@@ -597,7 +597,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello-*debug - test -f ${debug_file} || echo "No debug file ${debug_file}" - - # Extract the build-id from the .debug file --id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - test ${id_main} = ${id_debug} || echo "unequal main and debug id" - -@@ -662,7 +662,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file --id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # alldebug not here... - id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" -@@ -732,7 +732,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file --id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # alldebug not here... - id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" -@@ -799,7 +799,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file --id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # separate build-ids split... - id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -@@ -866,7 +866,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file --id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # separate build-ids split... - id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -@@ -930,7 +930,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file --id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # compat build-ids split... - id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -@@ -1009,7 +1009,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ - hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file --id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # compat build-ids split... - id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" -@@ -1084,7 +1084,7 @@ hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file - test -f $hello_file || echo "No $hello_file" --id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # Make sure we generate a new one - rm $hello_file -@@ -1101,7 +1101,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ - - # Extract the build-id from the main file - test -f $hello_file || echo "No $hello_file" --id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id2=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - if test "$id1" == "$id2"; then echo "equal $id1"; else echo "unequal"; fi - ], -@@ -1138,7 +1138,7 @@ hello_file=./usr/local/bin/hello - - # Extract the build-id from the main file - test -f $hello_file || echo "No $hello_file" --id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - # Make sure we generate a new one - rm $hello_file -@@ -1157,7 +1157,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ - - # Extract the build-id from the main file - test -f $hello_file || echo "No $hello_file" --id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') -+id2=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') - - if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi - ], diff --git a/0019-rpmbuild-Reset-attrFlags-in-generateBuildIDs.patch b/0019-rpmbuild-Reset-attrFlags-in-generateBuildIDs.patch new file mode 100644 index 0000000..1658dc1 --- /dev/null +++ b/0019-rpmbuild-Reset-attrFlags-in-generateBuildIDs.patch @@ -0,0 +1,129 @@ +From 20636f4358db0cb85f2251333190626dc2e4ee02 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Fri, 19 May 2017 23:11:39 +0200 +Subject: [PATCH 19/49] rpmbuild: Reset attrFlags in generateBuildIDs. + +Debuginfo directories and files could be marked as configuration files +if the file list ended with a config file. + +Patch by Panu Matilainen. Testcase by me. + +https://bugzilla.redhat.com/show_bug.cgi?id=1449732 + +Signed-off-by: Mark Wielaard +(cherry picked from commit 9d942049cf929d5a053c239cdd64f5b97d182c14) + +Conflicts: + tests/Makefile.am +--- + build/files.c | 2 ++ + tests/Makefile.am | 1 + + tests/data/SPECS/hello-config-buildid.spec | 30 ++++++++++++++++++++++++++++ + tests/rpmbuildid.at | 32 ++++++++++++++++++++++++++++++ + 4 files changed, 65 insertions(+) + create mode 100644 tests/data/SPECS/hello-config-buildid.spec + +diff --git a/build/files.c b/build/files.c +index 728a44ba2..6c0ca39ef 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1782,6 +1782,8 @@ static int generateBuildIDs(FileList fl) + Uses parseForAttr to reset ar, arFlags, and specdFlags. + Note that parseForAttr pokes at the attrstr, so we cannot + just pass a static string. */ ++ fl->cur.attrFlags = 0; ++ fl->def.attrFlags = 0; + fl->def.verifyFlags = RPMVERIFY_ALL; + fl->cur.verifyFlags = RPMVERIFY_ALL; + fl->def.specdFlags |= SPECD_VERIFY; +diff --git a/tests/Makefile.am b/tests/Makefile.am +index d9586da1d..83586ec67 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -70,6 +70,7 @@ EXTRA_DIST += data/SRPMS/foo-1.0-1.src.rpm + EXTRA_DIST += data/SRPMS/hello-1.0-1.src.rpm + EXTRA_DIST += data/SOURCES/hello.c + EXTRA_DIST += data/SPECS/hello-attr-buildid.spec ++EXTRA_DIST += data/SPECS/hello-config-buildid.spec + + # testsuite voodoo + AUTOTEST = $(AUTOM4TE) --language=autotest +diff --git a/tests/data/SPECS/hello-config-buildid.spec b/tests/data/SPECS/hello-config-buildid.spec +new file mode 100644 +index 000000000..ca2d30db3 +--- /dev/null ++++ b/tests/data/SPECS/hello-config-buildid.spec +@@ -0,0 +1,30 @@ ++Name: test ++Version: 1.0 ++Release: 1 ++Summary: Test ++ ++License: Public Domain ++URL: https://fedoraproject.org ++Source: hello.c ++ ++%description ++%{summary}. ++ ++%prep ++%autosetup -c -D -T ++cp -a %{S:0} . ++ ++%build ++gcc -g hello.c -o hello ++ ++%install ++mkdir -p %{buildroot}/bin ++install -D -p -m 0755 -t %{buildroot}/bin hello ++mkdir -p %{buildroot}/etc ++echo "settings" > %{buildroot}/etc/config.file ++ ++%files ++%attr(644,root,root) /bin/hello ++%config(noreplace) /etc/config.file ++ ++%changelog +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +index 1cae26dbf..a0e39782c 100644 +--- a/tests/rpmbuildid.at ++++ b/tests/rpmbuildid.at +@@ -1202,3 +1202,35 @@ run rpm -qp --qf "[[%{filenames} %{filemodes:perms}\n]]" \ + ], + [ignore]) + AT_CLEANUP ++ ++# ------------------------------ ++# Check that build-id directories are created with the right attributes ++# even if the spec file sets config explicitly. ++AT_SETUP([rpmbuild buildid config attrs]) ++AT_KEYWORDS([build] [debuginfo] [buildid]) ++AT_CHECK([ ++rm -rf ${TOPDIR} ++AS_MKDIR_P(${TOPDIR}/SOURCES) ++ ++# Setup sources ++cp "${abs_srcdir}"/data/SOURCES/hello.c ${TOPDIR}/SOURCES ++ ++# Build, contains one ELF which should have a buildid. ++run rpmbuild \ ++ --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="_build_id_links compat" \ ++ --define "_unique_debug_names 1" \ ++ --define "_unique_debug_srcs 1" \ ++ --quiet -ba "${abs_srcdir}"/data/SPECS/hello-config-buildid.spec ++ ++# Should contain one config file. ++run rpm -c -qp ${abs_builddir}/testing/build/RPMS/*/test-1.0-1*rpm ++# Should not contain config files. ++run rpm -c -qp ${abs_builddir}/testing/build/RPMS/*/test-debuginfo-1.0-1*rpm ++], ++[0], ++[/etc/config.file ++], ++[ignore]) ++AT_CLEANUP +-- +2.13.2 + diff --git a/0020-build-files-exec-build-id.patch b/0020-build-files-exec-build-id.patch deleted file mode 100644 index 3a27056..0000000 --- a/0020-build-files-exec-build-id.patch +++ /dev/null @@ -1,38 +0,0 @@ -diff --git a/build/files.c b/build/files.c -index 6021643..afa01cd 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1711,6 +1711,19 @@ static int generateBuildIDs(FileList fl) - for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { - struct stat sbuf; - if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { -+ /* We determine whether this is a main or -+ debug ELF based on path. */ -+ #define DEBUGPATH "/usr/lib/debug/" -+ int isDbg = strncmp (flp->cpioPath, -+ DEBUGPATH, strlen (DEBUGPATH)) == 0; -+ -+ /* For the main package files mimic what find-debuginfo.sh does. -+ Only check build-ids for executable files. Debug files are -+ always non-executable. */ -+ if (!isDbg -+ && (sbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) -+ continue; -+ - int fd = open (flp->diskPath, O_RDONLY); - if (fd >= 0) { - /* Only real ELF files, that are ET_EXEC, ET_DYN or -@@ -1732,12 +1745,8 @@ static int generateBuildIDs(FileList fl) - is 128 bits) and 64 bytes (largest sha3 is 512 - bits), common is 20 bytes (sha1 is 160 bits). */ - if (len >= 16 && len <= 64) { -- /* We determine whether this is a main or -- debug ELF based on path. */ -- #define DEBUGPATH "/usr/lib/debug/" - int addid = 0; -- if (strncmp (flp->cpioPath, -- DEBUGPATH, strlen (DEBUGPATH)) == 0) { -+ if (isDbg) { - needDbg = 1; - addid = 1; - } diff --git a/0020-debugedit-Fix-edit_dwarf2_line-replace_dirs-replace_.patch b/0020-debugedit-Fix-edit_dwarf2_line-replace_dirs-replace_.patch new file mode 100644 index 0000000..996caff --- /dev/null +++ b/0020-debugedit-Fix-edit_dwarf2_line-replace_dirs-replace_.patch @@ -0,0 +1,37 @@ +From 8e74618100580a1370b9045296c4d2d37340735f Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 16 Mar 2017 22:53:54 +0100 +Subject: [PATCH 20/49] debugedit: Fix edit_dwarf2_line replace_dirs -> + replace_files typo. + +We wouldn't replace the changed file names if replace_dirs was false, +but replace_files was true. This could overrun the new debug_line data +buffer if the original file name was larger than the replacement. It +wasn't found before because often when we need to replace files we +also would have to replace dirs. + +This fixes the kubernetes build in fedora. + +Signed-off-by: Mark Wielaard + +(cherry picked from commit dc759bc655ff1c18a08d77dd31dedfe3ae1025b0) +--- + tools/debugedit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 4798c6370..87a423fdb 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1185,7 +1185,7 @@ edit_dwarf2_line (DSO *dso) + { + const char *file = (const char *) optr; + const char *file_path = NULL; +- if (t->replace_dirs) ++ if (t->replace_files) + { + file_path = skip_dir_prefix (file, base_dir); + if (file_path != NULL) +-- +2.13.2 + diff --git a/0021-build-files.c-processPackageFiles-Don-t-call-generat.patch b/0021-build-files.c-processPackageFiles-Don-t-call-generat.patch new file mode 100644 index 0000000..37513c3 --- /dev/null +++ b/0021-build-files.c-processPackageFiles-Don-t-call-generat.patch @@ -0,0 +1,45 @@ +From 430f012c5794873a84db81b93c5858ca96ea4559 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Fri, 17 Mar 2017 11:14:00 +0100 +Subject: [PATCH 21/49] build/files.c (processPackageFiles): Don't call + generateBuildIDs for noarch. + +We don't want to do build-id processing for noarch packages. It might be +that noarch packages do contain architecture depended files, but those are +already handled by processBinaryFiles. + +This fixes the building of openbios in fedora. +https://bugzilla.redhat.com/show_bug.cgi?id=1433129 + +Signed-off-by: Mark Wielaard +(cherry picked from commit 5e82c7e8a8fc05195cdf622d0a120b9e70a9371b) +--- + build/files.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 6c0ca39ef..9e58ae547 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -2378,10 +2378,14 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + goto exit; + + #if HAVE_LIBDW +- if (generateBuildIDs (&fl) != 0) { +- rpmlog(RPMLOG_ERR, _("Generating build-id links failed\n")); +- fl.processingFailed = 1; +- goto exit; ++ /* Check build-ids and add build-ids links for files to package list. */ ++ const char *arch = headerGetString(pkg->header, RPMTAG_ARCH); ++ if (!rstreq(arch, "noarch")) { ++ if (generateBuildIDs (&fl) != 0) { ++ rpmlog(RPMLOG_ERR, _("Generating build-id links failed\n")); ++ fl.processingFailed = 1; ++ goto exit; ++ } + } + #endif + +-- +2.13.2 + diff --git a/0021-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch b/0021-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch deleted file mode 100644 index a8e016c..0000000 --- a/0021-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e6cbf971242e424264711f9ffad57eee7f6d6f67 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Tue, 21 Mar 2017 16:46:37 +0100 -Subject: [PATCH] debugedit: Fix off-by-one adding DW_FORM_string replacement - slashes. - -We would put one too many slashes in between the new dest_dir and file name -part of the replacement of a DW_FORM_string in the .debug_info. If there -was file part then we would overwrite the first character of the name. If -there was no file part at all then this would overwrite the zero terminator -and cause a crash reading the rest of the data. - -A crash did happen while building the docker package on fedora s390x. -https://bugzilla.redhat.com/show_bug.cgi?id=1434347 - -The reason neither issue would normally trigger is because if we do detect -that the dest_dir is larger than the base_dir we refuse to replace anything. - -Signed-off-by: Mark Wielaard ---- - tools/debugedit.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/tools/debugedit.c b/tools/debugedit.c -index 0f37316..b618dce 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -1507,12 +1507,16 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - comp_dir, base_dir, dest_dir); - else - { -- /* Add one or more slashes in between to -- fill up all space (replacement must be -- of the same length). */ -+ /* Add zero (if no file part), one or more -+ slashes in between the new dest_dir and the -+ file name to fill up all space (replacement -+ DW_FORM_string must be of the same length). -+ We don't need to copy the old file name (if -+ any) or the zero terminator, because those -+ are already at the end of the string. */ - memcpy (ptr, dest_dir, dest_len); - memset (ptr + dest_len, '/', -- orig_len - new_len + 1); -+ orig_len - new_len); - } - } - } --- -1.8.3.1 - diff --git a/0022-debugedit-Fix-cross-endian-build-id-reading-and-upda.patch b/0022-debugedit-Fix-cross-endian-build-id-reading-and-upda.patch new file mode 100644 index 0000000..0f04113 --- /dev/null +++ b/0022-debugedit-Fix-cross-endian-build-id-reading-and-upda.patch @@ -0,0 +1,120 @@ +From 5598e24ef8aef14727ff72eea71ec460200bc2e3 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Fri, 17 Mar 2017 21:03:35 +0100 +Subject: [PATCH 22/49] debugedit: Fix cross-endian build-id reading and + updating section data. + +debugedit doesn't read raw mmap data any longer. Which made the complex +way to read the build-id unnecessary (and it was broken for cross-endian). +Just use gelf_getnote to read the notes. + +Also in some special cases when only the debug_info or build_id data +was updated, but no section changed size and we had to preserve the +allocated section headers we could hit a bug in elfutils that could +trash some section data in case there were gaps between non-dirty and +dirty sections. See https://sourceware.org/bugzilla/show_bug.cgi?id=21199 +Add a workaround for that issue. + +This fixes the kompose package build on fedora ppc64. +And makes it possible to replicate that issue on x86_64. + +Signed-off-by: Mark Wielaard +(cherry picked from commit a6e767600309bdb1f8af33b44563a1187fb0dbc4) +--- + tools/debugedit.c | 63 +++++++++++++++++++++++++++---------------------------- + 1 file changed, 31 insertions(+), 32 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 87a423fdb..0f373162d 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -2581,40 +2581,25 @@ main (int argc, char *argv[]) + break; + case SHT_NOTE: + if (do_build_id +- && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC)) ++ && build_id == 0 && (dso->shdr[i].sh_flags & SHF_ALLOC)) + { + /* Look for a build-ID note here. */ ++ size_t off = 0; ++ GElf_Nhdr nhdr; ++ size_t name_off; ++ size_t desc_off; + Elf_Data *data = elf_getdata (elf_getscn (dso->elf, i), NULL); +- Elf32_Nhdr nh; +- Elf_Data dst = +- { +- .d_version = EV_CURRENT, .d_type = ELF_T_NHDR, +- .d_buf = &nh, .d_size = sizeof nh +- }; +- Elf_Data src = dst; +- src.d_buf = data->d_buf; +- assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); +- while ((char *) data->d_buf + data->d_size - +- (char *) src.d_buf > (int) sizeof nh +- && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA])) +- { +- Elf32_Word len = sizeof nh + nh.n_namesz; +- len = (len + 3) & ~3; +- +- if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3 +- && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU")) +- { +- build_id = data; +- build_id_offset = (char *) src.d_buf + len - +- (char *) data->d_buf; +- build_id_size = nh.n_descsz; +- break; +- } +- +- len += nh.n_descsz; +- len = (len + 3) & ~3; +- src.d_buf = (char *) src.d_buf + len; +- } ++ while ((off = gelf_getnote (data, off, ++ &nhdr, &name_off, &desc_off)) > 0) ++ if (nhdr.n_type == NT_GNU_BUILD_ID ++ && nhdr.n_namesz == sizeof "GNU" ++ && (memcmp ((char *)data->d_buf + name_off, "GNU", ++ sizeof "GNU") == 0)) ++ { ++ build_id = data; ++ build_id_offset = desc_off; ++ build_id_size = nhdr.n_descsz; ++ } + } + break; + default: +@@ -2622,6 +2607,20 @@ main (int argc, char *argv[]) + } + } + ++ /* Normally we only need to explicitly update the section headers ++ and data when any section data changed size. But because of a bug ++ in elfutils before 0.169 we will have to update and write out all ++ section data if any data has changed (when ELF_F_LAYOUT was ++ set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ ++ bool need_update = need_strp_update || need_stmt_update; ++ ++#if !_ELFUTILS_PREREQ (0, 169) ++ /* string replacements or build_id updates don't change section size. */ ++ need_update = (need_update ++ || need_string_replacement ++ || (do_build_id && build_id != NULL)); ++#endif ++ + /* We might have changed the size of some debug sections. If so make + sure the section headers are updated and the data offsets are + correct. We set ELF_F_LAYOUT above because we don't want libelf +@@ -2631,7 +2630,7 @@ main (int argc, char *argv[]) + anything for the phdrs allocated sections. Keep the offset of + allocated sections so they are at the same place in the file. Add + unallocated ones after the allocated ones. */ +- if (dso->phnum != 0 && (need_strp_update || need_stmt_update)) ++ if (dso->phnum != 0 && need_update) + { + Elf *elf = dso->elf; + GElf_Off last_offset; +-- +2.13.2 + diff --git a/0022-unbreak-short-circuit.patch b/0022-unbreak-short-circuit.patch deleted file mode 100644 index ca57624..0000000 --- a/0022-unbreak-short-circuit.patch +++ /dev/null @@ -1,171 +0,0 @@ -commit eea78b023539875309b7d38e4c8924f647644924 -Author: Panu Matilainen -Date: Thu Jan 5 13:47:28 2017 +0200 - - Unbreak short-circuited binary builds - - Commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 broke short-circuited - binary builds (which can be handy for testing when working on large - packages), eg: - rpmbuild -bi foo.spec; rpmbuild -bb --short-circuit foo.spec - - The problem is that in a short-circuited build all the links already - exist and point to the right place, but the code doesn't realize this - and creates new links instead, which leaves the old links unowned - in the buildroot which ultimately causes the build to fail with - "Installed (but unpackaged) file(s) found" for the previously created - build-id links. - - When checking for pre-existing links see if they already point to - the right file and in that case just reuse it instead of creating new ones. - Keep track of duplicate build-ids found by noticing existing links that - point to different targets. But don't do this for compat links, they should - just point to the last (duplicate) main build-id symlink found. - - Signed-off-by: Mark Wielaard - -diff --git a/build/files.c b/build/files.c -index cca14b9..93021d1 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1592,11 +1592,12 @@ exit: - - static int addNewIDSymlink(FileList fl, - char *targetpath, char *idlinkpath, -- int isDbg, int isCompat) -+ int isDbg, int *dups) - { - const char *linkerr = _("failed symlink"); - int rc = 0; - int nr = 0; -+ int exists = 0; - char *origpath, *linkpath; - - if (isDbg) -@@ -1606,6 +1607,26 @@ static int addNewIDSymlink(FileList fl, - origpath = linkpath; - - while (faccessat(AT_FDCWD, linkpath, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { -+ /* We don't care about finding dups for compat links, they are -+ OK as is. Otherwise we will need to double check if -+ existing link points to the correct target. */ -+ if (dups == NULL) -+ { -+ exists = 1; -+ break; -+ } -+ -+ char ltarget[PATH_MAX]; -+ ssize_t llen; -+ /* In short-circuited builds the link might already exist */ -+ if ((llen = readlink(linkpath, ltarget, sizeof(ltarget)-1)) != -1) { -+ ltarget[llen] = '\0'; -+ if (rstreq(ltarget, targetpath)) { -+ exists = 1; -+ break; -+ } -+ } -+ - if (nr > 0) - free(linkpath); - nr++; -@@ -1613,21 +1634,16 @@ static int addNewIDSymlink(FileList fl, - isDbg ? ".debug" : ""); - } - -- char *symtarget = targetpath; -- if (nr > 0 && isCompat) -- rasprintf (&symtarget, "%s.%d", targetpath, nr); -- -- if (symlink(symtarget, linkpath) < 0) { -+ if (!exists && symlink(targetpath, linkpath) < 0) { - rc = 1; - rpmlog(RPMLOG_ERR, "%s: %s -> %s: %m\n", -- linkerr, linkpath, symtarget); -+ linkerr, linkpath, targetpath); - } else { - fl->cur.isDir = 0; - rc = addFile(fl, linkpath, NULL); - } - -- /* Don't warn (again) if this is a compat id-link, we retarget it. */ -- if (nr > 0 && !isCompat) { -+ if (nr > 0) { - /* Lets see why there are multiple build-ids. If the original - targets are hard linked, then it is OK, otherwise warn - something fishy is going on. Would be nice to call -@@ -1656,8 +1672,8 @@ static int addNewIDSymlink(FileList fl, - free(origpath); - if (nr > 0) - free(linkpath); -- if (nr > 0 && isCompat) -- free(symtarget); -+ if (dups != NULL) -+ *dups = nr; - - return rc; - } -@@ -1897,6 +1913,7 @@ static int generateBuildIDs(FileList fl) - || (rc = addFile(fl, buildidsubdir, NULL)) == 0) { - char *linkpattern, *targetpattern; - char *linkpath, *targetpath; -+ int dups = 0; - if (isDbg) { - linkpattern = "%s/%s"; - targetpattern = "../../../../..%s"; -@@ -1908,7 +1925,7 @@ static int generateBuildIDs(FileList fl) - buildidsubdir, &ids[i][2]); - rasprintf(&targetpath, targetpattern, paths[i]); - rc = addNewIDSymlink(fl, targetpath, linkpath, -- isDbg, 0); -+ isDbg, &dups); - - /* We might want to have a link from the debug - build_ids dir to the main one. We create it -@@ -1931,16 +1948,30 @@ static int generateBuildIDs(FileList fl) - && build_id_links == BUILD_IDS_COMPAT) { - /* buildidsubdir already points to the - debug buildid. We just need to setup -- the symlink to the main one. */ -+ the symlink to the main one. There -+ might be duplicate IDs, those are found -+ by the addNewIDSymlink above. Target -+ the last found duplicate, if any. */ - free(linkpath); - free(targetpath); -- rasprintf(&linkpath, "%s/%s", -- buildidsubdir, &ids[i][2]); -- rasprintf(&targetpath, -- "../../../.build-id%s/%s", -- subdir, &ids[i][2]); -+ if (dups == 0) -+ { -+ rasprintf(&linkpath, "%s/%s", -+ buildidsubdir, &ids[i][2]); -+ rasprintf(&targetpath, -+ "../../../.build-id%s/%s", -+ subdir, &ids[i][2]); -+ } -+ else -+ { -+ rasprintf(&linkpath, "%s/%s.%d", -+ buildidsubdir, &ids[i][2], dups); -+ rasprintf(&targetpath, -+ "../../../.build-id%s/%s.%d", -+ subdir, &ids[i][2], dups); -+ } - rc = addNewIDSymlink(fl, targetpath, linkpath, -- 0, 1); -+ 0, NULL); - } - - if (rc == 0 && isDbg -@@ -1978,7 +2009,7 @@ static int generateBuildIDs(FileList fl) - rasprintf(&targetpath, "../../../../..%s", - targetstr); - rc = addNewIDSymlink(fl, targetpath, -- linkpath, 0, 0); -+ linkpath, 0, &dups); - free(targetstr); - } - } diff --git a/0023-minisymtab-exe-sh.patch b/0023-minisymtab-exe-sh.patch deleted file mode 100644 index 9ad8630..0000000 --- a/0023-minisymtab-exe-sh.patch +++ /dev/null @@ -1,35 +0,0 @@ -commit 95822abd90b9b3991b15ba82193abb5b9998dc99 -Author: Mark Wielaard -Date: Sat Apr 15 13:34:18 2017 +0200 - - find-debuginfo.sh: Only add minisymtab for executables or shared libraries. - - It only makes sense to add a minisymtab for executables and shared - libraries. Other executable ELF files (like kernel modules) don't need it. - Since those don't have a dynsym section trying to add it will fail and - produce confusing errors from nm. - - Signed-off-by: Mark Wielaard - -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index 6f38e19..39bb0b7 100755 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -358,7 +358,16 @@ do_file() - fi - - # strip -g implies we have full symtab, don't add mini symtab in that case. -- $strip_g || ($include_minidebug && add_minidebug "${debugfn}" "$f") -+ # It only makes sense to add a minisymtab for executables and shared -+ # libraries. Other executable ELF files (like kernel modules) don't need it. -+ if [ "$include_minidebug" = "true" -a "$strip_g" = "false" ]; then -+ skip_mini=true -+ case "$(file -bi "$f")" in -+ application/x-sharedlib*) skip_mini=false ;; -+ application/x-executable*) skip_mini=false ;; -+ esac -+ $skip_mini || add_minidebug "${debugfn}" "$f" -+ fi - - echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" - diff --git a/0023-tests-tpmbuild.at-Make-file-sed-regexp-more-strict-t.patch b/0023-tests-tpmbuild.at-Make-file-sed-regexp-more-strict-t.patch new file mode 100644 index 0000000..09bdeaf --- /dev/null +++ b/0023-tests-tpmbuild.at-Make-file-sed-regexp-more-strict-t.patch @@ -0,0 +1,60 @@ +From 8cd45c82a968404929e00dce65644f81e906591b Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Fri, 3 Mar 2017 23:51:13 +0100 +Subject: [PATCH 23/49] tests/tpmbuild.at: Make file sed regexp more strict to + extract BuildID. + +In some testcases we extract the BuildID with the file command. +Unfortunately the file command output changed slightly between versions. +Make the sed regexp more strict by only matching a hex-string. +Also properly "escape" [ and ] which inside an AT_CHECK should be [[ and ]]. + +Tested against file versions 5.11, 5.29 and 5.30. + +Signed-off-by: Mark Wielaard +(cherry picked from commit f0a581925ad4c948dc58cc8f9a55399ad8de351e) +--- + tests/rpmbuild.at | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at +index a46822f52..dcbdd2cad 100644 +--- a/tests/rpmbuild.at ++++ b/tests/rpmbuild.at +@@ -423,11 +423,11 @@ hello2_file=./usr/local/bin/hello2 + test -f $hello_file || echo "no hello file: $hello_file" + test -f $hello2_file || echo "no hello2 file: $hello2_file" + +-id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++id2=$(file $hello2_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++id1debug=$(file $hello_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++idmulti=$(file $hello_multi_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" + test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" +@@ -516,11 +516,11 @@ hello2_file=./usr/local/bin/hello2 + test -f $hello_file || echo "no hello file: $hello_file" + test -f $hello2_file || echo "no hello2 file: $hello2_file" + +-id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-id2=$(file $hello2_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-id1debug=$(file $hello_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') +-idmulti=$(file $hello_multi_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++id2=$(file $hello2_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++id1debug=$(file $hello_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++id2debug=$(file $hello2_file_debug | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++idmulti=$(file $hello_multi_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test "$id1" = "$id1debug" || echo "id1: $id1 != id1debug: $id1debug" + test "$id2" = "$id2debug" || echo "id2: $id2 != id2debug: $id2debug" +-- +2.13.2 + diff --git a/0024-no-recompute-build-id.patch b/0024-no-recompute-build-id.patch deleted file mode 100644 index b0e7eab..0000000 --- a/0024-no-recompute-build-id.patch +++ /dev/null @@ -1,271 +0,0 @@ -commit 8edddd82f855d547bd68ba4d693db497bbbed7ab -Author: Mark Wielaard -Date: Sat Apr 15 20:31:14 2017 +0200 - - debugedit: Add -n, --no-recompute-build-id. - - Some packages depend on the build-ids as generated during the build - and cannot handle rpmbuild recomputing them before generating the - package file list. Add -n, --no-recompute-build-id to debugedit and - add -n to find-debuginfo.sh set by defining the %_no_recompute_build_ids - macro for such packages. %_no_recompute_build_ids can not be used together - with %_unique_build_ids. - - Signed-off-by: Mark Wielaard - -diff --git a/macros.in b/macros.in -index f7d16de..cf22628 100644 ---- a/macros.in -+++ b/macros.in -@@ -172,7 +172,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ - %{nil} - - # Template for debug information sub-package. -@@ -498,6 +498,11 @@ package or when debugging this package.\ - # onto debugedit --build-id-seed to be used to prime the build-id note hash. - %_unique_build_ids 1 - -+# Do not recompute build-ids but keep whatever is in the ELF file already. -+# Cannot be used together with _unique_build_ids (which forces recomputation). -+# Defaults to undefined (unset). -+#%_no_recompute_build_ids 1 -+ - # Whether .debug files should be made unique between package version, - # release and architecture. If set to 1 this will pass - # --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index b52822e..86a248d 100755 ---- 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] [-m] [-i] -+# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n] - # [-o debugfiles.list] - # [--run-dwz] [--dwz-low-mem-die-limit N] - # [--dwz-max-die-limit N] -@@ -16,6 +16,7 @@ - # The -r flag says to use eu-strip --reloc-debug-sections. - # The -m flag says to include a .gnu_debugdata section in the main binary. - # The -i flag says to include a .gdb_index section in the .debug file. -+# The -n flag says to not recompute the build-id. - # - # A single -o switch before any -l or -p switches simply renames - # the primary output file from debugfiles.list to something else. -@@ -56,6 +57,9 @@ include_gdb_index=false - # Barf on missing build IDs. - strict=false - -+# Do not recompute build IDs. -+no_recompute_build_id=false -+ - # DWZ parameters. - run_dwz=false - dwz_low_mem_die_limit= -@@ -110,6 +114,9 @@ while [ $# -gt 0 ]; do - -m) - include_minidebug=true - ;; -+ -n) -+ no_recompute_build_id=true -+ ;; - -i) - include_gdb_index=true - ;; -@@ -159,6 +166,11 @@ if test -z "$unique_debug_arch" -a -n "$unique_debug_src_base"; then - exit 2 - fi - -+if test -n "$ver_rel" -a "$no_recompute_build_id" = "true"; then -+ echo >&2 "*** ERROR: --ver-rel (unique build-ids) and -n (do not recompute build-id cannot be used together" -+ exit 2 -+fi -+ - i=0 - while ((i < nout)); do - outs[$i]="$BUILDDIR/${outs[$i]}" -@@ -310,8 +322,12 @@ - debug_base_name="$BUILDDIR" - debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" - fi -+ no_recompute= -+ if [ "$no_recompute_build_id" = "true" ]; then -+ no_recompute="-n" -+ fi - id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ -- -i $build_id_seed -l "$SOURCEFILE" "$f") || exit -+ $no_recompute -i $build_id_seed -l "$SOURCEFILE" "$f") || exit - if [ $nlinks -gt 1 ]; then - eval linkedid_$inum=\$id - fi -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -index dc47b90..88ce226 100644 ---- a/tests/rpmbuildid.at -+++ b/tests/rpmbuildid.at -@@ -1060,6 +1060,128 @@ debug dup id in debug package - AT_CLEANUP - - # ------------------------------ -+# Check build-ids are recomputed with unique_build_ids, -+# but not with _no_recompute_build_ids -+AT_SETUP([rpmbuild buildid recompute]) -+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 -+ -+# Make sure we get debuginfo -+export CFLAGS="-g" -+ -+# Unique 1 -+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" \ -+ --undefine="_no_recompute_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 -+test -f $hello_file || echo "No $hello_file" -+id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+ -+# Make sure we generate a new one -+rm $hello_file -+ -+# Unique 2 -+# 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" \ -+ --undefine="_no_recompute_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 -+test -f $hello_file || echo "No $hello_file" -+id2=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+ -+# Two unique builds should not be equal -+if test "$id1" == "$id2"; then -+ echo "uniques equal"; -+else -+ echo "uniques unequal"; -+fi -+ -+# Make sure we generate a new one -+rm $hello_file -+ -+# no-recompute 1 -+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" \ -+ --undefine="_unique_debug_names" \ -+ --undefine="_unique_debug_srcs" \ -+ --define="_no_recompute_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 -+test -f $hello_file || echo "No $hello_file" -+id3=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+ -+# An unique and no-recompute build should be unequal -+if test "$id2" == "$id3"; then -+ echo "no-recompute unique equal"; -+else -+ echo "no-recompute unique unequal"; -+fi -+ -+# Make sure we generate a new one -+rm $hello_file -+ -+# no-recompute 2 -+# 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" \ -+ --undefine="_unique_debug_names" \ -+ --undefine="_unique_debug_srcs" \ -+ --define="_no_recompute_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 -+test -f $hello_file || echo "No $hello_file" -+id4=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') -+ -+# Two no-recompute builds should be equal. Even for different "releases". -+if test "$id3" == "$id4"; then -+ echo "no-recomputes equal"; -+else -+ echo "no-recomputes unequal"; -+fi -+], -+[0], -+[uniques unequal -+no-recompute unique unequal -+no-recomputes equal -+], -+[ignore]) -+AT_CLEANUP -+ -+# ------------------------------ - # Check build-ids are unique between versions/releases - # with _unique_build_ids defined. - AT_SETUP([rpmbuild buildid unique r1 r2]) -diff --git a/tools/debugedit.c b/tools/debugedit.c -index b618dce..8444e03 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -85,6 +85,7 @@ char *dest_dir = NULL; - char *list_file = NULL; - int list_file_fd = -1; - int do_build_id = 0; -+int no_recompute_build_id = 0; - char *build_id_seed = NULL; - - /* We go over the debug sections in two phases. In phase zero we keep -@@ -2261,6 +2262,8 @@ static struct poptOption optionsTable[] = { - "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 }, -+ { "no-recompute-build-id", 'n', POPT_ARG_NONE, &no_recompute_build_id, 0, -+ "do not recompute build ID note even when -i or -s are given", NULL }, - POPT_AUTOHELP - { NULL, 0, 0, NULL, 0, NULL, NULL } - }; -@@ -2380,7 +2383,8 @@ handle_build_id (DSO *dso, Elf_Data *build_id, - exit (1); - } - -- if (!dirty_elf && build_id_seed == NULL) -+ if (no_recompute_build_id -+ || (! dirty_elf && build_id_seed == NULL)) - goto print; - - /* Clear the old bits so they do not affect the new hash. */ diff --git a/0024-tests-rpmbuildid.at-Make-file-sed-regexp-more-strict.patch b/0024-tests-rpmbuildid.at-Make-file-sed-regexp-more-strict.patch new file mode 100644 index 0000000..751e539 --- /dev/null +++ b/0024-tests-rpmbuildid.at-Make-file-sed-regexp-more-strict.patch @@ -0,0 +1,222 @@ +From 58f2b095c0d1507ad09990669f1ae03f6f1d931f Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Mon, 20 Mar 2017 09:55:44 +0100 +Subject: [PATCH 24/49] tests/rpmbuildid.at: Make file sed regexp more strict + to extract BuildID. + +Like commit f0a5819 for rpmbuild.at. In the case of rpmbuildid.at the +sed expression looked to work, but only matched by accident. Make the sed +regexp more strict by only matching a hex-string. And properly "escape" +[ and ] which inside an AT_CHECK should be [[ and ]]. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 60f958ab41f854f8839fe04f1a67d1752ad7eda0) +--- + tests/rpmbuildid.at | 44 ++++++++++++++++++++++---------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +index a0e39782c..158ce122d 100644 +--- a/tests/rpmbuildid.at ++++ b/tests/rpmbuildid.at +@@ -97,7 +97,7 @@ main_file=./usr/local/bin/hello + test -f "${main_file}" || echo "No main file ${main_file}" + + # Extract the build-id from the main file +-id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" + test -L "$id_main_file" || echo "No build-id file $id_main_file" +@@ -120,7 +120,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello.debug + test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file +-id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test ${id_main} = ${id_debug} || echo "unequal main and debug id" + +@@ -190,7 +190,7 @@ main_file=./usr/local/bin/hello + test -f "${main_file}" || echo "No main file ${main_file}" + + # Extract the build-id from the main file +-id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + id_main_file="./usr/lib/debug/.build-id/${id_main:0:2}/${id_main:2}" + test -L "$id_main_file" || echo "No build-id file $id_main_file" +@@ -213,7 +213,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug + test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file +-id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test ${id_main} = ${id_debug} || echo "unequal main and debug id" + +@@ -283,7 +283,7 @@ main_file=./usr/local/bin/hello + test -f "${main_file}" || echo "No main file ${main_file}" + + # Extract the build-id from the main file +-id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" + test -L "$id_main_file" || echo "No build-id file $id_main_file" +@@ -306,7 +306,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello.debug + test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file +-id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test ${id_main} = ${id_debug} || echo "unequal main and debug id" + +@@ -375,7 +375,7 @@ main_file=./usr/local/bin/hello + test -f "${main_file}" || echo "No main file ${main_file}" + + # Extract the build-id from the main file +-id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" + test -L "$id_main_file" || echo "No build-id file $id_main_file" +@@ -398,7 +398,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello-*.debug + test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file +-id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test ${id_main} = ${id_debug} || echo "unequal main and debug id" + +@@ -469,7 +469,7 @@ main_file=./usr/local/bin/hello + test -f "${main_file}" || echo "No main file ${main_file}" + + # Extract the build-id from the main file +-id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" + test -L "$id_main_file" || echo "No build-id file $id_main_file" +@@ -492,7 +492,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello.debug + test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file +-id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test ${id_main} = ${id_debug} || echo "unequal main and debug id" + +@@ -574,7 +574,7 @@ main_file=./usr/local/bin/hello + test -f "${main_file}" || echo "No main file ${main_file}" + + # Extract the build-id from the main file +-id_main=$(file $main_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_main=$(file $main_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + id_main_file="./usr/lib/.build-id/${id_main:0:2}/${id_main:2}" + test -L "$id_main_file" || echo "No build-id file $id_main_file" +@@ -597,7 +597,7 @@ debug_file=./usr/lib/debug/usr/local/bin/hello-*debug + test -f ${debug_file} || echo "No debug file ${debug_file}" + + # Extract the build-id from the .debug file +-id_debug=$(file $debug_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id_debug=$(file $debug_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + test ${id_main} = ${id_debug} || echo "unequal main and debug id" + +@@ -662,7 +662,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file +-id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # alldebug not here... + id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" +@@ -732,7 +732,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file +-id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # alldebug not here... + id_file="./usr/lib/debug/.build-id/${id:0:2}/${id:2}" +@@ -799,7 +799,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file +-id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # separate build-ids split... + id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" +@@ -866,7 +866,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file +-id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # separate build-ids split... + id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" +@@ -930,7 +930,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file +-id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # compat build-ids split... + id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" +@@ -1009,7 +1009,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \ + hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file +-id=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # compat build-ids split... + id_file="./usr/lib/.build-id/${id:0:2}/${id:2}" +@@ -1084,7 +1084,7 @@ hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file + test -f $hello_file || echo "No $hello_file" +-id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # Make sure we generate a new one + rm $hello_file +@@ -1101,7 +1101,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ + + # Extract the build-id from the main file + test -f $hello_file || echo "No $hello_file" +-id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id2=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + if test "$id1" == "$id2"; then echo "equal $id1"; else echo "unequal"; fi + ], +@@ -1138,7 +1138,7 @@ hello_file=./usr/local/bin/hello + + # Extract the build-id from the main file + test -f $hello_file || echo "No $hello_file" +-id1=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + # Make sure we generate a new one + rm $hello_file +@@ -1157,7 +1157,7 @@ rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-2.*.rpm \ + + # Extract the build-id from the main file + test -f $hello_file || echo "No $hello_file" +-id2=$(file $hello_file | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/') ++id2=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') + + if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi + ], +-- +2.13.2 + diff --git a/0025-build-files.c-Only-check-build-ids-for-executable-fi.patch b/0025-build-files.c-Only-check-build-ids-for-executable-fi.patch new file mode 100644 index 0000000..93c0662 --- /dev/null +++ b/0025-build-files.c-Only-check-build-ids-for-executable-fi.patch @@ -0,0 +1,62 @@ +From c21bf3aefdcfb22bc3f41888ef090c6d5a45baec Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Mon, 20 Mar 2017 11:52:00 +0100 +Subject: [PATCH 25/49] build/files.c: Only check build-ids for executable + files in the main package. + +generateBuildIDs should mimic what find-debuginfo.sh does. Only check +build-ids for executable files in non-debuginfo packages. This moves the +isDbg check up so the is executeble check can be done when the file is +part of the main package. + +This fixes the build of qemu and uboot-tools in fedora. Both ship +non-executable ELF bios files in architecture specific packages. +https://bugzilla.redhat.com/show_bug.cgi?id=1433837 + +Signed-off-by: Mark Wielaard +(cherry picked from commit c9035d464a6ac3853b5dc705e0df1734ce915cd4) +--- + build/files.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 9e58ae547..9f7def78c 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1684,6 +1684,19 @@ static int generateBuildIDs(FileList fl) + for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { + struct stat sbuf; + if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { ++ /* We determine whether this is a main or ++ debug ELF based on path. */ ++ #define DEBUGPATH "/usr/lib/debug/" ++ int isDbg = strncmp (flp->cpioPath, ++ DEBUGPATH, strlen (DEBUGPATH)) == 0; ++ ++ /* For the main package files mimic what find-debuginfo.sh does. ++ Only check build-ids for executable files. Debug files are ++ always non-executable. */ ++ if (!isDbg ++ && (sbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) ++ continue; ++ + int fd = open (flp->diskPath, O_RDONLY); + if (fd >= 0) { + /* Only real ELF files, that are ET_EXEC, ET_DYN or +@@ -1705,12 +1718,8 @@ static int generateBuildIDs(FileList fl) + is 128 bits) and 64 bytes (largest sha3 is 512 + bits), common is 20 bytes (sha1 is 160 bits). */ + if (len >= 16 && len <= 64) { +- /* We determine whether this is a main or +- debug ELF based on path. */ +- #define DEBUGPATH "/usr/lib/debug/" + int addid = 0; +- if (strncmp (flp->cpioPath, +- DEBUGPATH, strlen (DEBUGPATH)) == 0) { ++ if (isDbg) { + needDbg = 1; + addid = 1; + } +-- +2.13.2 + diff --git a/0025-buildid-reset-attrs.patch b/0025-buildid-reset-attrs.patch deleted file mode 100644 index 5a9b3f3..0000000 --- a/0025-buildid-reset-attrs.patch +++ /dev/null @@ -1,233 +0,0 @@ -commit b91dc6106e360f13ff365dfac247191942039152 -Author: Mark Wielaard -Date: Wed Mar 15 20:07:29 2017 +0100 - - Make sure to reset file attributes for generated build-id directories. - - [Note this patch is currently being tested in Fedora. See bug below.] - - When creating the build-id directories we should reset the file attributes - to the defaults. Otherwise if the file list contained an %attr or %defattr - the directories would come out with the wrong mode. - - Includes a testcase based on a spec by Igor Gnatenko that fails before - and Check that build-id directories are created with the right permissions - even if the spec file sets attrs explicitly. - - https://bugzilla.redhat.com/show_bug.cgi?id=1432372 - - Signed-off-by: Mark Wielaard - -[Just the testcase] - -diff --git a/tests/Makefile.am b/tests/Makefile.am -index 815a390..ad41957 100644 ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -69,6 +69,8 @@ EXTRA_DIST += data/RPMS/hello-2.0-1.i686.rpm - EXTRA_DIST += data/RPMS/hello-2.0-1.x86_64.rpm - EXTRA_DIST += data/SRPMS/foo-1.0-1.src.rpm - EXTRA_DIST += data/SRPMS/hello-1.0-1.src.rpm -+EXTRA_DIST += data/SOURCES/hello.c -+EXTRA_DIST += data/SPECS/hello-attr-buildid.spec - - # testsuite voodoo - AUTOTEST = $(AUTOM4TE) --language=autotest -diff --git a/tests/data/SOURCES/hello.c b/tests/data/SOURCES/hello.c -new file mode 100644 -index 0000000..020484e ---- /dev/null -+++ b/tests/data/SOURCES/hello.c -@@ -0,0 +1,8 @@ -+#include -+ -+int -+main (void) -+{ -+ printf ("Hello, world!\n"); -+ return 0; -+} -diff --git a/tests/data/SPECS/hello-attr-buildid.spec b/tests/data/SPECS/hello-attr-buildid.spec -new file mode 100644 -index 0000000..cdab95f ---- /dev/null -+++ b/tests/data/SPECS/hello-attr-buildid.spec -@@ -0,0 +1,27 @@ -+Name: test -+Version: 1.0 -+Release: 1 -+Summary: Test -+ -+License: Public Domain -+URL: https://fedoraproject.org -+Source: hello.c -+ -+%description -+%{summary}. -+ -+%prep -+%autosetup -c -D -T -+cp -a %{S:0} . -+ -+%build -+gcc -g hello.c -o hello -+ -+%install -+mkdir -p %{buildroot}%{_bindir} -+install -D -p -m 0755 -t %{buildroot}%{_bindir} hello -+ -+%files -+%attr(644,root,root) %{_bindir}/hello -+ -+%changelog -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -index 15c0620..1cae26d 100644 ---- a/tests/rpmbuildid.at -+++ b/tests/rpmbuildid.at -@@ -1166,3 +1166,39 @@ if test "$id1" == "$id2"; then echo "equal"; else echo "unequal $id1 $id2"; fi - ], - [ignore]) - AT_CLEANUP -+ -+# ------------------------------ -+# Check that build-id directories are created with the right permissions -+# even if the spec file sets attrs explicitly. -+AT_SETUP([rpmbuild buildid attrs]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello.c ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links compat" \ -+ --define "_unique_debug_names 1" \ -+ --define "_unique_debug_srcs 1" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello-attr-buildid.spec -+ -+run rpm -qp --qf "[[%{filenames} %{filemodes:perms}\n]]" \ -+ ${abs_builddir}/testing/build/RPMS/*/test-1.0-1*rpm \ -+ | grep "build-id d" -+ -+run rpm -qp --qf "[[%{filenames} %{filemodes:perms}\n]]" \ -+ ${abs_builddir}/testing/build/RPMS/*/test-debuginfo-1.0-1*rpm \ -+ | grep "build-id d" -+], -+[0], -+[/usr/lib/.build-id drwxr-xr-x -+/usr/lib/debug/.build-id drwxr-xr-x -+], -+[ignore]) -+AT_CLEANUP - -commit 9d942049cf929d5a053c239cdd64f5b97d182c14 -Author: Mark Wielaard -Date: Fri May 19 23:11:39 2017 +0200 - - rpmbuild: Reset attrFlags in generateBuildIDs. - - Debuginfo directories and files could be marked as configuration files - if the file list ended with a config file. - - Patch by Panu Matilainen. Testcase by me. - - https://bugzilla.redhat.com/show_bug.cgi?id=1449732 - - Signed-off-by: Mark Wielaard - -diff --git a/build/files.c b/build/files.c -index 791bbe2..86c601b 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -1860,6 +1860,8 @@ static int generateBuildIDs(FileList fl) - Uses parseForAttr to reset ar, arFlags, and specdFlags. - Note that parseForAttr pokes at the attrstr, so we cannot - just pass a static string. */ -+ fl->cur.attrFlags = 0; -+ fl->def.attrFlags = 0; - fl->def.verifyFlags = RPMVERIFY_ALL; - fl->cur.verifyFlags = RPMVERIFY_ALL; - fl->def.specdFlags |= SPECD_VERIFY; - -diff --git a/tests/data/SPECS/hello-config-buildid.spec b/tests/data/SPECS/hello-config-buildid.spec -new file mode 100644 -index 0000000..ca2d30d ---- /dev/null -+++ b/tests/data/SPECS/hello-config-buildid.spec -@@ -0,0 +1,30 @@ -+Name: test -+Version: 1.0 -+Release: 1 -+Summary: Test -+ -+License: Public Domain -+URL: https://fedoraproject.org -+Source: hello.c -+ -+%description -+%{summary}. -+ -+%prep -+%autosetup -c -D -T -+cp -a %{S:0} . -+ -+%build -+gcc -g hello.c -o hello -+ -+%install -+mkdir -p %{buildroot}/bin -+install -D -p -m 0755 -t %{buildroot}/bin hello -+mkdir -p %{buildroot}/etc -+echo "settings" > %{buildroot}/etc/config.file -+ -+%files -+%attr(644,root,root) /bin/hello -+%config(noreplace) /etc/config.file -+ -+%changelog -diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at -index 88ce226..4fab3d5 100644 ---- a/tests/rpmbuildid.at -+++ b/tests/rpmbuildid.at -@@ -1324,3 +1324,35 @@ run rpm -qp --qf "[[%{filenames} %{filemodes:perms}\n]]" \ - ], - [ignore]) - AT_CLEANUP -+ -+# ------------------------------ -+# Check that build-id directories are created with the right attributes -+# even if the spec file sets config explicitly. -+AT_SETUP([rpmbuild buildid config attrs]) -+AT_KEYWORDS([build] [debuginfo] [buildid]) -+AT_CHECK([ -+rm -rf ${TOPDIR} -+AS_MKDIR_P(${TOPDIR}/SOURCES) -+ -+# Setup sources -+cp "${abs_srcdir}"/data/SOURCES/hello.c ${TOPDIR}/SOURCES -+ -+# Build, contains one ELF which should have a buildid. -+run rpmbuild \ -+ --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="_build_id_links compat" \ -+ --define "_unique_debug_names 1" \ -+ --define "_unique_debug_srcs 1" \ -+ --quiet -ba "${abs_srcdir}"/data/SPECS/hello-config-buildid.spec -+ -+# Should contain one config file. -+run rpm -c -qp ${abs_builddir}/testing/build/RPMS/*/test-1.0-1*rpm -+# Should not contain config files. -+run rpm -c -qp ${abs_builddir}/testing/build/RPMS/*/test-debuginfo-1.0-1*rpm -+], -+[0], -+[/etc/config.file -+], -+[ignore]) -+AT_CLEANUP - diff --git a/0026-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch b/0026-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch new file mode 100644 index 0000000..0209e61 --- /dev/null +++ b/0026-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch @@ -0,0 +1,51 @@ +From 419ae36f2c0dad195737982b446fcace507d0814 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 21 Mar 2017 16:57:44 +0100 +Subject: [PATCH 26/49] debugedit: Fix off-by-one adding DW_FORM_string + replacement slashes. + +We would put one too many slashes in between the new dest_dir and file name +part of the replacement of a DW_FORM_string in the .debug_info. If there +was file part then we would overwrite the first character of the name. If +there was no file part at all then this would overwrite the zero terminator +and cause a crash reading the rest of the data. + +A crash did happen while building the docker package on fedora s390x. +https://bugzilla.redhat.com/show_bug.cgi?id=1434347 + +The reason neither issue would normally trigger is because if we do detect +that the dest_dir is larger than the base_dir we refuse to replace anything. + +Signed-off-by: Mark Wielaard +--- + tools/debugedit.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 0f373162d..b618dceb5 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1507,12 +1507,16 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + comp_dir, base_dir, dest_dir); + else + { +- /* Add one or more slashes in between to +- fill up all space (replacement must be +- of the same length). */ ++ /* Add zero (if no file part), one or more ++ slashes in between the new dest_dir and the ++ file name to fill up all space (replacement ++ DW_FORM_string must be of the same length). ++ We don't need to copy the old file name (if ++ any) or the zero terminator, because those ++ are already at the end of the string. */ + memcpy (ptr, dest_dir, dest_len); + memset (ptr + dest_len, '/', +- orig_len - new_len + 1); ++ orig_len - new_len); + } + } + } +-- +2.13.2 + diff --git a/0027-Unbreak-short-circuited-binary-builds.patch b/0027-Unbreak-short-circuited-binary-builds.patch new file mode 100644 index 0000000..36fda10 --- /dev/null +++ b/0027-Unbreak-short-circuited-binary-builds.patch @@ -0,0 +1,177 @@ +From 6328e1e0da3ba26885f095ccbd83d223d5830527 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 5 Jan 2017 13:47:28 +0200 +Subject: [PATCH 27/49] Unbreak short-circuited binary builds + +Commit bbfe1f86b2e4b5c0bd499d9f3dd9de9c9c20fff2 broke short-circuited +binary builds (which can be handy for testing when working on large +packages), eg: + rpmbuild -bi foo.spec; rpmbuild -bb --short-circuit foo.spec + +The problem is that in a short-circuited build all the links already +exist and point to the right place, but the code doesn't realize this +and creates new links instead, which leaves the old links unowned +in the buildroot which ultimately causes the build to fail with +"Installed (but unpackaged) file(s) found" for the previously created +build-id links. + +When checking for pre-existing links see if they already point to +the right file and in that case just reuse it instead of creating new ones. +Keep track of duplicate build-ids found by noticing existing links that +point to different targets. But don't do this for compat links, they should +just point to the last (duplicate) main build-id symlink found. + +Signed-off-by: Mark Wielaard +(cherry picked from commit eea78b023539875309b7d38e4c8924f647644924) +--- + build/files.c | 71 ++++++++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 51 insertions(+), 20 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 9f7def78c..2f02587f0 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -1565,11 +1565,12 @@ exit: + + static int addNewIDSymlink(FileList fl, + char *targetpath, char *idlinkpath, +- int isDbg, int isCompat) ++ int isDbg, int *dups) + { + const char *linkerr = _("failed symlink"); + int rc = 0; + int nr = 0; ++ int exists = 0; + char *origpath, *linkpath; + + if (isDbg) +@@ -1579,6 +1580,26 @@ static int addNewIDSymlink(FileList fl, + origpath = linkpath; + + while (faccessat(AT_FDCWD, linkpath, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { ++ /* We don't care about finding dups for compat links, they are ++ OK as is. Otherwise we will need to double check if ++ existing link points to the correct target. */ ++ if (dups == NULL) ++ { ++ exists = 1; ++ break; ++ } ++ ++ char ltarget[PATH_MAX]; ++ ssize_t llen; ++ /* In short-circuited builds the link might already exist */ ++ if ((llen = readlink(linkpath, ltarget, sizeof(ltarget)-1)) != -1) { ++ ltarget[llen] = '\0'; ++ if (rstreq(ltarget, targetpath)) { ++ exists = 1; ++ break; ++ } ++ } ++ + if (nr > 0) + free(linkpath); + nr++; +@@ -1586,21 +1607,16 @@ static int addNewIDSymlink(FileList fl, + isDbg ? ".debug" : ""); + } + +- char *symtarget = targetpath; +- if (nr > 0 && isCompat) +- rasprintf (&symtarget, "%s.%d", targetpath, nr); +- +- if (symlink(symtarget, linkpath) < 0) { ++ if (!exists && symlink(targetpath, linkpath) < 0) { + rc = 1; + rpmlog(RPMLOG_ERR, "%s: %s -> %s: %m\n", +- linkerr, linkpath, symtarget); ++ linkerr, linkpath, targetpath); + } else { + fl->cur.isDir = 0; + rc = addFile(fl, linkpath, NULL); + } + +- /* Don't warn (again) if this is a compat id-link, we retarget it. */ +- if (nr > 0 && !isCompat) { ++ if (nr > 0) { + /* Lets see why there are multiple build-ids. If the original + targets are hard linked, then it is OK, otherwise warn + something fishy is going on. Would be nice to call +@@ -1629,8 +1645,8 @@ static int addNewIDSymlink(FileList fl, + free(origpath); + if (nr > 0) + free(linkpath); +- if (nr > 0 && isCompat) +- free(symtarget); ++ if (dups != NULL) ++ *dups = nr; + + return rc; + } +@@ -1872,6 +1888,7 @@ static int generateBuildIDs(FileList fl) + || (rc = addFile(fl, buildidsubdir, NULL)) == 0) { + char *linkpattern, *targetpattern; + char *linkpath, *targetpath; ++ int dups = 0; + if (isDbg) { + linkpattern = "%s/%s"; + targetpattern = "../../../../..%s"; +@@ -1883,7 +1900,7 @@ static int generateBuildIDs(FileList fl) + buildidsubdir, &ids[i][2]); + rasprintf(&targetpath, targetpattern, paths[i]); + rc = addNewIDSymlink(fl, targetpath, linkpath, +- isDbg, 0); ++ isDbg, &dups); + + /* We might want to have a link from the debug + build_ids dir to the main one. We create it +@@ -1906,16 +1923,30 @@ static int generateBuildIDs(FileList fl) + && build_id_links == BUILD_IDS_COMPAT) { + /* buildidsubdir already points to the + debug buildid. We just need to setup +- the symlink to the main one. */ ++ the symlink to the main one. There ++ might be duplicate IDs, those are found ++ by the addNewIDSymlink above. Target ++ the last found duplicate, if any. */ + free(linkpath); + free(targetpath); +- rasprintf(&linkpath, "%s/%s", +- buildidsubdir, &ids[i][2]); +- rasprintf(&targetpath, +- "../../../.build-id%s/%s", +- subdir, &ids[i][2]); ++ if (dups == 0) ++ { ++ rasprintf(&linkpath, "%s/%s", ++ buildidsubdir, &ids[i][2]); ++ rasprintf(&targetpath, ++ "../../../.build-id%s/%s", ++ subdir, &ids[i][2]); ++ } ++ else ++ { ++ rasprintf(&linkpath, "%s/%s.%d", ++ buildidsubdir, &ids[i][2], dups); ++ rasprintf(&targetpath, ++ "../../../.build-id%s/%s.%d", ++ subdir, &ids[i][2], dups); ++ } + rc = addNewIDSymlink(fl, targetpath, linkpath, +- 0, 1); ++ 0, NULL); + } + + if (rc == 0 && isDbg +@@ -1953,7 +1984,7 @@ static int generateBuildIDs(FileList fl) + rasprintf(&targetpath, "../../../../..%s", + targetstr); + rc = addNewIDSymlink(fl, targetpath, +- linkpath, 0, 0); ++ linkpath, 0, &dups); + free(targetstr); + } + } +-- +2.13.2 + diff --git a/0028-find-debuginfo.sh-Only-add-minisymtab-for-executable.patch b/0028-find-debuginfo.sh-Only-add-minisymtab-for-executable.patch new file mode 100644 index 0000000..173a38b --- /dev/null +++ b/0028-find-debuginfo.sh-Only-add-minisymtab-for-executable.patch @@ -0,0 +1,42 @@ +From 349489c3219e31efd552d87e255b06a864d1c034 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Sun, 16 Apr 2017 18:16:02 +0200 +Subject: [PATCH 28/49] find-debuginfo.sh: Only add minisymtab for executables + or shared libraries. + +It only makes sense to add a minisymtab for executables and shared +libraries. Other executable ELF files (like kernel modules) don't need it. +Since those don't have a dynsym section trying to add it will fail and +produce confusing errors from nm. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 3790a6872749a9601be6044be7d8fb0951131376) +--- + scripts/find-debuginfo.sh | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index 1420ef6cd..f1ffcd7d8 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -347,7 +347,16 @@ while read nlinks inum f; do + fi + + # strip -g implies we have full symtab, don't add mini symtab in that case. +- $strip_g || ($include_minidebug && add_minidebug "${debugfn}" "$f") ++ # It only makes sense to add a minisymtab for executables and shared ++ # libraries. Other executable ELF files (like kernel modules) don't need it. ++ if [ "$include_minidebug" = "true" -a "$strip_g" = "false" ]; then ++ skip_mini=true ++ case "$(file -bi "$f")" in ++ application/x-sharedlib*) skip_mini=false ;; ++ application/x-executable*) skip_mini=false ;; ++ esac ++ $skip_mini || add_minidebug "${debugfn}" "$f" ++ fi + + echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" + +-- +2.13.2 + diff --git a/0029-debugedit-Add-n-no-recompute-build-id.patch b/0029-debugedit-Add-n-no-recompute-build-id.patch new file mode 100644 index 0000000..68169b0 --- /dev/null +++ b/0029-debugedit-Add-n-no-recompute-build-id.patch @@ -0,0 +1,285 @@ +From 525282b9a8b78c2890c752e45c4dc7dcf25f42cb Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Sun, 16 Apr 2017 18:16:46 +0200 +Subject: [PATCH 29/49] debugedit: Add -n, --no-recompute-build-id. + +Some packages depend on the build-ids as generated during the build +and cannot handle rpmbuild recomputing them before generating the +package file list. Add -n, --no-recompute-build-id to debugedit and +add -n to find-debuginfo.sh set by defining the %_no_recompute_build_ids +macro for such packages. %_no_recompute_build_ids can not be used together +with %_unique_build_ids. + +Signed-off-by: Mark Wielaard + +(cherry picked from commit 6e9fd97f6dba9e04cfd33225b610272b964cc5fc) + +Conflicts: + macros.in + scripts/find-debuginfo.sh +--- + macros.in | 7 ++- + scripts/find-debuginfo.sh | 20 +++++++- + tests/rpmbuildid.at | 122 ++++++++++++++++++++++++++++++++++++++++++++++ + tools/debugedit.c | 6 ++- + 4 files changed, 151 insertions(+), 4 deletions(-) + +diff --git a/macros.in b/macros.in +index e48ef60c8..c5b1a0b26 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,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} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ + %{nil} + + # Template for debug information sub-package. +@@ -488,6 +488,11 @@ package or when debugging this package.\ + # onto debugedit --build-id-seed to be used to prime the build-id note hash. + %_unique_build_ids 1 + ++# Do not recompute build-ids but keep whatever is in the ELF file already. ++# Cannot be used together with _unique_build_ids (which forces recomputation). ++# Defaults to undefined (unset). ++#%_no_recompute_build_ids 1 ++ + # Whether .debug files should be made unique between package version, + # release and architecture. If set to 1 this will pass + # --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index f1ffcd7d8..1d3dc0623 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] [-m] [-i] ++# Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n] + # [-o debugfiles.list] + # [--run-dwz] [--dwz-low-mem-die-limit N] + # [--dwz-max-die-limit N] +@@ -16,6 +16,7 @@ + # The -r flag says to use eu-strip --reloc-debug-sections. + # The -m flag says to include a .gnu_debugdata section in the main binary. + # The -i flag says to include a .gdb_index section in the .debug file. ++# The -n flag says to not recompute the build-id. + # + # A single -o switch before any -l or -p switches simply renames + # the primary output file from debugfiles.list to something else. +@@ -56,6 +57,9 @@ include_gdb_index=false + # Barf on missing build IDs. + strict=false + ++# Do not recompute build IDs. ++no_recompute_build_id=false ++ + # DWZ parameters. + run_dwz=false + dwz_low_mem_die_limit= +@@ -107,6 +111,9 @@ while [ $# -gt 0 ]; do + -m) + include_minidebug=true + ;; ++ -n) ++ no_recompute_build_id=true ++ ;; + -i) + include_gdb_index=true + ;; +@@ -149,6 +156,11 @@ if test -z "$unique_debug_arch" -a -n "$unique_debug_src_base"; then + exit 2 + fi + ++if test -n "$ver_rel" -a "$no_recompute_build_id" = "true"; then ++ echo >&2 "*** ERROR: --ver-rel (unique build-ids) and -n (do not recompute build-id cannot be used together" ++ exit 2 ++fi ++ + i=0 + while ((i < nout)); do + outs[$i]="$BUILDDIR/${outs[$i]}" +@@ -310,8 +322,12 @@ while read nlinks inum f; do + debug_base_name="$BUILDDIR" + debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" + fi ++ no_recompute= ++ if [ "$no_recompute_build_id" = "true" ]; then ++ no_recompute="-n" ++ fi + id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ +- -i $build_id_seed -l "$SOURCEFILE" "$f") || exit ++ $no_recompute -i $build_id_seed -l "$SOURCEFILE" "$f") || exit + if [ $nlinks -gt 1 ]; then + eval linkedid_$inum=\$id + fi +diff --git a/tests/rpmbuildid.at b/tests/rpmbuildid.at +index 158ce122d..4fab3d5dc 100644 +--- a/tests/rpmbuildid.at ++++ b/tests/rpmbuildid.at +@@ -1060,6 +1060,128 @@ debug dup id in debug package + AT_CLEANUP + + # ------------------------------ ++# Check build-ids are recomputed with unique_build_ids, ++# but not with _no_recompute_build_ids ++AT_SETUP([rpmbuild buildid recompute]) ++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 ++ ++# Make sure we get debuginfo ++export CFLAGS="-g" ++ ++# Unique 1 ++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" \ ++ --undefine="_no_recompute_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 ++test -f $hello_file || echo "No $hello_file" ++id1=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++ ++# Make sure we generate a new one ++rm $hello_file ++ ++# Unique 2 ++# 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" \ ++ --undefine="_no_recompute_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 ++test -f $hello_file || echo "No $hello_file" ++id2=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++ ++# Two unique builds should not be equal ++if test "$id1" == "$id2"; then ++ echo "uniques equal"; ++else ++ echo "uniques unequal"; ++fi ++ ++# Make sure we generate a new one ++rm $hello_file ++ ++# no-recompute 1 ++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" \ ++ --undefine="_unique_debug_names" \ ++ --undefine="_unique_debug_srcs" \ ++ --define="_no_recompute_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 ++test -f $hello_file || echo "No $hello_file" ++id3=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++ ++# An unique and no-recompute build should be unequal ++if test "$id2" == "$id3"; then ++ echo "no-recompute unique equal"; ++else ++ echo "no-recompute unique unequal"; ++fi ++ ++# Make sure we generate a new one ++rm $hello_file ++ ++# no-recompute 2 ++# 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" \ ++ --undefine="_unique_debug_names" \ ++ --undefine="_unique_debug_srcs" \ ++ --define="_no_recompute_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 ++test -f $hello_file || echo "No $hello_file" ++id4=$(file $hello_file | sed 's/.*, BuildID\[[.*\]]=\([[0-9a-f]]*\),.*/\1/') ++ ++# Two no-recompute builds should be equal. Even for different "releases". ++if test "$id3" == "$id4"; then ++ echo "no-recomputes equal"; ++else ++ echo "no-recomputes unequal"; ++fi ++], ++[0], ++[uniques unequal ++no-recompute unique unequal ++no-recomputes equal ++], ++[ignore]) ++AT_CLEANUP ++ ++# ------------------------------ + # Check build-ids are unique between versions/releases + # with _unique_build_ids defined. + AT_SETUP([rpmbuild buildid unique r1 r2]) +diff --git a/tools/debugedit.c b/tools/debugedit.c +index b618dceb5..8444e030e 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -85,6 +85,7 @@ char *dest_dir = NULL; + char *list_file = NULL; + int list_file_fd = -1; + int do_build_id = 0; ++int no_recompute_build_id = 0; + char *build_id_seed = NULL; + + /* We go over the debug sections in two phases. In phase zero we keep +@@ -2261,6 +2262,8 @@ static struct poptOption optionsTable[] = { + "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 }, ++ { "no-recompute-build-id", 'n', POPT_ARG_NONE, &no_recompute_build_id, 0, ++ "do not recompute build ID note even when -i or -s are given", NULL }, + POPT_AUTOHELP + { NULL, 0, 0, NULL, 0, NULL, NULL } + }; +@@ -2380,7 +2383,8 @@ handle_build_id (DSO *dso, Elf_Data *build_id, + exit (1); + } + +- if (!dirty_elf && build_id_seed == NULL) ++ if (no_recompute_build_id ++ || (! dirty_elf && build_id_seed == NULL)) + goto print; + + /* Clear the old bits so they do not affect the new hash. */ +-- +2.13.2 + diff --git a/0030-Fix-non-standard-inherented-modes-of-directories-in-.patch b/0030-Fix-non-standard-inherented-modes-of-directories-in-.patch new file mode 100644 index 0000000..2ac432a --- /dev/null +++ b/0030-Fix-non-standard-inherented-modes-of-directories-in-.patch @@ -0,0 +1,39 @@ +From ba8f2239de528f02d272aed71599a4a560ddd238 Mon Sep 17 00:00:00 2001 +From: Robin Lee +Date: Sat, 8 Apr 2017 21:21:39 +0800 +Subject: [PATCH 30/49] Fix non-standard inherented modes of directories in + debuginfo + +In case that binary compiled from source generated in /tmp, a +/usr/src/debug/tmp directory will be created with the same mode as +/tmp, a.k.a 777, which should be avoided. + +Fixes: rhbz#641022 +(cherry picked from commit c707ab26362e795d3f9dba4eb87dc7ed99a28bcb) +--- + scripts/find-debuginfo.sh | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + mode change 100644 => 100755 scripts/find-debuginfo.sh + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +old mode 100644 +new mode 100755 +index 1d3dc0623..5087c4050 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -443,9 +443,10 @@ if [ -s "$SOURCEFILE" ]; then + mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" + LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(|)$' | + (cd "${debug_base_name}"; cpio -pd0mL "${RPM_BUILD_ROOT}${debug_dest_name}") +- # stupid cpio creates new directories in mode 0700, fixup ++ # stupid cpio creates new directories in mode 0700, ++ # and non-standard modes may be inherented from original directories, fixup + find "${RPM_BUILD_ROOT}${debug_dest_name}" -type d -print0 | +- xargs --no-run-if-empty -0 chmod a+rx ++ xargs --no-run-if-empty -0 chmod 0755 + fi + + if [ -d "${RPM_BUILD_ROOT}/usr/lib" -o -d "${RPM_BUILD_ROOT}/usr/src" ]; then +-- +2.13.2 + diff --git a/0031-debugedit-Only-output-comp_dir-under-build-dir-once.patch b/0031-debugedit-Only-output-comp_dir-under-build-dir-once.patch new file mode 100644 index 0000000..99891e7 --- /dev/null +++ b/0031-debugedit-Only-output-comp_dir-under-build-dir-once.patch @@ -0,0 +1,81 @@ +From 387acd5cb74c968b4751a1c2c731964fc1ab6c3f Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Fri, 21 Apr 2017 17:33:26 +0200 +Subject: [PATCH 31/49] debugedit: Only output comp_dir under build dir (once). + +The fix for rhbz#444310 (commit c1a5eb - Include empty CU current dirs) +was a little greedy. It would also include comp_dirs outside the build +root. Those are unnecessary and we don't have a good way to store them. +Such dirs (e.g. /tmp) would then show up at the root of /usr/src/debug. + +Fix this by including only comp_dirs under base_dir. Also only output +all dirs once (during phase zero) and don't output empty dirs (which +was harmless but would produce a warning from cpio). + +This still includes all empty dirs from the original rhbz#444310 +nodir testcase and it is an alternative fix for rhbz#641022 +(commit c707ab). + +Both fixes are necessary in case of an unexpected mode for a directory +actually in the build root that we want to include in the source list. + +Signed-off-by: Mark Wielaard +(cherry picked from commit e795899780337dea751d85db8f381eff3fe75275) +--- + tools/debugedit.c | 39 ++++++++++++++++----------------------- + 1 file changed, 16 insertions(+), 23 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 8444e030e..bf115136c 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1680,30 +1680,23 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + /* Ensure the CU current directory will exist even if only empty. Source + filenames possibly located in its parent directories refer relatively to + it and the debugger (GDB) cannot safely optimize out the missing +- CU current dir subdirectories. */ +- if (comp_dir && list_file_fd != -1) ++ CU current dir subdirectories. Only do this once in phase one. And ++ only do this for dirs under our build/base_dir. Don't output the ++ empty string (in case the comp_dir == base_dir). */ ++ if (phase == 0 && base_dir && comp_dir && list_file_fd != -1) + { +- const char *p = NULL; +- size_t size; +- +- if (base_dir) +- { +- p = skip_dir_prefix (comp_dir, base_dir); +- if (p == NULL && dest_dir != NULL) +- p = skip_dir_prefix (comp_dir, dest_dir); +- } +- +- if (p == NULL) +- p = comp_dir; +- +- size = strlen (p) + 1; +- while (size > 0) +- { +- ssize_t ret = write (list_file_fd, p, size); +- if (ret == -1) +- break; +- size -= ret; +- p += ret; ++ const char *p = skip_dir_prefix (comp_dir, base_dir); ++ if (p != NULL && p[0] != '\0') ++ { ++ size_t size = strlen (p) + 1; ++ while (size > 0) ++ { ++ ssize_t ret = write (list_file_fd, p, size); ++ if (ret == -1) ++ break; ++ size -= ret; ++ p += ret; ++ } + } + } + +-- +2.13.2 + diff --git a/0032-find-debuginfo.sh-Split-directory-traversal-and-debu.patch b/0032-find-debuginfo.sh-Split-directory-traversal-and-debu.patch new file mode 100644 index 0000000..919bc07 --- /dev/null +++ b/0032-find-debuginfo.sh-Split-directory-traversal-and-debu.patch @@ -0,0 +1,114 @@ +From 534fae47e4d05fd27c277c9e04ad238e608289f5 Mon Sep 17 00:00:00 2001 +From: Michal Marek +Date: Sat, 10 Sep 2016 23:13:24 +0200 +Subject: [PATCH 32/49] find-debuginfo.sh: Split directory traversal and + debuginfo extraction + +This siplifies the handling of hardlinks a bit and allows a later patch +to parallelize the debuginfo extraction. + +Signed-off-by: Michal Marek + +(cherry picked from commit 038bfe01796f751001e02de41c5d8678f511f366) + +Conflicts: + scripts/find-debuginfo.sh +--- + scripts/find-debuginfo.sh | 53 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + mode change 100755 => 100644 scripts/find-debuginfo.sh + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +old mode 100755 +new mode 100644 +index 5087c4050..097b749bb +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -283,32 +283,36 @@ set -o pipefail + strict_error=ERROR + $strict || strict_error=WARNING + +-# Strip ELF binaries ++temp=$(mktemp -d ${TMPDIR:-/tmp}/find-debuginfo.XXXXXX) ++trap 'rm -rf "$temp"' EXIT ++ ++# Build a list of unstripped ELF files and their hardlinks ++touch "$temp/primary" + find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \ + \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \ + -print | + file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped.*/\1/p' | + xargs --no-run-if-empty stat -c '%h %D_%i %n' | + while read nlinks inum f; do +- get_debugfn "$f" +- [ -f "${debugfn}" ] && continue +- +- # If this file has multiple links, keep track and make +- # the corresponding .debug files all links to one file too. + if [ $nlinks -gt 1 ]; then +- eval linked=\$linked_$inum +- if [ -n "$linked" ]; then +- eval id=\$linkedid_$inum +- link=$debugfn +- get_debugfn "$linked" +- echo "hard linked $link to $debugfn" +- mkdir -p "$(dirname "$link")" && ln -nf "$debugfn" "$link" ++ var=seen_$inum ++ if test -n "${!var}"; then ++ echo "$inum $f" >>"$temp/linked" + continue + else +- eval linked_$inum=\$f +- echo "file $f has $[$nlinks - 1] other hard links" ++ read "$var" < <(echo 1) + fi + fi ++ echo "$nlinks $inum $f" >>"$temp/primary" ++done ++ ++# Strip ELF binaries ++do_file() ++{ ++ local nlinks=$1 inum=$2 f=$3 id link linked ++ ++ get_debugfn "$f" ++ [ -f "${debugfn}" ] && return + + echo "extracting debug info from $f" + build_id_seed= +@@ -328,9 +332,6 @@ while read nlinks inum f; do + fi + id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ + $no_recompute -i $build_id_seed -l "$SOURCEFILE" "$f") || exit +- if [ $nlinks -gt 1 ]; then +- eval linkedid_$inum=\$id +- fi + if [ -z "$id" ]; then + echo >&2 "*** ${strict_error}: No build ID note found in $f" + $strict && exit 2 +@@ -376,7 +377,21 @@ while read nlinks inum f; do + + echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" + +-done || exit ++ # If this file has multiple links, make the corresponding .debug files ++ # all links to one file too. ++ if [ $nlinks -gt 1 ]; then ++ grep "^$inum " "$temp/linked" | while read inum linked; do ++ link=$debugfn ++ get_debugfn "$linked" ++ echo "hard linked $link to $debugfn" ++ mkdir -p "$(dirname "$debugfn")" && ln -nf "$link" "$debugfn" ++ done ++ fi ++} ++ ++while read nlinks inum f; do ++ do_file "$nlinks" "$inum" "$f" ++done <"$temp/primary" + + # Invoke the DWARF Compressor utility. + if $run_dwz \ +-- +2.13.2 + diff --git a/0033-find-debuginfo.sh-Use-return-not-continue-to-break-o.patch b/0033-find-debuginfo.sh-Use-return-not-continue-to-break-o.patch new file mode 100644 index 0000000..0069967 --- /dev/null +++ b/0033-find-debuginfo.sh-Use-return-not-continue-to-break-o.patch @@ -0,0 +1,37 @@ +From 3e0419ebc11494d9848decfdfb4909cbce9448b7 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 28 Jun 2017 14:21:32 +0200 +Subject: [PATCH 33/49] find-debuginfo.sh: Use 'return', not 'continue', to + break out do_file(). + +commit 038bfe "Split directory traversal and debuginfo extraction" +put the core of a while loop into its own function 'do_file()'. +That means that instead of using 'continue' to break out early it now +needs to use 'return'. Otherwise the script will give errors like: + + continue: only meaningful in a `for', `while', or `until' loop + +https://bugzilla.redhat.com/show_bug.cgi?id=1465170 + +Signed-off-by: Mark Wielaard +(cherry picked from commit a08e154459d160ff9a9a5576266e685ab85bfc5d) +--- + scripts/find-debuginfo.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index 097b749bb..c435a02e4 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -351,7 +351,7 @@ do_file() + # just has its file names collected and adjusted. + case "$dn" in + /usr/lib/debug/*) +- continue ;; ++ return ;; + esac + + mkdir -p "${debugdn}" +-- +2.13.2 + diff --git a/0034-find-debuginfo.sh-Process-files-in-parallel.patch b/0034-find-debuginfo.sh-Process-files-in-parallel.patch new file mode 100644 index 0000000..9b73611 --- /dev/null +++ b/0034-find-debuginfo.sh-Process-files-in-parallel.patch @@ -0,0 +1,125 @@ +From aede94115e077e87504b03bf668ef375290200ad Mon Sep 17 00:00:00 2001 +From: Michal Marek +Date: Sat, 10 Sep 2016 23:13:25 +0200 +Subject: [PATCH 34/49] find-debuginfo.sh: Process files in parallel + +Add a -j option, which, when used, will spawn processes to do the +debuginfo extraction in parallel. A pipe is used to dispatch the files among +the processes. + +Signed-off-by: Michal Marek + +(cherry picked from commit 1b338aa84d4c67fefa957352a028eaca1a45d1f6) + +Conflicts: + macros.in + scripts/find-debuginfo.sh +--- + macros.in | 2 +- + scripts/find-debuginfo.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 61 insertions(+), 4 deletions(-) + +diff --git a/macros.in b/macros.in +index c5b1a0b26..93e360c79 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,7 @@ + # the script. See the script for details. + # + %__debug_install_post \ +- %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh %{?_smp_mflags} %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_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 c435a02e4..d8b718bdf 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -74,6 +74,9 @@ unique_debug_arch= + # Base given by --unique-debug-src-base + unique_debug_src_base= + ++# Number of parallel jobs to spawn ++n_jobs=1 ++ + BUILDDIR=. + out=debugfiles.list + nout=0 +@@ -137,6 +140,13 @@ while [ $# -gt 0 ]; do + -r) + strip_r=true + ;; ++ -j) ++ n_jobs=$2 ++ shift ++ ;; ++ -j*) ++ n_jobs=${1#-j} ++ ;; + *) + BUILDDIR=$1 + shift +@@ -389,9 +399,56 @@ do_file() + fi + } + +-while read nlinks inum f; do +- do_file "$nlinks" "$inum" "$f" +-done <"$temp/primary" ++# 16^6 - 1 or about 16 milion files ++FILENUM_DIGITS=6 ++run_job() ++{ ++ local jobid=$1 filenum ++ local SOURCEFILE=$temp/debugsources.$jobid ELFBINSFILE=$temp/elfbins.$jobid ++ ++ >"$SOURCEFILE" ++ >"$ELFBINSFILE" ++ # can't use read -n , because it reads bytes one by one, allowing for ++ # races ++ while :; do ++ filenum=$(dd bs=$(( FILENUM_DIGITS + 1 )) count=1 status=none) ++ if test -z "$filenum"; then ++ break ++ fi ++ do_file $(sed -n "$(( 0x$filenum )) p" "$temp/primary") ++ done ++ echo 0 >"$temp/res.$jobid" ++} ++ ++n_files=$(wc -l <"$temp/primary") ++if [ $n_jobs -gt $n_files ]; then ++ n_jobs=$n_files ++fi ++if [ $n_jobs -le 1 ]; then ++ while read nlinks inum f; do ++ do_file "$nlinks" "$inum" "$f" ++ done <"$temp/primary" ++else ++ for ((i = 1; i <= n_files; i++)); do ++ printf "%0${FILENUM_DIGITS}x\\n" $i ++ done | ( ++ exec 3<&0 ++ for ((i = 0; i < n_jobs; i++)); do ++ # The shell redirects stdin to /dev/null for background jobs. Work ++ # around this by duplicating fd 0 ++ run_job $i <&3 & ++ done ++ wait ++ ) ++ for f in "$temp"/res.*; do ++ res=$(< "$f") ++ if [ "$res" != "0" ]; then ++ exit 1 ++ fi ++ done ++ cat "$temp"/debugsources.* >"$SOURCEFILE" ++ cat "$temp"/elfbins.* >"$ELFBINSFILE" ++fi + + # Invoke the DWARF Compressor utility. + if $run_dwz \ +-- +2.13.2 + diff --git a/0035-Untangle-unique-build-options-in-find-debuginfo.sh.patch b/0035-Untangle-unique-build-options-in-find-debuginfo.sh.patch new file mode 100644 index 0000000..a536590 --- /dev/null +++ b/0035-Untangle-unique-build-options-in-find-debuginfo.sh.patch @@ -0,0 +1,175 @@ +From ac275c650fee13ec0fd204bf2b05fbff01a053cd Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 28 Mar 2017 14:20:50 +0200 +Subject: [PATCH 35/49] Untangle unique build options in find-debuginfo.sh + +Rename --ver-rel option to --build-id-seed, so that it reflects what +it does, not how it is used. + +Remove implcit usage of the old --ver-rel option for --unique-debug-arch +and --unique-debug-src-base, instead already call find-debuginfo.sh with +the version included. + +Rename --unique-debug-arch to --unique-debug-suffix because it now +also contains the package version. + +(cherry picked from commit 4842adfd91c3b37744c66d9f01c0112468fdbf37) +--- + macros.in | 13 +++++++++++- + scripts/find-debuginfo.sh | 53 ++++++++++++++++------------------------------- + 2 files changed, 30 insertions(+), 36 deletions(-) + +diff --git a/macros.in b/macros.in +index 93e360c79..b5bf26ac9 100644 +--- a/macros.in ++++ b/macros.in +@@ -180,7 +180,18 @@ + # the script. See the script for details. + # + %__debug_install_post \ +- %{_rpmconfigdir}/find-debuginfo.sh %{?_smp_mflags} %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ ++ %{_rpmconfigdir}/find-debuginfo.sh \\\ ++ %{?_smp_mflags} \\\ ++ %{?_missing_build_ids_terminate_build:--strict-build-id} \\\ ++ %{?_no_recompute_build_ids:-n} \\\ ++ %{?_include_minidebuginfo:-m} \\\ ++ %{?_include_gdb_index:-i} \\\ ++ %{?_unique_build_ids:--build-id-seed "%{VERSION}-%{RELEASE}"} \\\ ++ %{?_unique_debug_names:--unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch}"} \\\ ++ %{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\ ++ %{?_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 d8b718bdf..cd2931c0d 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -6,7 +6,7 @@ + # [-o debugfiles.list] + # [--run-dwz] [--dwz-low-mem-die-limit N] + # [--dwz-max-die-limit N] +-# [--ver-rel VERSION-RELEASE] ++# [--build-id-seed VERSION-RELEASE] + # [[-l filelist]... [-p 'pattern'] -o debuginfo.list] + # [builddir] + # +@@ -30,7 +30,7 @@ + # 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 ++# If --build-id-seed 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 +@@ -65,11 +65,11 @@ run_dwz=false + dwz_low_mem_die_limit= + dwz_max_die_limit= + +-# Version and release of the spec. Given by --ver-rel +-ver_rel= ++# build id seed given by the --build-id-seed option ++build_id_seed= + + # Arch given by --unique-debug-arch +-unique_debug_arch= ++unique_debug_suffix= + + # Base given by --unique-debug-src-base + unique_debug_src_base= +@@ -96,12 +96,12 @@ while [ $# -gt 0 ]; do + dwz_max_die_limit=$2 + shift + ;; +- --ver-rel) +- ver_rel=$2 ++ --build-id-seed) ++ build_id_seed=$2 + shift + ;; +- --unique-debug-arch) +- unique_debug_arch=$2 ++ --unique-debug-suffix) ++ unique_debug_suffix=$2 + shift + ;; + --unique-debug-src-base) +@@ -156,18 +156,8 @@ while [ $# -gt 0 ]; do + shift + done + +-if test -z "$ver_rel" -a -n "$unique_debug_arch"; then +- echo >&2 "*** ERROR: --unique-debug-arch (${unique_debug_arch}) needs --ver-rel (${ver_rel})" +- exit 2 +-fi +- +-if test -z "$unique_debug_arch" -a -n "$unique_debug_src_base"; then +- echo >&2 "*** ERROR: --unique-debug-src-base (${unique_debug_src_base}) needs --unique-debug-arch (${unique_debug_arch})" +- exit 2 +-fi +- +-if test -n "$ver_rel" -a "$no_recompute_build_id" = "true"; then +- echo >&2 "*** ERROR: --ver-rel (unique build-ids) and -n (do not recompute build-id cannot be used together" ++if test -n "$build_id_seed" -a "$no_recompute_build_id" = "true"; then ++ echo >&2 "*** ERROR: --build-id-seed (unique build-ids) and -n (do not recompute build-id) cannot be used together" + exit 2 + fi + +@@ -278,12 +268,7 @@ debug_link() + get_debugfn() + { + dn=$(dirname "${1#$RPM_BUILD_ROOT}") +- if test -n "${unique_debug_arch}"; then +- bn=$(basename "$1" .debug)-${ver_rel}.${unique_debug_arch}.debug +- else +- bn=$(basename "$1" .debug).debug +- fi +- ++ bn=$(basename "$1" .debug)${unique_debug_suffix}.debug + debugdn=${debugdir}${dn} + debugfn=${debugdn}/${bn} + } +@@ -325,23 +310,21 @@ do_file() + [ -f "${debugfn}" ] && return + + echo "extracting debug info from $f" +- build_id_seed= +- if [ ! -z "$ver_rel" ]; then +- build_id_seed="--build-id-seed=$ver_rel" +- fi + # See also cpio SOURCEFILE copy. Directories must match up. + debug_base_name="$RPM_BUILD_DIR" + debug_dest_name="/usr/src/debug" + if [ ! -z "$unique_debug_src_base" ]; then + debug_base_name="$BUILDDIR" +- debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" ++ debug_dest_name="/usr/src/debug/${unique_debug_src_base}" + fi + no_recompute= + if [ "$no_recompute_build_id" = "true" ]; then + no_recompute="-n" + fi +- id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ +- $no_recompute -i $build_id_seed -l "$SOURCEFILE" "$f") || exit ++ id=$(${lib_rpm_dir}/debugedit -b "$debug_base_name" -d "$debug_dest_name" \ ++ $no_recompute -i \ ++ ${build_id_seed:+--build-id-seed="$build_id_seed"} \ ++ -l "$SOURCEFILE" "$f") || exit + if [ -z "$id" ]; then + echo >&2 "*** ${strict_error}: No build ID note found in $f" + $strict && exit 2 +@@ -509,7 +492,7 @@ if [ -s "$SOURCEFILE" ]; then + debug_dest_name="/usr/src/debug" + if [ ! -z "$unique_debug_src_base" ]; then + debug_base_name="$BUILDDIR" +- debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" ++ debug_dest_name="/usr/src/debug/${unique_debug_src_base}" + fi + + mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" +-- +2.13.2 + diff --git a/0036-Support-debugsource-subpackages.patch b/0036-Support-debugsource-subpackages.patch new file mode 100644 index 0000000..7d42e05 --- /dev/null +++ b/0036-Support-debugsource-subpackages.patch @@ -0,0 +1,125 @@ +From 01145b9b68b89d0d4d6d5a77d9af70dba7dbc9a3 Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Tue, 28 Mar 2017 14:21:40 +0200 +Subject: [PATCH 36/49] Support debugsource subpackages + +This can be enabled by setting the _debugsource_packages macro. + +(cherry picked from commit 538cecf0f1fe127dc416afce7a7ee6f94fdb1ad7) +--- + macros.in | 28 +++++++++++++++++++++++++--- + scripts/find-debuginfo.sh | 17 ++++++++++++++++- + 2 files changed, 41 insertions(+), 4 deletions(-) + +diff --git a/macros.in b/macros.in +index b5bf26ac9..d104ad5a7 100644 +--- a/macros.in ++++ b/macros.in +@@ -191,13 +191,12 @@ + %{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\ + %{?_find_debuginfo_dwz_opts} \\\ + %{?_find_debuginfo_opts} \\\ ++ %{?_debugsource_packages:-S debugsourcefiles.list} \\\ + "%{_builddir}/%{?buildsubdir}"\ + %{nil} + + # Template for debug information sub-package. +-%debug_package \ +-%ifnarch noarch\ +-%global __debug_package 1\ ++%_debuginfo_template \ + %package debuginfo\ + Summary: Debug information for package %{name}\ + Group: Development/Debug\ +@@ -208,6 +207,26 @@ Debug information is useful when developing applications that use this\ + package or when debugging this package.\ + %files debuginfo -f debugfiles.list\ + %defattr(-,root,root)\ ++%{nil} ++ ++%_debugsource_template \ ++%package debugsource\ ++Summary: Debug sources for package %{name}\ ++Group: Development/Debug\ ++AutoReqProv: 0\ ++%description debugsource\ ++This package provides debug sources for package %{name}.\ ++Debug sources are useful when developing applications that use this\ ++package or when debugging this package.\ ++%files debugsource -f debugsourcefiles.list\ ++%defattr(-,root,root)\ ++%{nil} ++ ++%debug_package \ ++%ifnarch noarch\ ++%global __debug_package 1\ ++%_debuginfo_template\ ++%{?_debugsource_packages:%_debugsource_template}\ + %endif\ + %{nil} + +@@ -517,6 +536,9 @@ package or when debugging this package.\ + # directory under /usr/debug/src as --. + %_unique_debug_srcs 1 + ++# Whether rpm should put debug source files into its own subpackage ++#%_debugsource_packages 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 cd2931c0d..bede833d7 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -4,6 +4,7 @@ + # + # Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n] + # [-o debugfiles.list] ++# [-S debugsourcefiles.list] + # [--run-dwz] [--dwz-low-mem-die-limit N] + # [--dwz-max-die-limit N] + # [--build-id-seed VERSION-RELEASE] +@@ -79,6 +80,7 @@ n_jobs=1 + + BUILDDIR=. + out=debugfiles.list ++srcout= + nout=0 + while [ $# -gt 0 ]; do + case "$1" in +@@ -147,6 +149,10 @@ while [ $# -gt 0 ]; do + -j*) + n_jobs=${1#-j} + ;; ++ -S) ++ srcout=$2 ++ shift ++ ;; + *) + BUILDDIR=$1 + shift +@@ -512,10 +518,19 @@ if [ -d "${RPM_BUILD_ROOT}/usr/lib" -o -d "${RPM_BUILD_ROOT}/usr/src" ]; then + + (cd "${RPM_BUILD_ROOT}/usr" + test ! -d lib/debug || find lib/debug ! -type d +- test ! -d src/debug || find src/debug -mindepth 1 -maxdepth 1 ++ test ! -d src/debug -o -n "$srcout" || find src/debug -mindepth 1 -maxdepth 1 + ) | sed 's,^,/usr/,' >> "$LISTFILE" + fi + ++if [ -n "$srcout" ]; then ++ > "$srcout" ++ if [ -d "${RPM_BUILD_ROOT}/usr/src/debug" ]; then ++ (cd "${RPM_BUILD_ROOT}/usr" ++ find src/debug -mindepth 1 -maxdepth 1 ++ ) | sed 's,^,/usr/,' >> "$srcout" ++ fi ++fi ++ + # Append to $1 only the lines from stdin not already in the file. + append_uniq() + { +-- +2.13.2 + diff --git a/0037-Support-debuginfo-subpackages.patch b/0037-Support-debuginfo-subpackages.patch new file mode 100644 index 0000000..9417e7f --- /dev/null +++ b/0037-Support-debuginfo-subpackages.patch @@ -0,0 +1,479 @@ +From bc5c404e7415108f15a8cd5e8514a74b43a7755a Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Fri, 24 Mar 2017 15:35:23 +0100 +Subject: [PATCH 37/49] Support debuginfo subpackages + +We do this by filtering the debuginfo files generated by find-debuginfo.sh +with the files from the (sub)packages. + +This commit is heavily based on a patch by Richard Biener. + +(cherry picked from commit 980749fdce055254ca92ee7e2595b16750b699a2) + +Conflicts: + build/files.c +--- + build/files.c | 285 ++++++++++++++++++++++++++++++++++++++++++++-- + build/parsePreamble.c | 10 +- + build/parseSpec.c | 2 +- + build/rpmbuild_internal.h | 17 +++ + macros.in | 3 + + 5 files changed, 304 insertions(+), 13 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 2f02587f0..779a2a102 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -40,6 +40,16 @@ + #define SKIPWHITE(_x) {while(*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;} + #define SKIPNONWHITE(_x){while(*(_x) &&!(risspace(*_x) || *(_x) == ',')) (_x)++;} + ++/* the following defines must be in sync with the equally hardcoded paths from ++ * scripts/find-debuginfo.sh ++ */ ++#define BUILD_ID_DIR "/usr/lib/.build-id" ++#define DEBUG_SRC_DIR "/usr/src/debug" ++#define DEBUG_LIB_DIR "/usr/lib/debug" ++#define DEBUG_LIB_PREFIX "/usr/lib/debug/" ++#define DEBUG_ID_DIR "/usr/lib/debug/.build-id" ++#define DEBUG_DWZ_DIR "/usr/lib/debug/.dwz" ++ + /** + */ + enum specfFlags_e { +@@ -1702,9 +1712,8 @@ static int generateBuildIDs(FileList fl) + if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { + /* We determine whether this is a main or + debug ELF based on path. */ +- #define DEBUGPATH "/usr/lib/debug/" + int isDbg = strncmp (flp->cpioPath, +- DEBUGPATH, strlen (DEBUGPATH)) == 0; ++ DEBUG_LIB_PREFIX, strlen (DEBUG_LIB_PREFIX)) == 0; + + /* For the main package files mimic what find-debuginfo.sh does. + Only check build-ids for executable files. Debug files are +@@ -1797,8 +1806,6 @@ static int generateBuildIDs(FileList fl) + if (rc == 0) { + char *attrstr; + /* Add .build-id directories to hold the subdirs/symlinks. */ +- #define BUILD_ID_DIR "/usr/lib/.build-id" +- #define DEBUG_ID_DIR "/usr/lib/debug/.build-id" + + mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL); + debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL); +@@ -1864,8 +1871,8 @@ static int generateBuildIDs(FileList fl) + /* Don't add anything more when an error occured. But do + cleanup. */ + if (rc == 0) { +- int isDbg = strncmp (paths[i], DEBUGPATH, +- strlen (DEBUGPATH)) == 0; ++ int isDbg = strncmp (paths[i], DEBUG_LIB_PREFIX, ++ strlen (DEBUG_LIB_PREFIX)) == 0; + + char *buildidsubdir; + char subdir[4]; +@@ -1967,7 +1974,7 @@ static int generateBuildIDs(FileList fl) + which don't end in ".debug". */ + int pathlen = strlen(paths[i]); + int debuglen = strlen(".debug"); +- int prefixlen = strlen("/usr/lib/debug"); ++ int prefixlen = strlen(DEBUG_LIB_DIR); + int vralen = vra == NULL ? 0 : strlen(vra); + if (pathlen > prefixlen + debuglen + vralen + && strcmp ((paths[i] + pathlen - debuglen), +@@ -2621,24 +2628,273 @@ exit: + return rc; + } + ++static rpmTag copyTagsFromMainDebug[] = { ++ RPMTAG_ARCH, ++ RPMTAG_SUMMARY, ++ RPMTAG_DESCRIPTION, ++ RPMTAG_GROUP, ++ /* see addTargets */ ++ RPMTAG_OS, ++ RPMTAG_PLATFORM, ++ RPMTAG_OPTFLAGS, ++}; ++ ++/* this is a hack: patch the summary and the description to include ++ * the correct package name */ ++static void patchDebugPackageString(Package dbg, rpmTag tag, Package pkg, Package mainpkg) ++{ ++ const char *oldname, *newname, *old; ++ char *oldsubst = NULL, *newsubst = NULL, *p; ++ oldname = headerGetString(mainpkg->header, RPMTAG_NAME); ++ newname = headerGetString(pkg->header, RPMTAG_NAME); ++ rasprintf(&oldsubst, "package %s", oldname); ++ rasprintf(&newsubst, "package %s", newname); ++ old = headerGetString(dbg->header, tag); ++ p = old ? strstr(old, oldsubst) : NULL; ++ if (p) { ++ char *new = NULL; ++ rasprintf(&new, "%.*s%s%s", (int)(p - old), old, newsubst, p + strlen(oldsubst)); ++ headerDel(dbg->header, tag); ++ headerPutString(dbg->header, tag, new); ++ _free(new); ++ } ++ _free(oldsubst); ++ _free(newsubst); ++} ++ ++/* create a new debuginfo subpackage for package pkg from the ++ * main debuginfo package */ ++static Package cloneDebuginfoPackage(rpmSpec spec, Package pkg, Package maindbg) ++{ ++ const char *name = headerGetString(pkg->header, RPMTAG_NAME); ++ char *dbgname = NULL; ++ Package dbg; ++ ++ rasprintf(&dbgname, "%s-%s", name, "debuginfo"); ++ dbg = newPackage(dbgname, spec->pool, &spec->packages); ++ headerPutString(dbg->header, RPMTAG_NAME, dbgname); ++ copyInheritedTags(dbg->header, pkg->header); ++ headerDel(dbg->header, RPMTAG_GROUP); ++ headerCopyTags(maindbg->header, dbg->header, copyTagsFromMainDebug); ++ dbg->autoReq = maindbg->autoReq; ++ dbg->autoProv = maindbg->autoProv; ++ ++ /* patch summary and description strings */ ++ patchDebugPackageString(dbg, RPMTAG_SUMMARY, pkg, spec->packages); ++ patchDebugPackageString(dbg, RPMTAG_DESCRIPTION, pkg, spec->packages); ++ ++ /* Add self-provides (normally done by addTargets) */ ++ addPackageProvides(dbg); ++ dbg->ds = rpmdsThis(dbg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); ++ ++ _free(dbgname); ++ return dbg; ++} ++ ++/* add a directory to the file list */ ++static void argvAddDir(ARGV_t *filesp, const char *dir) ++{ ++ char *line = NULL; ++ rasprintf(&line, "%%dir %s", dir); ++ argvAdd(filesp, line); ++ _free(line); ++} ++ ++/* collect the debug files for package pkg and put them into ++ * a (possibly new) debuginfo subpackage */ ++static void filterDebuginfoPackage(rpmSpec spec, Package pkg, ++ Package maindbg, char *buildroot, char *uniquearch) ++{ ++ rpmfi fi; ++ ARGV_t files = NULL; ++ Package dbg = NULL; ++ char *path = NULL; ++ size_t buildrootlen = strlen(buildroot); ++ ++ /* ignore noarch subpackages */ ++ if (rstreq(headerGetString(pkg->header, RPMTAG_ARCH), "noarch")) ++ return; ++ ++ if (!uniquearch) ++ uniquearch = ""; ++ ++ fi = rpmfilesIter(pkg->cpioList, RPMFI_ITER_FWD); ++ /* Check if the current package has files with debug info ++ and add them to the file list */ ++ fi = rpmfiInit(fi, 0); ++ while (rpmfiNext(fi) >= 0) { ++ const char *name = rpmfiFN(fi); ++ int namel = strlen(name); ++ ++ /* strip trailing .debug like in find-debuginfo.sh */ ++ namel = strlen(name); ++ if (namel > 6 && !strcmp(name + namel - 6, ".debug")) ++ namel -= 6; ++ ++ /* generate path */ ++ rasprintf(&path, "%s%s%.*s%s.debug", buildroot, DEBUG_LIB_DIR, namel, name, uniquearch); ++ ++ /* If that file exists we have debug information for it */ ++ if (access(path, F_OK) == 0) { ++ /* Append the file list preamble */ ++ if (!files) { ++ argvAdd(&files, "%defattr(-,root,root)"); ++ argvAddDir(&files, DEBUG_LIB_DIR); ++ } ++ /* Add the files main debug-info file */ ++ argvAdd(&files, path + buildrootlen); ++ } ++ path = _free(path); ++ } ++ ++ if (files) { ++ /* we have collected some files. Now put them in a debuginfo ++ * package. If this is not the main package, clone the main ++ * debuginfo package */ ++ if (pkg == spec->packages) ++ maindbg->fileList = files; ++ else { ++ Package dbg = cloneDebuginfoPackage(spec, pkg, maindbg); ++ dbg->fileList = files; ++ } ++ } ++} ++ ++/* add the debug dwz files to package pkg. ++ * return 1 if something was added, 0 otherwise. */ ++static int addDebugDwz(Package pkg, char *buildroot) ++{ ++ int ret = 0; ++ char *path = NULL; ++ struct stat sbuf; ++ ++ rasprintf(&path, "%s%s", buildroot, DEBUG_DWZ_DIR); ++ if (lstat(path, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)) { ++ if (!pkg->fileList) { ++ argvAdd(&pkg->fileList, "%defattr(-,root,root)"); ++ argvAddDir(&pkg->fileList, DEBUG_LIB_DIR); ++ } ++ argvAdd(&pkg->fileList, DEBUG_DWZ_DIR); ++ ret = 1; ++ } ++ path = _free(path); ++ return ret; ++} ++ ++/* add the debug source files to package pkg. ++ * return 1 if something was added, 0 otherwise. */ ++static int addDebugSrc(Package pkg, char *buildroot) ++{ ++ int ret = 0; ++ char *path = NULL; ++ DIR *d; ++ struct dirent *de; ++ ++ /* not needed if we have an extra debugsource subpackage */ ++ if (rpmExpandNumeric("%{?_debugsource_packages}")) ++ return 0; ++ ++ rasprintf(&path, "%s%s", buildroot, DEBUG_SRC_DIR); ++ d = opendir(path); ++ path = _free(path); ++ if (d) { ++ while ((de = readdir(d)) != NULL) { ++ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) ++ continue; ++ rasprintf(&path, "%s/%s", DEBUG_SRC_DIR, de->d_name); ++ if (!pkg->fileList) ++ argvAdd(&pkg->fileList, "%defattr(-,root,root)"); ++ argvAdd(&pkg->fileList, path); ++ path = _free(path); ++ ret = 1; ++ } ++ closedir(d); ++ } ++ return ret; ++} ++ ++/* find the main debuginfo package. We do this simply by ++ * searching for a package with the right name. */ ++static Package findDebuginfoPackage(rpmSpec spec) ++{ ++ Package pkg = NULL; ++ if (lookupPackage(spec, "debuginfo", PART_SUBNAME, &pkg)) ++ return NULL; ++ return pkg && pkg->fileList ? pkg : NULL; ++} ++ ++/* add a requires for package "to" into package "from". */ ++static void addPackageRequires(Package from, Package to) ++{ ++ const char *name; ++ char *evr, *isaprov; ++ name = headerGetString(to->header, RPMTAG_NAME); ++ evr = headerGetAsString(to->header, RPMTAG_EVR); ++ isaprov = rpmExpand(name, "%{?_isa}", NULL); ++ addReqProv(from, RPMTAG_REQUIRENAME, isaprov, evr, RPMSENSE_EQUAL, 0); ++ free(isaprov); ++ free(evr); ++} ++ + rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + int installSpecialDoc, int test) + { + Package pkg; + rpmRC rc = RPMRC_OK; ++ char *buildroot; ++ char *uniquearch = NULL; ++ Package maindbg = NULL; /* the (existing) main debuginfo package */ ++ Package deplink = NULL; /* create requires to this package */ + + #if HAVE_LIBDW + elf_version (EV_CURRENT); + #endif + check_fileList = newStringBuf(); + genSourceRpmName(spec); ++ buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL); + ++ if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) { ++ maindbg = findDebuginfoPackage(spec); ++ if (maindbg) { ++ /* move debuginfo package to back */ ++ if (maindbg->next) { ++ Package *pp; ++ /* dequeue */ ++ for (pp = &spec->packages; *pp != maindbg; pp = &(*pp)->next) ++ ; ++ *pp = maindbg->next; ++ maindbg->next = 0; ++ /* enqueue at tail */ ++ for (; *pp; pp = &(*pp)->next) ++ ; ++ *pp = maindbg; ++ } ++ /* delete unsplit file list, we will re-add files back later */ ++ maindbg->fileFile = argvFree(maindbg->fileFile); ++ maindbg->fileList = argvFree(maindbg->fileList); ++ if (rpmExpandNumeric("%{?_unique_debug_names}")) ++ uniquearch = rpmExpand("-%{VERSION}-%{RELEASE}.%{_arch}", NULL); ++ } ++ } ++ + for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { + char *nvr; + const char *a; + int header_color; + int arch_color; + ++ if (pkg == maindbg) { ++ /* if there is just one debuginfo package, we put our extra stuff ++ * in it. Otherwise we put it in the main debug package */ ++ Package extradbg = !maindbg->fileList && maindbg->next && !maindbg->next->next ? ++ maindbg->next : maindbg; ++ if (addDebugDwz(extradbg, buildroot)) ++ deplink = extradbg; ++ if (addDebugSrc(extradbg, buildroot)) ++ deplink = extradbg; ++ maindbg = NULL; /* all normal packages processed */ ++ } ++ + if (pkg->fileList == NULL) + continue; + +@@ -2647,9 +2903,16 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + nvr = headerGetAsString(pkg->header, RPMTAG_NVRA); + rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr); + free(nvr); +- +- if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK || +- (rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK) ++ ++ if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK) ++ goto exit; ++ ++ if (maindbg) ++ filterDebuginfoPackage(spec, pkg, maindbg, buildroot, uniquearch); ++ else if (deplink && pkg != deplink) ++ addPackageRequires(pkg, deplink); ++ ++ if ((rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK) + goto exit; + + a = headerGetString(pkg->header, RPMTAG_ARCH); +@@ -2684,6 +2947,8 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + } + exit: + check_fileList = freeStringBuf(check_fileList); ++ _free(buildroot); ++ _free(uniquearch); + + return rc; + } +diff --git a/build/parsePreamble.c b/build/parsePreamble.c +index 6be440369..3bb833cff 100644 +--- a/build/parsePreamble.c ++++ b/build/parsePreamble.c +@@ -544,6 +544,13 @@ static void fillOutMainPackage(Header h) + + /** + */ ++void copyInheritedTags(Header h, Header fromh) ++{ ++ headerCopyTags(fromh, h, (rpmTagVal *)copyTagsDuringParse); ++} ++ ++/** ++ */ + static rpmRC readIcon(Header h, const char * file) + { + char *fn = NULL; +@@ -1171,8 +1178,7 @@ int parsePreamble(rpmSpec spec, int initialPackage) + } + + if (pkg != spec->packages) { +- headerCopyTags(spec->packages->header, pkg->header, +- (rpmTagVal *)copyTagsDuringParse); ++ copyInheritedTags(pkg->header, spec->packages->header); + } + + if (checkForRequired(pkg->header, NVR)) { +diff --git a/build/parseSpec.c b/build/parseSpec.c +index 9fff0e2c8..582060770 100644 +--- a/build/parseSpec.c ++++ b/build/parseSpec.c +@@ -564,7 +564,7 @@ static void initSourceHeader(rpmSpec spec) + } + + /* Add extra provides to package. */ +-static void addPackageProvides(Package pkg) ++void addPackageProvides(Package pkg) + { + const char *arch, *name; + char *evr, *isaprov; +diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h +index 7dd577f26..7ec05b9c9 100644 +--- a/build/rpmbuild_internal.h ++++ b/build/rpmbuild_internal.h +@@ -442,6 +442,13 @@ int addReqProv(Package pkg, rpmTagVal tagN, + + + /** \ingroup rpmbuild ++ * Add self-provides to package. ++ * @param pkg package ++ */ ++RPM_GNUC_INTERNAL ++void addPackageProvides(Package pkg); ++ ++/** \ingroup rpmbuild + * Add rpmlib feature dependency. + * @param pkg package + * @param feature rpm feature name (i.e. "rpmlib(Foo)" for feature Foo) +@@ -453,6 +460,16 @@ int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEV + + RPM_GNUC_INTERNAL + rpmRC checkForEncoding(Header h, int addtag); ++ ++ ++/** \ingroup rpmbuild ++ * Copy tags inherited by subpackages from the source header to the target header ++ * @param h target header ++ * @param fromh source header ++ */ ++RPM_GNUC_INTERNAL ++void copyInheritedTags(Header h, Header fromh); ++ + #ifdef __cplusplus + } + #endif +diff --git a/macros.in b/macros.in +index d104ad5a7..0c055a7fd 100644 +--- a/macros.in ++++ b/macros.in +@@ -539,6 +539,9 @@ package or when debugging this package.\ + # Whether rpm should put debug source files into its own subpackage + #%_debugsource_packages 1 + ++# Whether rpm should create extra debuginfo packages for each subpackage ++#%_debuginfo_subpackages 1 ++ + # + # Use internal dependency generator rather than external helpers? + %_use_internal_dependency_generator 1 +-- +2.13.2 + diff --git a/0038-Also-add-directories-to-split-debuginfo-packages.patch b/0038-Also-add-directories-to-split-debuginfo-packages.patch new file mode 100644 index 0000000..1620994 --- /dev/null +++ b/0038-Also-add-directories-to-split-debuginfo-packages.patch @@ -0,0 +1,70 @@ +From 9f826d903dabbc2ce199560e296224c320bb840f Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Wed, 29 Mar 2017 14:55:10 +0200 +Subject: [PATCH 38/49] Also add directories to split debuginfo packages + +This gets rid of the last difference between debuginfo subpackages +and normal debuginfo packages. + +(cherry picked from commit a517554e36666f58724620347a4b8224471d2225) +--- + build/files.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +diff --git a/build/files.c b/build/files.c +index 779a2a102..f27dcc7c1 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -2707,8 +2707,9 @@ static void filterDebuginfoPackage(rpmSpec spec, Package pkg, + { + rpmfi fi; + ARGV_t files = NULL; +- Package dbg = NULL; +- char *path = NULL; ++ ARGV_t dirs = NULL; ++ int lastdiridx = -1, dirsadded; ++ char *path = NULL, *p, *pmin; + size_t buildrootlen = strlen(buildroot); + + /* ignore noarch subpackages */ +@@ -2741,12 +2742,37 @@ static void filterDebuginfoPackage(rpmSpec spec, Package pkg, + argvAdd(&files, "%defattr(-,root,root)"); + argvAddDir(&files, DEBUG_LIB_DIR); + } ++ + /* Add the files main debug-info file */ + argvAdd(&files, path + buildrootlen); ++ ++ /* Add the dir(s) */ ++ dirsadded = 0; ++ pmin = path + buildrootlen + strlen(DEBUG_LIB_DIR); ++ while ((p = strrchr(path + buildrootlen, '/')) != NULL && p > pmin) { ++ *p = 0; ++ if (lastdiridx >= 0 && !strcmp(dirs[lastdiridx], path + buildrootlen)) ++ break; /* already added this one */ ++ argvAdd(&dirs, path + buildrootlen); ++ dirsadded++; ++ } ++ if (dirsadded) ++ lastdiridx = argvCount(dirs) - dirsadded; /* remember longest dir */ + } + path = _free(path); + } + ++ /* add collected directories to file list */ ++ if (dirs) { ++ int i; ++ argvSort(dirs, NULL); ++ for (i = 0; dirs[i]; i++) { ++ if (!i || strcmp(dirs[i], dirs[i - 1]) != 0) ++ argvAddDir(&files, dirs[i]); ++ } ++ dirs = argvFree(dirs); ++ } ++ + if (files) { + /* we have collected some files. Now put them in a debuginfo + * package. If this is not the main package, clone the main +-- +2.13.2 + diff --git a/0039-debugedit-skip_dir_prefix-should-check-for-dir-separ.patch b/0039-debugedit-skip_dir_prefix-should-check-for-dir-separ.patch new file mode 100644 index 0000000..1e4af80 --- /dev/null +++ b/0039-debugedit-skip_dir_prefix-should-check-for-dir-separ.patch @@ -0,0 +1,58 @@ +From faaf3bbfc261f49eda996801b50996fb1066092f Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 28 Jun 2017 20:25:39 +0200 +Subject: [PATCH 39/49] debugedit: skip_dir_prefix should check for dir + separator. + +To count as a real directory prefix the string matched should either +be equal to the given prefix or start with the prefix plus '/'. + +skip_dir_prefix is always used with base_dir or dest_dir which don't +end with a slash themselves. + +This really only is an issue if a package would put a directory named +similar to the package source dir (which cargo on fedora does, by adding +a directory named cargo-vendor in the builddir itself). + +Signed-off-by: Mark Wielaard +(cherry picked from commit 2ea5619e375f0717b755c8aa4a38254ea622b833) +--- + tools/debugedit.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index bf115136c..682189929 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -662,7 +662,8 @@ canonicalize_path (const char *s, char *d) + /* Returns the rest of PATH if it starts with DIR_PREFIX, skipping any + / path separators, or NULL if PATH doesn't start with + DIR_PREFIX. Might return the empty string if PATH equals DIR_PREFIX +- (modulo trailing slashes). Never returns path starting with '/'. */ ++ (modulo trailing slashes). Never returns path starting with '/'. ++ Note that DIR_PREFIX itself should NOT end with a '/'. */ + static const char * + skip_dir_prefix (const char *path, const char *dir_prefix) + { +@@ -670,12 +671,17 @@ skip_dir_prefix (const char *path, const char *dir_prefix) + if (strncmp (path, dir_prefix, prefix_len) == 0) + { + path += prefix_len; ++ /* Unless path == dir_prefix there should be at least one '/' ++ in the path (which we will skip). Otherwise the path has ++ a different (longer) directory prefix. */ ++ if (*path != '\0' && !IS_DIR_SEPARATOR (*path)) ++ return NULL; + while (IS_DIR_SEPARATOR (path[0])) + path++; + return path; + } + +- return 0; ++ return NULL; + } + + /* Most strings will be in the existing debug string table. But to +-- +2.13.2 + diff --git a/0040-find-debuginfo.sh-Filter-out-all-built-in-like-fake-.patch b/0040-find-debuginfo.sh-Filter-out-all-built-in-like-fake-.patch new file mode 100644 index 0000000..5952a03 --- /dev/null +++ b/0040-find-debuginfo.sh-Filter-out-all-built-in-like-fake-.patch @@ -0,0 +1,43 @@ +From b4d166652011f0d0e8573feb616283698f6cf848 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 28 Jun 2017 13:34:55 +0200 +Subject: [PATCH 40/49] find-debuginfo.sh: Filter out all like fake + file names. + +There is no official way to mark an instruction range as being not +part of some actual source code, but as part of a compiler built-in +construct in DWARF. So different compilers have come up with fake +source file names like or <__thread_local_inner macros>. +We already filtered out the strings "" and "". +Just filter out all '(^|/)<[a-z _-]+>$'. They are fake files! + +This is mainly to appease the rustc compiler which generates lots of +different variants to encode some instruction sequence is part of an +compiler generated macro expansion. + +Signed-off-by: Mark Wielaard +(cherry picked from commit ff239ff4b06c86485eccaf8f4ecadc9bceb34748) +--- + scripts/find-debuginfo.sh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index bede833d7..eb62a158a 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -502,7 +502,11 @@ if [ -s "$SOURCEFILE" ]; then + fi + + mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" +- LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(|)$' | ++ # Filter out anything compiler generated which isn't a source file. ++ # e.g. , , <__thread_local_inner macros>. ++ # Some compilers generate them as if they are part of the working ++ # directory (which is why we match against ^ or /). ++ LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(^|/)<[a-z _-]+>$' | + (cd "${debug_base_name}"; cpio -pd0mL "${RPM_BUILD_ROOT}${debug_dest_name}") + # stupid cpio creates new directories in mode 0700, + # and non-standard modes may be inherented from original directories, fixup +-- +2.13.2 + diff --git a/0041-find-debuginfo.sh-Don-t-create-dwz-multi-file-if-the.patch b/0041-find-debuginfo.sh-Don-t-create-dwz-multi-file-if-the.patch new file mode 100644 index 0000000..0a36004 --- /dev/null +++ b/0041-find-debuginfo.sh-Don-t-create-dwz-multi-file-if-the.patch @@ -0,0 +1,57 @@ +From f22cb2890026544499ee4f1a309a44c71e0b8152 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Mon, 26 Jun 2017 17:38:30 +0200 +Subject: [PATCH 41/49] find-debuginfo.sh: Don't create dwz multi file if there + is only one .debug. + +dwz -m multi only works when there are multiple .debug input files. +With just one .debug file it doesn't really make sense to extract +the shared debug info into a separate file and dwz will complain: + + dwz: Too few files for multifile optimization. + +So only add -m multi if there is more than one .debug file. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 0f162dc41f2051eab237bd223356d88e94a07580) +--- + scripts/find-debuginfo.sh | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index eb62a158a..3bfc15a79 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -442,8 +442,8 @@ fi + # Invoke the DWARF Compressor utility. + if $run_dwz \ + && [ -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 ++ readarray dwz_files < <(cd "${RPM_BUILD_ROOT}/usr/lib/debug"; find -type f -name \*.debug) ++ if [ ${#dwz_files[@]} -gt 0 ]; then + dwz_multifile_name="${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}-${RPM_PACKAGE_RELEASE}.${RPM_ARCH}" + dwz_multifile_suffix= + dwz_multifile_idx=0 +@@ -452,14 +452,16 @@ if $run_dwz \ + 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}" ++ dwz_opts="-h -q -r" ++ [ ${#dwz_files[@]} -gt 1 ] \ ++ && dwz_opts="${dwz_opts} -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}" + if type dwz >/dev/null 2>&1; then +- ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts $dwz_files ) ++ ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts ${dwz_files[@]} ) + else + echo >&2 "*** ERROR: DWARF compression requested, but no dwz installed" + exit 2 +-- +2.13.2 + diff --git a/0042-Update-find-debuginfo.sh-options-and-macros-document.patch b/0042-Update-find-debuginfo.sh-options-and-macros-document.patch new file mode 100644 index 0000000..6c0586d --- /dev/null +++ b/0042-Update-find-debuginfo.sh-options-and-macros-document.patch @@ -0,0 +1,114 @@ +From 201b856c02aeb3c4fc6b3a8b96ce8817278f4fbf Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Mon, 26 Jun 2017 13:35:48 +0200 +Subject: [PATCH 42/49] Update find-debuginfo.sh options and macros + documentation. + +This adds some missing documentation for rpm macros and find-debuginfo.sh +options that were recently added (or renamed). -j N, --build-id-seed SEED, +--unique-debug-suffix SUFFIX and --unique-debug-src-base BASE. + +Signed-off-by: Mark Wielaard +(cherry picked from commit 173e5642a97c535f8bdaac5bf88854a103cc125b) +--- + macros.in | 14 ++++++++------ + scripts/find-debuginfo.sh | 28 ++++++++++++++++++++++------ + 2 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/macros.in b/macros.in +index 0c055a7fd..2a114ccd7 100644 +--- a/macros.in ++++ b/macros.in +@@ -514,8 +514,9 @@ package or when debugging this package.\ + + # 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. ++# --build-id-seed "%{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 + + # Do not recompute build-ids but keep whatever is in the ELF file already. +@@ -525,15 +526,16 @@ package or when debugging this package.\ + + # Whether .debug files should be made unique between package version, + # release and architecture. If set to 1 this will pass +-# --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create +-# debuginfo files which end in --..debug ++# --unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch} find-debuginfo.sh ++# to create debuginfo files which end in --..debug + # Requires _unique_build_ids. + %_unique_debug_names 1 + + # Whether the /usr/debug/src/ directories should be unique between + # package version, release and architecture. If set to 1 this will pass +-# --unique-debug-src-base "%{name}" to find-debuginfo.sh to name the +-# directory under /usr/debug/src as --. ++# --unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}" to ++# find-debuginfo.sh to name the directory under /usr/debug/src as ++# --.. + %_unique_debug_srcs 1 + + # Whether rpm should put debug source files into its own subpackage +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index 3bfc15a79..185d25f96 100644 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -3,11 +3,14 @@ + #for inclusion in an rpm spec file. + # + # Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n] ++# [-j N] + # [-o debugfiles.list] + # [-S debugsourcefiles.list] + # [--run-dwz] [--dwz-low-mem-die-limit N] + # [--dwz-max-die-limit N] +-# [--build-id-seed VERSION-RELEASE] ++# [--build-id-seed SEED] ++# [--unique-debug-suffix SUFFIX] ++# [--unique-debug-src-base BASE] + # [[-l filelist]... [-p 'pattern'] -o debuginfo.list] + # [builddir] + # +@@ -19,6 +22,9 @@ + # The -i flag says to include a .gdb_index section in the .debug file. + # The -n flag says to not recompute the build-id. + # ++# The -j N option will spawn N processes to do the debuginfo extraction ++# in parallel. ++# + # A single -o switch before any -l or -p switches simply renames + # the primary output file from debugfiles.list to something else. + # A -o switch that follows a -p switch or some -l switches produces +@@ -31,11 +37,21 @@ + # 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 --build-id-seed 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. ++# If --build-id-seed SEED is given then debugedit is called to ++# update the build-ids it finds adding the SEED 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. ++# (Use --build-id-seed "%{VERSION}-%{RELEASE}".) ++# ++# If --unique-debug-suffix SUFFIX is given then the debug files created ++# for will be named -.debug. This makes sure .debug ++# are unique between package version, release and architecture. ++# (Use --unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch}".) ++# ++# If --unique-debug-src-base BASE is given then the source directory ++# will be called /usr/debug/src/. This makes sure the debug source ++# directories are unique between package version, release and architecture. ++# (Use --unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}".) + # + # All file names in switches are relative to builddir (. if not given). + # +-- +2.13.2 + diff --git a/0043-Add-OpenSSL-support-for-digest-and-signatures.patch b/0043-Add-OpenSSL-support-for-digest-and-signatures.patch new file mode 100644 index 0000000..a67536f --- /dev/null +++ b/0043-Add-OpenSSL-support-for-digest-and-signatures.patch @@ -0,0 +1,1173 @@ +From 709e675cdf0c8f9b07507aad12400398f354cc90 Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Mon, 16 Jan 2017 09:19:43 -0500 +Subject: [PATCH 43/49] Add OpenSSL support for digest and signatures + +Autotools: add --with-crypto=openssl +This enables RPM to locate the appropriate flags for compiling +against OpenSSL for digest and hash functions. + +This implementation changes the old behavior of +--with[out]-beecrypt toggling between beecrypt and nss. It will +now throw an error if attempting to use --with-beecrypt +indicating that the user should instead use --with-crypto= + +See also: +https://github.com/rpm-software-management/rpm/issues/119 + +(cherry picked from commit 64028f9a1c25ada8ffc7a48775f526600edcbf85) + +Conflicts: + Makefile.am + configure.ac +--- + INSTALL | 27 +- + Makefile.am | 17 +- + configure.ac | 115 ++++++- + rpmio/Makefile.am | 6 + + rpmio/digest_openssl.c | 838 +++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 982 insertions(+), 21 deletions(-) + create mode 100644 rpmio/digest_openssl.c + +diff --git a/INSTALL b/INSTALL +index 60536e316..8eefef799 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -9,17 +9,34 @@ The libmagic (aka file) library for file type detection (used by rpmbuild). + The source for the file utility + library is available from + ftp://ftp.astron.com/pub/file/ + +-The NSS >= 3.12 library for encryption, and NSPR library which NSS uses. +-Both NSPR and NSS libraries and headers need to be installed during RPM +-compilation. As NSPR and NSS typically install their headers outside +-the regular include search path, you need to tell configure about this, +-eg something like: ++You will need a cryptographic library to support digests and signatures. ++This library may be Mozilla NSS, OpenSSL or beecrypt. Which library to use ++must be specified with the --with-crypto=[beecrypt|nss|openssl] argument ++to configure. ++ ++If using the Mozilla NSS library for encyption (and NSPR library which ++NSS uses) it must be version 3.12 or later. Both NSPR and NSS libraries and ++headers need to be installed during RPM compilation. As NSPR and NSS ++typically install their headers outside the regular include search path, ++you need to tell configure about this, eg something like: + ./configure <......> CPPFLAGS="-I/usr/include/nspr -I/usr/include/nss" + + The NSPR and NSS libraries are available from + http://www.mozilla.org/projects/security/pki/nss/ + http://www.mozilla.org/projects/nspr/ + ++If using the OpenSSL library for encryption, it must be version 1.0.2 or ++later. Note: when compiling against OpenSSL, there is a possible license ++incompatibility. For more details on this, see ++https://people.gnome.org/~markmc/openssl-and-the-gpl.html ++Some Linux distributions have different legal interpretations of this ++possible incompatibility. It is recommended to consult with a lawyer before ++building RPM against OpenSSL. ++Fedora: https://fedoraproject.org/wiki/Licensing:FAQ#What.27s_the_deal_with_the_OpenSSL_license.3F ++Debian: https://lists.debian.org/debian-legal/2002/10/msg00113.html ++ ++The OpenSSL crypto library is available from https://www.openssl.org/ ++ + The Berkeley DB >= 4.3.x (4.5.x or newer recommended) is required for the + default database backend. BDB can be downloaded from + http://www.oracle.com/technology/software/products/berkeley-db/index.html +diff --git a/Makefile.am b/Makefile.am +index 1b77730aa..a5268030b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -41,6 +41,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/build + AM_CPPFLAGS += -I$(top_srcdir)/lib + AM_CPPFLAGS += -I$(top_srcdir)/rpmio + AM_CPPFLAGS += @WITH_NSS_INCLUDE@ ++AM_CPPFLAGS += @WITH_OPENSSL_INCLUDE@ + AM_CPPFLAGS += @WITH_POPT_INCLUDE@ + AM_CPPFLAGS += -I$(top_srcdir)/misc + AM_CPPFLAGS += -DLOCALEDIR="\"$(localedir)\"" +@@ -113,45 +114,45 @@ rpm_SOURCES = rpmqv.c debug.h system.h + rpm_CPPFLAGS = $(AM_CPPFLAGS) -DIAM_RPMEIU -DIAM_RPMQ -DIAM_RPMV + rpm_LDADD = libcliutils.la + rpm_LDADD += lib/librpm.la rpmio/librpmio.la +-rpm_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpm_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpmdb_SOURCES = rpmdb.c debug.h system.h + rpmdb_CPPFLAGS = $(AM_CPPFLAGS) + rpmdb_LDADD = libcliutils.la + rpmdb_LDADD += lib/librpm.la rpmio/librpmio.la +-rpmdb_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpmdb_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpmkeys_SOURCES = rpmkeys.c debug.h system.h + rpmkeys_CPPFLAGS = $(AM_CPPFLAGS) + rpmkeys_LDADD = libcliutils.la + rpmkeys_LDADD += lib/librpm.la rpmio/librpmio.la +-rpmkeys_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpmkeys_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpmsign_SOURCES = rpmsign.c debug.h system.h + rpmsign_CPPFLAGS = $(AM_CPPFLAGS) + rpmsign_LDADD = libcliutils.la + rpmsign_LDADD += sign/librpmsign.la lib/librpm.la rpmio/librpmio.la +-rpmsign_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpmsign_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpmbuild_SOURCES = rpmbuild.c debug.h system.h + rpmbuild_CPPFLAGS = $(AM_CPPFLAGS) + rpmbuild_LDADD = libcliutils.la + rpmbuild_LDADD += build/librpmbuild.la lib/librpm.la rpmio/librpmio.la +-rpmbuild_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpmbuild_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpmspec_SOURCES = rpmspec.c debug.h system.h + rpmspec_CPPFLAGS = $(AM_CPPFLAGS) + rpmspec_LDADD = libcliutils.la + rpmspec_LDADD += build/librpmbuild.la lib/librpm.la rpmio/librpmio.la +-rpmspec_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpmspec_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpm2cpio_SOURCES = rpm2cpio.c debug.h system.h + rpm2cpio_LDADD = lib/librpm.la rpmio/librpmio.la +-rpm2cpio_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ ++rpm2cpio_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + + rpm2archive_SOURCES = rpm2archive.c debug.h system.h + rpm2archive_LDADD = lib/librpm.la rpmio/librpmio.la +-rpm2archive_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ @WITH_ARCHIVE_LIB@ ++rpm2archive_LDADD += @WITH_NSS_LIB@ @WITH_OPENSSL_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ @WITH_ARCHIVE_LIB@ + + + if LIBELF +diff --git a/configure.ac b/configure.ac +index e6362535b..65052870a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -243,18 +243,30 @@ AC_CHECK_HEADERS([dwarf.h], [ + AM_CONDITIONAL(LIBDWARF,[test "$WITH_LIBDWARF" = yes]) + + #================= ++# Select crypto library ++AC_ARG_WITH(crypto, ++ [AC_HELP_STRING([--with-crypto=CRYPTO_LIB], ++ [The cryptographic library to use (nss|beecrypt|openssl). The default is nss.]) ++ ],[], ++ [with_crypto=nss]) ++ ++# Refuse to proceed if someone specified --with-beecrypt (removed) ++AC_ARG_WITH(beecrypt, ++ [AC_HELP_STRING([--with-beecrypt (OBSOLETE)], [Obsolete argument. Use --with-crypto=beecrypt]) ++ ],[AC_MSG_ERROR([--with-beecrypt no longer supported. Use --with-crypto=beecrypt])], ++ []) ++ + # Check for beecrypt library if requested. +-AC_ARG_WITH(beecrypt, [ --with-beecrypt build with beecrypt support ],,[with_beecrypt=no]) + AC_ARG_WITH(internal_beecrypt, [ --with-internal-beecrypt build with internal beecrypt library ],,[with_internal_beecrypt=no]) + AM_CONDITIONAL([WITH_INTERNAL_BEECRYPT],[test "$with_internal_beecrypt" = yes]) + if test "$with_internal_beecrypt" = yes ; then +- with_beecrypt=yes ++ with_crypto=beecrypt + fi +-AM_CONDITIONAL([WITH_BEECRYPT],[test "$with_beecrypt" = yes]) ++AM_CONDITIONAL([WITH_BEECRYPT],[test "$with_crypto" = beecrypt]) + + WITH_BEECRYPT_INCLUDE= + WITH_BEECRYPT_LIB= +-if test "$with_beecrypt" = yes ; then ++if test "$with_crypto" = beecrypt ; then + AC_DEFINE(WITH_BEECRYPT, 1, [Build with beecrypt instead of nss3 support?]) + if test "$with_internal_beecrypt" = yes ; then + WITH_BEECRYPT_INCLUDE="-I\$(top_srcdir)/beecrypt" +@@ -263,7 +275,7 @@ if test "$with_beecrypt" = yes ; then + AC_CHECK_LIB(beecrypt, mpfprintln, [ + WITH_BEECRYPT_LIB="-lbeecrypt" + ],[ +- AC_MSG_ERROR([missing required library 'beecrypt']) ++ AC_MSG_ERROR([missing required library 'beecrypt']) + ]) + AC_CHECK_HEADER([beecrypt/api.h], [AC_DEFINE(HAVE_BEECRYPT_API_H, 1, [Define to 1 if you have the header file.]) + ]) +@@ -273,13 +285,100 @@ AC_SUBST(WITH_BEECRYPT_LIB) + AC_SUBST(WITH_BEECRYPT_INCLUDE) + + #================= ++# Check for OpenSSL library. ++# We need evp.h from OpenSSL. ++ ++WITH_OPENSSL_INCLUDE= ++WITH_OPENSSL_LIB= ++if test "$with_crypto" = openssl; then ++# If we have pkgconfig make sure CPPFLAGS are setup correctly for the OpenSSL ++# -I include path. ++AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no], [$PATH:/usr/bin:/usr/local/bin]) ++if test "x$PKGCONFIG" != "xno"; then ++ CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags libcrypto)" ++ WITH_OPENSSL_LIB=$($PKGCONFIG --libs libcrypto) ++else ++ WITH_OPENSSL_LIB=-lcrypto ++fi ++ ++AC_CHECK_HEADERS([openssl/evp.h], [], [ ++ AC_MSG_ERROR([missing required OpenSSL header]) ++]) ++AC_CHECK_HEADERS([openssl/rsa.h], [], [ ++ AC_MSG_ERROR([missing required OpenSSL header]) ++]) ++AC_CHECK_HEADERS([openssl/dsa.h], [], [ ++ AC_MSG_ERROR([missing required OpenSSL header]) ++]) ++ ++AC_CHECK_LIB(crypto, EVP_DigestInit_ex, [], [ ++ AC_MSG_ERROR([required OpenSSL library 'libcrypto' missing or too old]) ++]) ++ ++AC_CHECK_LIB(crypto, EVP_MD_CTX_new, [ ++ AC_DEFINE(HAVE_EVP_MD_CTX_NEW, 1, [Define to 1 if OpenSSL has EVP_MD_CTX_new]) ++ AC_SUBST(HAVE_EVP_MD_CTX_NEW, [1]) ++ ], [ ++ AC_CHECK_LIB(crypt, EVP_MD_CTX_create, [], [ ++ AC_MSG_ERROR([required OpenSSL library 'libcrypto' missing or too old]) ++ ]) ++]) ++ ++AC_CHECK_LIB(crypto, EVP_PKEY_CTX_new, [], [ ++ AC_MSG_ERROR([required OpenSSL library 'libcrypto' missing or too old]) ++]) ++ ++AC_CHECK_LIB(crypto, DSA_set0_key, [ ++ AC_DEFINE(HAVE_DSA_SET0_KEY, 1, [Define to 1 if OpenSSL has DSA_set0_key]) ++ AC_SUBST(HAVE_DSA_SET0_KEY, [1]) ++ ], [] ++) ++ ++AC_CHECK_LIB(crypto, DSA_set0_pqg, [ ++ AC_DEFINE(HAVE_DSA_SET0_PQG, 1, [Define to 1 if OpenSSL has DSA_set0_pqg]) ++ AC_SUBST(HAVE_DSA_SET0_PQG, [1]) ++ ], [] ++) ++ ++AC_CHECK_LIB(crypto, DSA_SIG_set0, [ ++ AC_DEFINE(HAVE_DSA_SIG_SET0, 1, [Define to 1 if OpenSSL has DSA_SIG_set0]) ++ AC_SUBST(HAVE_DSA_SIG_SET0, [1]) ++ ], [] ++) ++ ++AC_CHECK_LIB(crypto, RSA_set0_key, [ ++ AC_DEFINE(HAVE_RSA_SET0_KEY, 1, [Define to 1 if OpenSSL has RSA_set0_key]) ++ AC_SUBST(HAVE_RSA_SET0_KEY, [1]) ++ ], [] ++) ++ ++AC_CHECK_LIB(crypto, BN_bn2binpad, [ ++ AC_DEFINE(HAVE_BN2BINPAD, 1, [Define to 1 if OpenSSL has BN_bn2binpad]) ++ AC_SUBST(HAVE_BN2BINPAD, [1]) ++ ], [] ++) ++ ++fi ++ ++AM_CONDITIONAL([WITH_OPENSSL],[test "$with_crypto" = openssl]) ++AC_SUBST(WITH_OPENSSL_INCLUDE) ++AC_SUBST(WITH_OPENSSL_LIB) ++ ++#================= + # Check for NSS library. +-# We need nss.h from NSS which needs nspr.h. Unfortunately both glibc and NSS +-# have a header named nss.h... so make extra check for NSS's sechash.h ++# We need nss.h from NSS which needs nspr.h. Unfortunately both glibc and NSS ++# have a header named nss.h... so make extra check for NSS's sechash.h + # which we use too and hopefully is slightly more unique to NSS. + WITH_NSS_INCLUDE= + WITH_NSS_LIB= +-if test "$with_beecrypt" != yes ; then ++if test "$with_crypto" = nss; then ++# If we have pkgconfig make sure CPPFLAGS are setup correctly for the nss ++# -I include path. Otherwise the below checks will fail because nspr.h ++# cannot be found. ++AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no], [$PATH:/usr/bin:/usr/local/bin]) ++if test "x$PKGCONFIG" != "xno"; then ++ CPPFLAGS="$CPPFLAGS $($PKGCONFIG --cflags nss)" ++fi + AC_CHECK_HEADERS([nspr.h nss.h sechash.h], [], [ + AC_MSG_ERROR([missing required NSPR / NSS header]) + ]) +diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am +index 68a821934..9062f58a5 100644 +--- a/rpmio/Makefile.am ++++ b/rpmio/Makefile.am +@@ -5,6 +5,7 @@ include $(top_srcdir)/rpm.am + AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/ + AM_CPPFLAGS += @WITH_NSS_INCLUDE@ + AM_CPPFLAGS += @WITH_BEECRYPT_INCLUDE@ ++AM_CPPFLAGS += @WITH_OPENSSL_INCLUDE@ + AM_CPPFLAGS += @WITH_POPT_INCLUDE@ + AM_CPPFLAGS += -I$(top_srcdir)/misc + AM_CPPFLAGS += -DRPMCONFIGDIR="\"@RPMCONFIGDIR@\"" +@@ -23,8 +24,12 @@ librpmio_la_SOURCES = \ + if WITH_BEECRYPT + librpmio_la_SOURCES += digest_beecrypt.c + else ++if WITH_OPENSSL ++librpmio_la_SOURCES += digest_openssl.c ++else + librpmio_la_SOURCES += digest_nss.c + endif ++endif + + + librpmio_la_LDFLAGS = -version-info $(rpm_version_info) +@@ -32,6 +37,7 @@ librpmio_la_LIBADD = \ + ../misc/libmisc.la \ + @WITH_NSS_LIB@ \ + @WITH_BEECRYPT_LIB@ \ ++ @WITH_OPENSSL_LIB@ \ + @WITH_BZ2_LIB@ \ + @WITH_ZLIB_LIB@ \ + @WITH_LIBELF_LIB@ \ +diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c +new file mode 100644 +index 000000000..aea460e39 +--- /dev/null ++++ b/rpmio/digest_openssl.c +@@ -0,0 +1,838 @@ ++#include "system.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "rpmio/digest.h" ++ ++ ++/* Compatibility functions for OpenSSL 1.0.2 */ ++ ++#ifndef HAVE_EVP_MD_CTX_NEW ++# define EVP_MD_CTX_new EVP_MD_CTX_create ++# define EVP_MD_CTX_free EVP_MD_CTX_destroy ++#endif ++ ++#ifndef HAVE_RSA_SET0_KEY ++int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); ++int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) ++{ ++ if (!r) return 0; ++ ++ if (n) { ++ r->n = n; ++ } ++ ++ if (e) { ++ r->e = e; ++ } ++ ++ if (d) { ++ r->d = d; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_RSA_SET0_KEY */ ++ ++#ifndef HAVE_DSA_SET0_KEY ++int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); ++ ++int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) ++{ ++ if (!d) return 0; ++ ++ if (pub_key) { ++ d->pub_key = pub_key; ++ } ++ ++ if (priv_key) { ++ d->priv_key = priv_key; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DSA_SET0_KEY */ ++ ++#ifndef HAVE_DSA_SET0_PQG ++int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); ++ ++int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) ++{ ++ if (!d) return 0; ++ ++ if (p) { ++ d->p = p; ++ } ++ ++ if (q) { ++ d->q = q; ++ } ++ ++ if (g) { ++ d->g = g; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DSA_SET0_PQG */ ++ ++#ifndef HAVE_DSA_SIG_SET0 ++int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); ++ ++int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) ++{ ++ if (!sig) return 0; ++ ++ if (r) { ++ sig->r = r; ++ } ++ ++ if (s) { ++ sig->s = s; ++ } ++ ++ return 1; ++} ++#endif /* HAVE_DSA_SIG_SET0 */ ++ ++#ifndef HAVE_BN2BINPAD ++static int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) ++{ ++ int i; ++ ++ i = BN_num_bytes(a); ++ if (tolen < i) ++ return -1; ++ ++ /* Add leading zeroes if necessary */ ++ if (tolen > i) { ++ memset(to, 0, tolen - i); ++ to += tolen - i; ++ } ++ ++ BN_bn2bin(a, to); ++ ++ return tolen; ++} ++#endif /* HAVE_BN2BINPAD */ ++ ++struct DIGEST_CTX_s { ++ rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */ ++ int algo; /*!< Used hash algorithm */ ++ ++ EVP_MD_CTX *md_ctx; /* Digest context (opaque) */ ++ ++}; ++ ++/**************************** init ************************************/ ++ ++int rpmInitCrypto(void) { ++ return 0; ++} ++ ++int rpmFreeCrypto(void) { ++ return 0; ++} ++ ++/**************************** digest ************************************/ ++ ++DIGEST_CTX rpmDigestDup(DIGEST_CTX octx) ++{ ++ if (!octx) return NULL; ++ ++ DIGEST_CTX nctx = NULL; ++ nctx = xcalloc(1, sizeof(*nctx)); ++ ++ nctx->flags = octx->flags; ++ nctx->algo = octx->algo; ++ nctx->md_ctx = EVP_MD_CTX_new(); ++ if (!nctx->md_ctx) { ++ free(nctx); ++ return NULL; ++ } ++ ++ if (!EVP_MD_CTX_copy(nctx->md_ctx, octx->md_ctx)) { ++ free(nctx); ++ return NULL; ++ } ++ ++ return nctx; ++} ++ ++static const EVP_MD *getEVPMD(int hashalgo) ++{ ++ switch (hashalgo) { ++ ++ case PGPHASHALGO_MD5: ++ return EVP_md5(); ++ ++ case PGPHASHALGO_SHA1: ++ return EVP_sha1(); ++ ++ case PGPHASHALGO_RIPEMD160: ++ return EVP_ripemd160(); ++ ++ case PGPHASHALGO_MD2: ++ return EVP_md2(); ++ ++ case PGPHASHALGO_SHA256: ++ return EVP_sha256(); ++ ++ case PGPHASHALGO_SHA384: ++ return EVP_sha384(); ++ ++ case PGPHASHALGO_SHA512: ++ return EVP_sha512(); ++ ++ case PGPHASHALGO_SHA224: ++ return EVP_sha224(); ++ ++ default: ++ return EVP_md_null(); ++ } ++} ++ ++size_t rpmDigestLength(int hashalgo) ++{ ++ return EVP_MD_size(getEVPMD(hashalgo)); ++} ++ ++DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags) ++{ ++ DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx)); ++ ++ ctx->md_ctx = EVP_MD_CTX_new(); ++ if (!ctx->md_ctx) { ++ free(ctx); ++ return NULL; ++ } ++ ++ const EVP_MD *md = getEVPMD(hashalgo); ++ if (md == EVP_md_null()) { ++ free(ctx->md_ctx); ++ free(ctx); ++ return NULL; ++ } ++ ++ ctx->algo = hashalgo; ++ ctx->flags = flags; ++ if (!EVP_DigestInit_ex(ctx->md_ctx, md, NULL)) { ++ free(ctx->md_ctx); ++ free(ctx); ++ return NULL; ++ } ++ ++ return ctx; ++} ++ ++int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len) ++{ ++ if (ctx == NULL) return -1; ++ ++ EVP_DigestUpdate(ctx->md_ctx, data, len); ++ ++ return 0; ++} ++ ++int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii) ++{ ++ int ret; ++ unsigned char *digest = NULL; ++ unsigned int digestlen; ++ ++ if (ctx == NULL) return -1; ++ ++ digestlen = EVP_MD_CTX_size(ctx->md_ctx); ++ digest = xcalloc(digestlen, sizeof(*digest)); ++ ++ ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, &digestlen); ++ if (ret != 1) goto done; ++ ++ if (!asAscii) { ++ /* Raw data requested */ ++ if (lenp) *lenp = digestlen; ++ if (datap) { ++ *datap = digest; ++ digest = NULL; ++ } ++ } ++ ++ else { ++ /* ASCII requested */ ++ if (lenp) *lenp = (2*digestlen) + 1; ++ if (datap) { ++ const uint8_t * s = (const uint8_t *) digest; ++ *datap = pgpHexStr(s, digestlen); ++ } ++ } ++ ++ ret = 1; ++ ++done: ++ if (digest) { ++ /* Zero the digest, just in case it's sensitive */ ++ memset(digest, 0, digestlen); ++ free(digest); ++ } ++ ++ EVP_MD_CTX_free(ctx->md_ctx); ++ free(ctx); ++ ++ if (ret != 1) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++/****************************** RSA **************************************/ ++ ++/* Key */ ++ ++struct pgpDigKeyRSA_s { ++ size_t nbytes; /* Size of modulus */ ++ ++ BIGNUM *n; /* Common Modulus */ ++ BIGNUM *e; /* Public Exponent */ ++ ++ EVP_PKEY *evp_pkey; /* Fully constructed key */ ++}; ++ ++static int constructRSASigningKey(struct pgpDigKeyRSA_s *key) ++{ ++ if (key->evp_pkey) { ++ /* We've already constructed it, so just reuse it */ ++ return 1; ++ } ++ ++ /* Create the RSA key */ ++ RSA *rsa = RSA_new(); ++ if (!rsa) return 0; ++ ++ if (!RSA_set0_key(rsa, key->n, key->e, NULL)) { ++ RSA_free(rsa); ++ return 0; ++ } ++ ++ /* Create an EVP_PKEY container to abstract the key-type. */ ++ key->evp_pkey = EVP_PKEY_new(); ++ if (!key->evp_pkey) { ++ RSA_free(rsa); ++ return 0; ++ } ++ ++ /* Assign the RSA key to the EVP_PKEY structure. ++ This will take over memory management of the RSA key */ ++ if (!EVP_PKEY_assign_RSA(key->evp_pkey, rsa)) { ++ EVP_PKEY_free(key->evp_pkey); ++ key->evp_pkey = NULL; ++ RSA_free(rsa); ++ } ++ ++ return 1; ++} ++ ++static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p) ++{ ++ size_t mlen = pgpMpiLen(p) - 2; ++ struct pgpDigKeyRSA_s *key = pgpkey->data; ++ ++ if(!key) { ++ key = pgpkey->data = xcalloc(1, sizeof(*key)); ++ } ++ ++ switch(num) { ++ case 0: ++ /* Modulus */ ++ if (key->n) { ++ /* This should only ever happen once per key */ ++ return 1; ++ } ++ ++ key->nbytes = mlen; ++ /* Create a BIGNUM from the pointer. ++ Note: this assumes big-endian data as required by PGP */ ++ key->n = BN_bin2bn(p+2, mlen, NULL); ++ if (!key->n) return 1; ++ break; ++ ++ case 1: ++ /* Exponent */ ++ if (key->e) { ++ /* This should only ever happen once per key */ ++ return 1; ++ } ++ ++ /* Create a BIGNUM from the pointer. ++ Note: this assumes big-endian data as required by PGP */ ++ key->e = BN_bin2bn(p+2, mlen, NULL); ++ if (!key->e) return 1; ++ break; ++ } ++ ++ return 0; ++} ++ ++static void pgpFreeKeyRSA(pgpDigAlg pgpkey) ++{ ++ struct pgpDigKeyRSA_s *key = pgpkey->data; ++ if (key) { ++ if (key->evp_pkey) { ++ EVP_PKEY_free(key->evp_pkey); ++ } else { ++ /* If key->evp_pkey was constructed, ++ * the memory management of these BNs ++ * are freed with it. */ ++ BN_clear_free(key->n); ++ BN_clear_free(key->e); ++ } ++ ++ free(key); ++ } ++} ++ ++/* Signature */ ++ ++struct pgpDigSigRSA_s { ++ BIGNUM *bn; ++ size_t len; ++}; ++ ++static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, const uint8_t *p) ++{ ++ BIGNUM *bn = NULL; ++ ++ int mlen = pgpMpiLen(p) - 2; ++ int rc = 1; ++ ++ struct pgpDigSigRSA_s *sig = pgpsig->data; ++ if (!sig) { ++ sig = xcalloc(1, sizeof(*sig)); ++ } ++ ++ switch (num) { ++ case 0: ++ if (sig->bn) { ++ /* This should only ever happen once per signature */ ++ return 1; ++ } ++ ++ bn = sig->bn = BN_new(); ++ if (!bn) return 1; ++ ++ /* Create a BIGNUM from the signature pointer. ++ Note: this assumes big-endian data as required ++ by the PGP multiprecision integer format ++ (RFC4880, Section 3.2) ++ This will be useful later, as we can ++ retrieve this value with appropriate ++ padding. */ ++ bn = BN_bin2bn(p+2, mlen, bn); ++ if (!bn) return 1; ++ ++ sig->bn = bn; ++ sig->len = mlen; ++ ++ pgpsig->data = sig; ++ rc = 0; ++ break; ++ } ++ return rc; ++} ++ ++static void pgpFreeSigRSA(pgpDigAlg pgpsig) ++{ ++ struct pgpDigSigRSA_s *sig = pgpsig->data; ++ if (sig) { ++ BN_clear_free(sig->bn); ++ free(pgpsig->data); ++ } ++} ++ ++static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, ++ uint8_t *hash, size_t hashlen, int hash_algo) ++{ ++ int rc, ret; ++ EVP_PKEY_CTX *pkey_ctx = NULL; ++ struct pgpDigSigRSA_s *sig = pgpsig->data; ++ ++ void *padded_sig = NULL; ++ ++ struct pgpDigKeyRSA_s *key = pgpkey->data; ++ ++ if(!constructRSASigningKey(key)) { ++ rc = 1; ++ goto done; ++ } ++ ++ pkey_ctx = EVP_PKEY_CTX_new(key->evp_pkey, NULL); ++ if (!pkey_ctx) { ++ rc = 1; ++ goto done; ++ } ++ ++ ret = EVP_PKEY_verify_init(pkey_ctx); ++ if (ret < 0) { ++ rc = 1; ++ goto done; ++ } ++ ++ ret = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING); ++ if (ret < 0) { ++ rc = 1; ++ goto done; ++ } ++ ++ ret = EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo)); ++ if (ret < 0) { ++ rc = 1; ++ goto done; ++ } ++ ++ int pkey_len = EVP_PKEY_size(key->evp_pkey); ++ padded_sig = xcalloc(1, pkey_len); ++ if (!BN_bn2binpad(sig->bn, padded_sig, pkey_len)) { ++ rc = 1; ++ goto done; ++ } ++ ++ ret = EVP_PKEY_verify(pkey_ctx, padded_sig, pkey_len, hash, hashlen); ++ if (ret == 1) ++ { ++ /* Success */ ++ rc = 0; ++ } ++ else ++ { ++ /* Failure */ ++ rc = 1; ++ } ++ ++done: ++ EVP_PKEY_CTX_free(pkey_ctx); ++ free(padded_sig); ++ return rc; ++} ++ ++/****************************** DSA ***************************************/ ++/* Key */ ++ ++struct pgpDigKeyDSA_s { ++ BIGNUM *p; /* Prime */ ++ BIGNUM *q; /* Subprime */ ++ BIGNUM *g; /* Base */ ++ BIGNUM *y; /* Public Key */ ++ ++ DSA *dsa_key; /* Fully constructed key */ ++}; ++ ++static int constructDSASigningKey(struct pgpDigKeyDSA_s *key) ++{ ++ int rc; ++ ++ if (key->dsa_key) { ++ /* We've already constructed it, so just reuse it */ ++ return 1; ++ } ++ ++ /* Create the DSA key */ ++ DSA *dsa = DSA_new(); ++ if (!dsa) return 0; ++ ++ if (!DSA_set0_pqg(dsa, key->p, key->q, key->g)) { ++ rc = 0; ++ goto done; ++ } ++ ++ if (!DSA_set0_key(dsa, key->y, NULL)) { ++ rc = 0; ++ } ++ ++ key->dsa_key = dsa; ++ ++ rc = 1; ++done: ++ if (rc == 0) { ++ DSA_free(dsa); ++ } ++ return rc; ++} ++ ++ ++static int pgpSetKeyMpiDSA(pgpDigAlg pgpkey, int num, const uint8_t *p) ++{ ++ BIGNUM *bn; ++ size_t mlen = pgpMpiLen(p) - 2; ++ struct pgpDigKeyDSA_s *key = pgpkey->data; ++ ++ if(!key) { ++ key = pgpkey->data = xcalloc(1, sizeof(*key)); ++ } ++ ++ /* Create a BIGNUM from the key pointer. ++ Note: this assumes big-endian data as required ++ by the PGP multiprecision integer format ++ (RFC4880, Section 3.2) */ ++ bn = BN_bin2bn(p+2, mlen, NULL); ++ if (!bn) return 1; ++ ++ switch(num) { ++ case 0: ++ /* Prime */ ++ if (key->p) { ++ /* This should only ever happen once per key */ ++ return 1; ++ } ++ key->p = bn; ++ break; ++ ++ case 1: ++ /* Subprime */ ++ if (key->q) { ++ /* This should only ever happen once per key */ ++ return 1; ++ } ++ key->q = bn; ++ break; ++ case 2: ++ /* Base */ ++ if (key->g) { ++ /* This should only ever happen once per key */ ++ return 1; ++ } ++ key->g = bn; ++ break; ++ case 3: ++ /* Public */ ++ if (key->y) { ++ /* This should only ever happen once per key */ ++ return 1; ++ } ++ key->y = bn; ++ break; ++ } ++ ++ return 0; ++} ++ ++static void pgpFreeKeyDSA(pgpDigAlg pgpkey) ++{ ++ struct pgpDigKeyDSA_s *key = pgpkey->data; ++ if (key) { ++ if (key->dsa_key) { ++ DSA_free(key->dsa_key); ++ } else { ++ /* If sig->dsa_key was constructed, ++ * the memory management of these BNs ++ * are freed with it. */ ++ BN_clear_free(key->p); ++ BN_clear_free(key->q); ++ BN_clear_free(key->g); ++ BN_clear_free(key->y); ++ } ++ free(key); ++ } ++} ++ ++/* Signature */ ++ ++struct pgpDigSigDSA_s { ++ BIGNUM *r; ++ BIGNUM *s; ++ ++ DSA_SIG *dsa_sig; ++}; ++ ++static int constructDSASignature(struct pgpDigSigDSA_s *sig) ++{ ++ int rc; ++ ++ if (sig->dsa_sig) { ++ /* We've already constructed it, so just reuse it */ ++ return 1; ++ } ++ ++ /* Create the DSA signature */ ++ DSA_SIG *dsa_sig = DSA_SIG_new(); ++ if (!dsa_sig) return 0; ++ ++ if (!DSA_SIG_set0(dsa_sig, sig->r, sig->s)) { ++ rc = 0; ++ goto done; ++ } ++ ++ sig->dsa_sig = dsa_sig; ++ ++ rc = 1; ++done: ++ if (rc == 0) { ++ DSA_SIG_free(sig->dsa_sig); ++ } ++ return rc; ++} ++ ++static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p) ++{ ++ BIGNUM *bn = NULL; ++ ++ int mlen = pgpMpiLen(p) - 2; ++ int rc = 1; ++ ++ struct pgpDigSigDSA_s *sig = pgpsig->data; ++ if (!sig) { ++ sig = xcalloc(1, sizeof(*sig)); ++ } ++ ++ /* Create a BIGNUM from the signature pointer. ++ Note: this assumes big-endian data as required ++ by the PGP multiprecision integer format ++ (RFC4880, Section 3.2) */ ++ bn = BN_bin2bn(p+2, mlen, NULL); ++ if (!bn) return 1; ++ ++ switch (num) { ++ case 0: ++ if (sig->r) { ++ /* This should only ever happen once per signature */ ++ BN_free(bn); ++ return 1; ++ } ++ sig->r = bn; ++ rc = 0; ++ break; ++ case 1: ++ if (sig->s) { ++ /* This should only ever happen once per signature */ ++ BN_free(bn); ++ return 1; ++ } ++ sig->s = bn; ++ rc = 0; ++ break; ++ } ++ ++ pgpsig->data = sig; ++ ++ return rc; ++} ++ ++static void pgpFreeSigDSA(pgpDigAlg pgpsig) ++{ ++ struct pgpDigSigDSA_s *sig = pgpsig->data; ++ if (sig) { ++ if (sig->dsa_sig) { ++ DSA_SIG_free(sig->dsa_sig); ++ } else { ++ /* If sig->dsa_sig was constructed, ++ * the memory management of these BNs ++ * are freed with it. */ ++ BN_clear_free(sig->r); ++ BN_clear_free(sig->s); ++ } ++ free(pgpsig->data); ++ } ++} ++ ++static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, ++ uint8_t *hash, size_t hashlen, int hash_algo) ++{ ++ int rc, ret; ++ struct pgpDigSigDSA_s *sig = pgpsig->data; ++ ++ struct pgpDigKeyDSA_s *key = pgpkey->data; ++ ++ if(!constructDSASigningKey(key)) { ++ rc = 1; ++ goto done; ++ } ++ ++ if (!constructDSASignature(sig)) { ++ rc = 1; ++ goto done; ++ } ++ ++ ret = DSA_do_verify(hash, hashlen, sig->dsa_sig, key->dsa_key); ++ if (ret == 1) ++ { ++ /* Success */ ++ rc = 0; ++ } ++ else ++ { ++ /* Failure */ ++ rc = 1; ++ } ++ ++done: ++ return rc; ++} ++ ++/****************************** NULL **************************************/ ++ ++static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p) ++{ ++ return 1; ++} ++ ++static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig, ++ uint8_t *hash, size_t hashlen, int hash_algo) ++{ ++ return 1; ++} ++ ++/****************************** PGP **************************************/ ++pgpDigAlg pgpPubkeyNew(int algo) ++{ ++ pgpDigAlg ka = xcalloc(1, sizeof(*ka));; ++ ++ switch (algo) { ++ case PGPPUBKEYALGO_RSA: ++ ka->setmpi = pgpSetKeyMpiRSA; ++ ka->free = pgpFreeKeyRSA; ++ ka->mpis = 2; ++ break; ++ case PGPPUBKEYALGO_DSA: ++ ka->setmpi = pgpSetKeyMpiDSA; ++ ka->free = pgpFreeKeyDSA; ++ ka->mpis = 4; ++ break; ++ default: ++ ka->setmpi = pgpSetMpiNULL; ++ ka->mpis = -1; ++ break; ++ } ++ ++ ka->verify = pgpVerifyNULL; /* keys can't be verified */ ++ ++ return ka; ++} ++ ++pgpDigAlg pgpSignatureNew(int algo) ++{ ++ pgpDigAlg sa = xcalloc(1, sizeof(*sa)); ++ ++ switch (algo) { ++ case PGPPUBKEYALGO_RSA: ++ sa->setmpi = pgpSetSigMpiRSA; ++ sa->free = pgpFreeSigRSA; ++ sa->verify = pgpVerifySigRSA; ++ sa->mpis = 1; ++ break; ++ case PGPPUBKEYALGO_DSA: ++ sa->setmpi = pgpSetSigMpiDSA; ++ sa->free = pgpFreeSigDSA; ++ sa->verify = pgpVerifySigDSA; ++ sa->mpis = 2; ++ break; ++ default: ++ sa->setmpi = pgpSetMpiNULL; ++ sa->verify = pgpVerifyNULL; ++ sa->mpis = -1; ++ break; ++ } ++ return sa; ++} +-- +2.13.2 + diff --git a/0044-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch b/0044-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch new file mode 100644 index 0000000..51bcc14 --- /dev/null +++ b/0044-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch @@ -0,0 +1,152 @@ +From 287cda21a5594ad41ffbd29eb01022f314637bdf Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Tue, 28 Feb 2017 10:57:56 +0100 +Subject: [PATCH 44/49] Use RPMTAG_*NAME instead of RPMTAG_*FLAGS in + parsePreamble.c and parseRCPOT() + +Using the FLGS tags is awkward and inconsistent with other part of the code +routinly use the NAME tags to denominate the type of dependencies. +This is also going to make using parseRCPOT() easier for the rpmfc code +that is also based on NAME tags. + +(cherry picked from commit 9d5bbd9774d00f50749bb045217eaf91c87b6de0) +--- + build/parsePreamble.c | 36 ++++++++++++++++++------------------ + build/parseReqs.c | 37 +++++++++++-------------------------- + build/rpmfc.c | 2 +- + 3 files changed, 30 insertions(+), 45 deletions(-) + +diff --git a/build/parsePreamble.c b/build/parsePreamble.c +index 3bb833cff..bc639e86c 100644 +--- a/build/parsePreamble.c ++++ b/build/parsePreamble.c +@@ -850,8 +850,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, + if (parseNoSource(spec, field, tag)) + goto exit; + break; +- case RPMTAG_ORDERFLAGS: +- case RPMTAG_REQUIREFLAGS: ++ case RPMTAG_ORDERNAME: ++ case RPMTAG_REQUIRENAME: + if (parseBits(lang, installScriptBits, &tagflags)) { + rpmlog(RPMLOG_ERR, _("line %d: Bad %s: qualifiers: %s\n"), + spec->lineNum, rpmTagGetName(tag), spec->line); +@@ -859,13 +859,13 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, + } + /* fallthrough */ + case RPMTAG_PREREQ: +- case RPMTAG_RECOMMENDFLAGS: +- case RPMTAG_SUGGESTFLAGS: +- case RPMTAG_SUPPLEMENTFLAGS: +- case RPMTAG_ENHANCEFLAGS: +- case RPMTAG_CONFLICTFLAGS: +- case RPMTAG_OBSOLETEFLAGS: +- case RPMTAG_PROVIDEFLAGS: ++ case RPMTAG_RECOMMENDNAME: ++ case RPMTAG_SUGGESTNAME: ++ case RPMTAG_SUPPLEMENTNAME: ++ case RPMTAG_ENHANCENAME: ++ case RPMTAG_CONFLICTNAME: ++ case RPMTAG_OBSOLETENAME: ++ case RPMTAG_PROVIDENAME: + if (parseRCPOT(spec, pkg, field, tag, 0, tagflags)) + goto exit; + break; +@@ -970,15 +970,15 @@ static struct PreambleRec_s const preambleList[] = { + {RPMTAG_EXCLUDEOS, 0, 0, LEN_AND_STR("excludeos")}, + {RPMTAG_EXCLUSIVEOS, 0, 0, LEN_AND_STR("exclusiveos")}, + {RPMTAG_ICON, 0, 0, LEN_AND_STR("icon")}, +- {RPMTAG_PROVIDEFLAGS, 0, 0, LEN_AND_STR("provides")}, +- {RPMTAG_REQUIREFLAGS, 2, 0, LEN_AND_STR("requires")}, +- {RPMTAG_RECOMMENDFLAGS, 0, 0, LEN_AND_STR("recommends")}, +- {RPMTAG_SUGGESTFLAGS, 0, 0, LEN_AND_STR("suggests")}, +- {RPMTAG_SUPPLEMENTFLAGS, 0, 0, LEN_AND_STR("supplements")}, +- {RPMTAG_ENHANCEFLAGS, 0, 0, LEN_AND_STR("enhances")}, ++ {RPMTAG_PROVIDENAME, 0, 0, LEN_AND_STR("provides")}, ++ {RPMTAG_REQUIRENAME, 2, 0, LEN_AND_STR("requires")}, ++ {RPMTAG_RECOMMENDNAME, 0, 0, LEN_AND_STR("recommends")}, ++ {RPMTAG_SUGGESTNAME, 0, 0, LEN_AND_STR("suggests")}, ++ {RPMTAG_SUPPLEMENTNAME, 0, 0, LEN_AND_STR("supplements")}, ++ {RPMTAG_ENHANCENAME, 0, 0, LEN_AND_STR("enhances")}, + {RPMTAG_PREREQ, 2, 1, LEN_AND_STR("prereq")}, +- {RPMTAG_CONFLICTFLAGS, 0, 0, LEN_AND_STR("conflicts")}, +- {RPMTAG_OBSOLETEFLAGS, 0, 0, LEN_AND_STR("obsoletes")}, ++ {RPMTAG_CONFLICTNAME, 0, 0, LEN_AND_STR("conflicts")}, ++ {RPMTAG_OBSOLETENAME, 0, 0, LEN_AND_STR("obsoletes")}, + {RPMTAG_PREFIXES, 0, 0, LEN_AND_STR("prefixes")}, + {RPMTAG_PREFIXES, 0, 0, LEN_AND_STR("prefix")}, + {RPMTAG_BUILDROOT, 0, 0, LEN_AND_STR("buildroot")}, +@@ -993,7 +993,7 @@ static struct PreambleRec_s const preambleList[] = { + {RPMTAG_DOCDIR, 0, 0, LEN_AND_STR("docdir")}, + {RPMTAG_DISTTAG, 0, 0, LEN_AND_STR("disttag")}, + {RPMTAG_BUGURL, 0, 0, LEN_AND_STR("bugurl")}, +- {RPMTAG_ORDERFLAGS, 2, 0, LEN_AND_STR("orderwithrequires")}, ++ {RPMTAG_ORDERNAME, 2, 0, LEN_AND_STR("orderwithrequires")}, + {RPMTAG_REMOVEPATHPOSTFIXES,0, 0, LEN_AND_STR("removepathpostfixes")}, + {0, 0, 0, 0} + }; +diff --git a/build/parseReqs.c b/build/parseReqs.c +index a443505e4..bd728ed2d 100644 +--- a/build/parseReqs.c ++++ b/build/parseReqs.c +@@ -132,33 +132,18 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + + switch (tagN) { + default: +- case RPMTAG_REQUIREFLAGS: +- nametag = RPMTAG_REQUIRENAME; ++ case RPMTAG_REQUIRENAME: + tagflags |= RPMSENSE_ANY; +- break; +- case RPMTAG_RECOMMENDFLAGS: +- nametag = RPMTAG_RECOMMENDNAME; +- break; +- case RPMTAG_SUGGESTFLAGS: +- nametag = RPMTAG_SUGGESTNAME; +- break; +- case RPMTAG_SUPPLEMENTFLAGS: +- nametag = RPMTAG_SUPPLEMENTNAME; +- break; +- case RPMTAG_ENHANCEFLAGS: +- nametag = RPMTAG_ENHANCENAME; +- break; +- case RPMTAG_PROVIDEFLAGS: +- nametag = RPMTAG_PROVIDENAME; +- break; +- case RPMTAG_OBSOLETEFLAGS: +- nametag = RPMTAG_OBSOLETENAME; +- break; +- case RPMTAG_CONFLICTFLAGS: +- nametag = RPMTAG_CONFLICTNAME; +- break; +- case RPMTAG_ORDERFLAGS: +- nametag = RPMTAG_ORDERNAME; ++ /* fall through */ ++ case RPMTAG_RECOMMENDNAME: ++ case RPMTAG_SUGGESTNAME: ++ case RPMTAG_SUPPLEMENTNAME: ++ case RPMTAG_ENHANCENAME: ++ case RPMTAG_PROVIDENAME: ++ case RPMTAG_OBSOLETENAME: ++ case RPMTAG_CONFLICTNAME: ++ case RPMTAG_ORDERNAME: ++ nametag = tagN; + break; + case RPMTAG_PREREQ: + /* XXX map legacy PreReq into Requires(pre,preun) */ +diff --git a/build/rpmfc.c b/build/rpmfc.c +index 73915015a..ce192fa9c 100644 +--- a/build/rpmfc.c ++++ b/build/rpmfc.c +@@ -1297,7 +1297,7 @@ static rpmRC rpmfcApplyExternal(rpmfc fc) + } + + /* Parse dependencies into header */ +- rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), tag, 0, tagflags); ++ rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags); + freeStringBuf(sb_stdout); + + if (rc) { +-- +2.13.2 + diff --git a/0045-Fix-check-for-weak-deps-in-external-dependency-gener.patch b/0045-Fix-check-for-weak-deps-in-external-dependency-gener.patch new file mode 100644 index 0000000..70c443c --- /dev/null +++ b/0045-Fix-check-for-weak-deps-in-external-dependency-gener.patch @@ -0,0 +1,37 @@ +From 4fb394a677c17a33c7e3f3455a1a6c109200b87e Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Tue, 28 Feb 2017 17:42:21 +0100 +Subject: [PATCH 45/49] Fix check for weak deps in external dependency + generator + +(cherry picked from commit 43d230884365d90d42184a0000f44bb33e5f1ab8) +--- + build/rpmfc.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/build/rpmfc.c b/build/rpmfc.c +index ce192fa9c..921814ad1 100644 +--- a/build/rpmfc.c ++++ b/build/rpmfc.c +@@ -1267,12 +1267,12 @@ static rpmRC rpmfcApplyExternal(rpmfc fc) + tagflags = RPMSENSE_FIND_PROVIDES; + break; + case RPMTAG_REQUIREFLAGS: +- case RPMTAG_RECOMMENDNAME: +- case RPMTAG_SUGGESTNAME: +- case RPMTAG_SUPPLEMENTNAME: +- case RPMTAG_ENHANCENAME: +- case RPMTAG_CONFLICTNAME: +- case RPMTAG_OBSOLETENAME: ++ case RPMTAG_RECOMMENDFLAGS: ++ case RPMTAG_SUGGESTFLAGS: ++ case RPMTAG_SUPPLEMENTFLAGS: ++ case RPMTAG_ENHANCEFLAGS: ++ case RPMTAG_CONFLICTFLAGS: ++ case RPMTAG_OBSOLETEFLAGS: + if (fc->skipReq) + continue; + tagflags = RPMSENSE_FIND_REQUIRES; +-- +2.13.2 + diff --git a/0046-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch b/0046-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch new file mode 100644 index 0000000..8033857 --- /dev/null +++ b/0046-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch @@ -0,0 +1,59 @@ +From 9a316cbeb61549b3004692c9dd8437b9fa805e74 Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Thu, 9 Mar 2017 12:12:32 +0100 +Subject: [PATCH 46/49] Fix check whether to allow rich deps in a given tag + +Broken with 9d5bbd9774d00f50749bb045217eaf91c87b6de0 + +(cherry picked from commit e4349ef7292578a7286bfca2e68a150422e65c3c) +--- + build/parseReqs.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/build/parseReqs.c b/build/parseReqs.c +index bd728ed2d..6c2aead4e 100644 +--- a/build/parseReqs.c ++++ b/build/parseReqs.c +@@ -129,6 +129,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + rpmTagVal nametag = RPMTAG_NOT_FOUND; + rpmsenseFlags Flags; + rpmRC rc = RPMRC_FAIL; /* assume failure */ ++ int allow_richdeps = 0; + + switch (tagN) { + default: +@@ -139,9 +140,11 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + case RPMTAG_SUGGESTNAME: + case RPMTAG_SUPPLEMENTNAME: + case RPMTAG_ENHANCENAME: ++ case RPMTAG_CONFLICTNAME: ++ allow_richdeps = 1; ++ /* fall through */ + case RPMTAG_PROVIDENAME: + case RPMTAG_OBSOLETENAME: +- case RPMTAG_CONFLICTNAME: + case RPMTAG_ORDERNAME: + nametag = tagN; + break; +@@ -149,6 +152,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + /* XXX map legacy PreReq into Requires(pre,preun) */ + nametag = RPMTAG_REQUIRENAME; + tagflags |= (RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_PREUN); ++ allow_richdeps = 1; + break; + case RPMTAG_TRIGGERPREIN: + nametag = RPMTAG_TRIGGERNAME; +@@ -209,9 +213,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + + if (r[0] == '(') { + struct parseRCPOTRichData data; +- if (nametag != RPMTAG_REQUIRENAME && nametag != RPMTAG_CONFLICTNAME && +- nametag != RPMTAG_RECOMMENDNAME && nametag != RPMTAG_SUPPLEMENTNAME && +- nametag != RPMTAG_SUGGESTNAME && nametag != RPMTAG_ENHANCENAME) { ++ if (!allow_richdeps) { + rasprintf(&emsg, _("No rich dependencies allowed for this type")); + goto exit; + } +-- +2.13.2 + diff --git a/0047-Re-enable-rich-dependecies-for-build-requires-and-co.patch b/0047-Re-enable-rich-dependecies-for-build-requires-and-co.patch new file mode 100644 index 0000000..b087748 --- /dev/null +++ b/0047-Re-enable-rich-dependecies-for-build-requires-and-co.patch @@ -0,0 +1,30 @@ +From 27c263a877dd4bfac12ae716038dfbb0a305625b Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Thu, 9 Mar 2017 14:02:10 +0100 +Subject: [PATCH 47/49] Re-enable rich dependecies for build requires and + conflicts + +(cherry picked from commit cb3dc0b43bd9a119196a527504d03d57d0785092) +--- + build/parseReqs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/build/parseReqs.c b/build/parseReqs.c +index 6c2aead4e..4d500c1df 100644 +--- a/build/parseReqs.c ++++ b/build/parseReqs.c +@@ -174,9 +174,11 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + case RPMTAG_BUILDREQUIRES: + nametag = RPMTAG_REQUIRENAME; + tagflags |= RPMSENSE_ANY; ++ allow_richdeps = 1; + break; + case RPMTAG_BUILDCONFLICTS: + nametag = RPMTAG_CONFLICTNAME; ++ allow_richdeps = 1; + break; + case RPMTAG_FILETRIGGERIN: + nametag = RPMTAG_FILETRIGGERNAME; +-- +2.13.2 + diff --git a/0048-add-support-for-rich-dependencies-from-dependency-ge.patch b/0048-add-support-for-rich-dependencies-from-dependency-ge.patch new file mode 100644 index 0000000..02db161 --- /dev/null +++ b/0048-add-support-for-rich-dependencies-from-dependency-ge.patch @@ -0,0 +1,279 @@ +From c1ed362facbab3d08b5576950d4c6a68cfae9e75 Mon Sep 17 00:00:00 2001 +From: Igor Gnatenko +Date: Sat, 25 Feb 2017 12:28:16 +0100 +Subject: [PATCH 48/49] add support for rich dependencies from dependency + generators + +Mostly achieved by replacing custom parser with the parseRCPOT(). + +Closes: https://github.com/rpm-software-management/rpm/issues/167 +Signed-off-by: Igor Gnatenko +(cherry picked from commit 8f509d669b9ae79c86dd510c5a4bc5109f60d733) + +Conflicts: + build/rpmfc.c +--- + build/parsePreamble.c | 4 +-- + build/parseReqs.c | 9 +++-- + build/parseScript.c | 2 +- + build/reqprov.c | 8 +++++ + build/rpmbuild_internal.h | 12 ++++++- + build/rpmfc.c | 90 ++++++++++++++--------------------------------- + 6 files changed, 54 insertions(+), 71 deletions(-) + +diff --git a/build/parsePreamble.c b/build/parsePreamble.c +index bc639e86c..6b3705598 100644 +--- a/build/parsePreamble.c ++++ b/build/parsePreamble.c +@@ -866,13 +866,13 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, + case RPMTAG_CONFLICTNAME: + case RPMTAG_OBSOLETENAME: + case RPMTAG_PROVIDENAME: +- if (parseRCPOT(spec, pkg, field, tag, 0, tagflags)) ++ if (parseRCPOT(spec, pkg, field, tag, 0, tagflags, addReqProvPkg, NULL)) + goto exit; + break; + case RPMTAG_BUILDPREREQ: + case RPMTAG_BUILDREQUIRES: + case RPMTAG_BUILDCONFLICTS: +- if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags)) ++ if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags, addReqProvPkg, NULL)) + goto exit; + break; + case RPMTAG_EXCLUDEARCH: +diff --git a/build/parseReqs.c b/build/parseReqs.c +index 4d500c1df..554ff49a5 100644 +--- a/build/parseReqs.c ++++ b/build/parseReqs.c +@@ -121,7 +121,7 @@ static rpmRC parseRCPOTRichCB(void *cbdata, rpmrichParseType type, + } + + rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, +- int index, rpmsenseFlags tagflags) ++ int index, rpmsenseFlags tagflags, addReqProvFunction cb, void *cbdata) + { + const char *r, *re, *v, *ve; + char *emsg = NULL; +@@ -131,6 +131,9 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + rpmRC rc = RPMRC_FAIL; /* assume failure */ + int allow_richdeps = 0; + ++ if (!cbdata) ++ cbdata = pkg; ++ + switch (tagN) { + default: + case RPMTAG_REQUIRENAME: +@@ -225,7 +228,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + freeStringBuf(data.sb); + goto exit; + } +- if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags, index)) { ++ if (cb && cb(cbdata, nametag, getStringBuf(data.sb), NULL, Flags, index) != RPMRC_OK) { + rasprintf(&emsg, _("invalid dependency")); + freeStringBuf(data.sb); + goto exit; +@@ -300,7 +303,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, + goto exit; + } + +- if (addReqProv(pkg, nametag, N, EVR, Flags, index)) { ++ if (cb && cb(cbdata, nametag, N, EVR, Flags, index) != RPMRC_OK) { + rasprintf(&emsg, _("invalid dependency")); + goto exit; + } +diff --git a/build/parseScript.c b/build/parseScript.c +index 64fd89693..849e40244 100644 +--- a/build/parseScript.c ++++ b/build/parseScript.c +@@ -398,7 +398,7 @@ int parseScript(rpmSpec spec, int parsePart) + priority); + + /* Generate the trigger tags */ +- if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)) ++ if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags, addReqProvPkg, NULL)) + goto exit; + } else { + struct rpmtd_s td; +diff --git a/build/reqprov.c b/build/reqprov.c +index 7422db65f..5fa0a1c6b 100644 +--- a/build/reqprov.c ++++ b/build/reqprov.c +@@ -34,6 +34,14 @@ int addReqProv(Package pkg, rpmTagVal tagN, + return 0; + } + ++rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN, ++ const char * N, const char *EVR, rpmsenseFlags Flags, ++ int index) ++{ ++ Package pkg = cbdata; ++ return addReqProv(pkg, tagN, N, EVR, Flags, index) ? RPMRC_FAIL : RPMRC_OK; ++} ++ + int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEVR) + { + char *reqname = NULL; +diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h +index 7ec05b9c9..1c3332faf 100644 +--- a/build/rpmbuild_internal.h ++++ b/build/rpmbuild_internal.h +@@ -283,6 +283,10 @@ int parseScript(rpmSpec spec, int parsePart); + RPM_GNUC_INTERNAL + rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist); + ++typedef rpmRC (*addReqProvFunction) (void *cbdata, rpmTagVal tagN, ++ const char * N, const char * EVR, rpmsenseFlags Flags, ++ int index); ++ + /** \ingroup rpmbuild + * Parse dependency relations from spec file and/or autogenerated output buffer. + * @param spec spec file control structure +@@ -291,11 +295,13 @@ rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist); + * @param tagN tag, identifies type of dependency + * @param index (0 always) + * @param tagflags dependency flags already known from context ++ * @param cb Callback for adding dependency (nullable) ++ * @param cbdata Callback data (@pkg if NULL) + * @return RPMRC_OK on success, RPMRC_FAIL on failure + */ + RPM_GNUC_INTERNAL + rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char * field, rpmTagVal tagN, +- int index, rpmsenseFlags tagflags); ++ int index, rpmsenseFlags tagflags, addReqProvFunction cb, void *cbdata); + + /** \ingroup rpmbuild + * Evaluate boolean expression. +@@ -440,6 +446,10 @@ int addReqProv(Package pkg, rpmTagVal tagN, + const char * N, const char * EVR, rpmsenseFlags Flags, + uint32_t index); + ++RPM_GNUC_INTERNAL ++rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN, ++ const char * N, const char * EVR, rpmsenseFlags Flags, ++ int index); + + /** \ingroup rpmbuild + * Add self-provides to package. +diff --git a/build/rpmfc.c b/build/rpmfc.c +index 921814ad1..7fa8227d0 100644 +--- a/build/rpmfc.c ++++ b/build/rpmfc.c +@@ -447,44 +447,27 @@ static ARGV_t runCmd(const char *nsdep, const char *depname, + return output; + } + +-static const char *parseDep(char **depav, int depac, +- const char **N, const char **EVR, rpmsenseFlags *Flags) ++struct addReqProvDataFc { ++ rpmfc fc; ++ const char *namespace; ++ regex_t *exclude; ++}; ++ ++static rpmRC addReqProvFc(void *cbdata, rpmTagVal tagN, ++ const char * N, const char * EVR, rpmsenseFlags Flags, ++ int index) + { +- const char *err = NULL; +- +- switch (depac) { +- case 1: /* only a name */ +- *N = depav[0]; +- *EVR = ""; +- break; +- case 3: /* name, range and version */ +- for (const char *s = depav[1]; *s; s++) { +- switch(*s) { +- default: +- err = _("bad operator"); +- break; +- case '=': +- *Flags |= RPMSENSE_EQUAL; +- break; +- case '<': +- *Flags |= RPMSENSE_LESS; +- break; +- case '>': +- *Flags |= RPMSENSE_GREATER; +- break; +- } +- } +- if (!err) { +- *N = depav[0]; +- *EVR = depav[2]; +- } +- break; +- default: +- err = _("bad format"); +- break; +- } ++ struct addReqProvDataFc *data = cbdata; ++ rpmfc fc = data->fc; ++ const char *namespace = data->namespace; ++ regex_t *exclude = data->exclude; ++ ++ rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags); ++ /* Add to package and file dependencies unless filtered */ ++ if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) ++ rpmfcAddFileDep(&fc->fileDeps, ds, index); + +- return err; ++ return RPMRC_OK; + } + + /** +@@ -522,35 +505,14 @@ static int rpmfcHelper(rpmfc fc, int ix, + namespace = rpmfcAttrMacro(nsdep, NULL, "namespace"); + exclude = rpmfcAttrReg(depname, NULL, "exclude"); + ++ struct addReqProvDataFc data; ++ data.fc = fc; ++ data.namespace = namespace; ++ data.exclude = exclude; ++ + for (int i = 0; i < pac; i++) { +- char ** depav = NULL; +- int xx, depac = 0; +- const char *N = NULL; +- const char *EVR = NULL; +- const char *err = NULL; +- rpmsenseFlags Flags = dsContext; +- +- if ((xx = poptParseArgvString(pav[i], &depac, (const char ***)&depav))) +- err = poptStrerror(xx); +- +- if (!err) +- err = parseDep(depav, depac, &N, &EVR, &Flags); +- +- if (!err) { +- rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags); +- +- /* Add to package and file dependencies unless filtered */ +- if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) { +- //rpmdsMerge(packageDependencies(fc->pkg, tagN), ds); +- rpmfcAddFileDep(&fc->fileDeps, ds, ix); +- } +- } else { +- rpmlog(RPMLOG_ERR, _("invalid dependency (%s): %s\n"), +- err, pav[i]); ++ if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, 0, dsContext, addReqProvFc, &data)) + rc++; +- } +- +- free(depav); + } + + argvFree(pav); +@@ -1297,7 +1259,7 @@ static rpmRC rpmfcApplyExternal(rpmfc fc) + } + + /* Parse dependencies into header */ +- rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags); ++ rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags, addReqProvPkg, NULL); + freeStringBuf(sb_stdout); + + if (rc) { +-- +2.13.2 + diff --git a/0049-Pass-proper-file-index-when-recording-generated-depe.patch b/0049-Pass-proper-file-index-when-recording-generated-depe.patch new file mode 100644 index 0000000..bb98401 --- /dev/null +++ b/0049-Pass-proper-file-index-when-recording-generated-depe.patch @@ -0,0 +1,30 @@ +From d6a1e94f18d2f73e7b03025d891aa7e407cb169a Mon Sep 17 00:00:00 2001 +From: Florian Festi +Date: Wed, 31 May 2017 10:42:03 +0200 +Subject: [PATCH 49/49] Pass proper file index when recording generated + dependencies + +Resolves regression introduced with 8f509d6 +Fixes #224 + +(cherry picked from commit dab75e7f26a08cc6798e4df177adb2dd8d40035c) +--- + build/rpmfc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build/rpmfc.c b/build/rpmfc.c +index 7fa8227d0..72f29ddf5 100644 +--- a/build/rpmfc.c ++++ b/build/rpmfc.c +@@ -511,7 +511,7 @@ static int rpmfcHelper(rpmfc fc, int ix, + data.exclude = exclude; + + for (int i = 0; i < pac; i++) { +- if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, 0, dsContext, addReqProvFc, &data)) ++ if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, ix, dsContext, addReqProvFc, &data)) + rc++; + } + +-- +2.13.2 + diff --git a/0050-fixup-Support-debuginfo-subpackages.patch b/0050-fixup-Support-debuginfo-subpackages.patch new file mode 100644 index 0000000..95caa0c --- /dev/null +++ b/0050-fixup-Support-debuginfo-subpackages.patch @@ -0,0 +1,25 @@ +From bacdd7eeac9abb5046f5163a79ec8296287d83fc Mon Sep 17 00:00:00 2001 +From: Igor Gnatenko +Date: Fri, 30 Jun 2017 16:52:03 +0200 +Subject: [PATCH 50/50] fixup! Support debuginfo subpackages + +--- + build/files.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build/files.c b/build/files.c +index 933fad35b..f27dcc7c1 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -2930,7 +2930,7 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, + rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr); + free(nvr); + +- if ((rc = processPackageFiles(spec, pkgFlags, pkg, didInstall, test)) != RPMRC_OK) ++ if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK) + goto exit; + + if (maindbg) +-- +2.13.2 + diff --git a/debugedit-prefix.patch b/debugedit-prefix.patch deleted file mode 100644 index b50e4c2..0000000 --- a/debugedit-prefix.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/tools/debugedit.c b/tools/debugedit.c -index abd2ca4..a271b91 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -662,7 +662,8 @@ canonicalize_path (const char *s, char *d) - /* Returns the rest of PATH if it starts with DIR_PREFIX, skipping any - / path separators, or NULL if PATH doesn't start with - DIR_PREFIX. Might return the empty string if PATH equals DIR_PREFIX -- (modulo trailing slashes). Never returns path starting with '/'. */ -+ (modulo trailing slashes). Never returns path starting with '/'. -+ Note that DIR_PREFIX itself should NOT end with a '/'. */ - static const char * - skip_dir_prefix (const char *path, const char *dir_prefix) - { -@@ -670,12 +671,17 @@ skip_dir_prefix (const char *path, const char *dir_prefix) - if (strncmp (path, dir_prefix, prefix_len) == 0) - { - path += prefix_len; -+ /* Unless path == dir_prefix there should be at least one '/' -+ in the path (which we will skip). Otherwise the path has -+ a different (longer) directory prefix. */ -+ if (*path != '\0' && !IS_DIR_SEPARATOR (*path)) -+ return NULL; - while (IS_DIR_SEPARATOR (path[0])) - path++; - return path; - } - -- return 0; -+ return NULL; - } - - /* Most strings will be in the existing debug string table. But to diff --git a/debugsrc-and-sub-debuginfo-packages.patch b/debugsrc-and-sub-debuginfo-packages.patch deleted file mode 100644 index b60cb53..0000000 --- a/debugsrc-and-sub-debuginfo-packages.patch +++ /dev/null @@ -1,647 +0,0 @@ -commit 538cecf0f1fe127dc416afce7a7ee6f94fdb1ad7 -Author: Michael Schroeder -Date: Tue Mar 28 14:21:40 2017 +0200 - - Support debugsource subpackages - - This can be enabled by setting the _debugsource_packages macro. - -diff --git a/macros.in b/macros.in -index 0ddde29..007b8d4 100644 ---- a/macros.in -+++ b/macros.in -@@ -183,13 +183,12 @@ - %{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\ - %{?_find_debuginfo_dwz_opts} \\\ - %{?_find_debuginfo_opts} \\\ -+ %{?_debugsource_packages:-S debugsourcefiles.list} \\\ - "%{_builddir}/%{?buildsubdir}"\ - %{nil} - - # Template for debug information sub-package. --%debug_package \ --%ifnarch noarch\ --%global __debug_package 1\ -+%_debuginfo_template \ - %package debuginfo\ - Summary: Debug information for package %{name}\ - Group: Development/Debug\ -@@ -201,6 +200,26 @@ Debug information is useful when developing applications that use this\ - package or when debugging this package.\ - %files debuginfo -f debugfiles.list\ - %defattr(-,root,root)\ -+%{nil} -+ -+%_debugsource_template \ -+%package debugsource\ -+Summary: Debug sources for package %{name}\ -+Group: Development/Debug\ -+AutoReqProv: 0\ -+%description debugsource\ -+This package provides debug sources for package %{name}.\ -+Debug sources are useful when developing applications that use this\ -+package or when debugging this package.\ -+%files debugsource -f debugsourcefiles.list\ -+%defattr(-,root,root)\ -+%{nil} -+ -+%debug_package \ -+%ifnarch noarch\ -+%global __debug_package 1\ -+%_debuginfo_template\ -+%{?_debugsource_packages:%_debugsource_template}\ - %endif\ - %{nil} - -@@ -527,6 +546,9 @@ package or when debugging this package.\ - # directory under /usr/debug/src as --. - %_unique_debug_srcs 1 - -+# Whether rpm should put debug source files into its own subpackage -+#%_debugsource_packages 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 1ebc159..aaf4c75 100755 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -4,6 +4,7 @@ - # - # Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n] - # [-o debugfiles.list] -+# [-S debugsourcefiles.list] - # [--run-dwz] [--dwz-low-mem-die-limit N] - # [--dwz-max-die-limit N] - # [--build-id-seed VERSION-RELEASE] -@@ -79,6 +80,7 @@ n_jobs=1 - - BUILDDIR=. - out=debugfiles.list -+srcout= - nout=0 - while [ $# -gt 0 ]; do - case "$1" in -@@ -147,6 +149,10 @@ while [ $# -gt 0 ]; do - -j*) - n_jobs=${1#-j} - ;; -+ -S) -+ srcout=$2 -+ shift -+ ;; - *) - BUILDDIR=$1 - shift -@@ -512,10 +518,19 @@ if [ -d "${RPM_BUILD_ROOT}/usr/lib" -o -d "${RPM_BUILD_ROOT}/usr/src" ]; then - - (cd "${RPM_BUILD_ROOT}/usr" - test ! -d lib/debug || find lib/debug ! -type d -- test ! -d src/debug || find src/debug -mindepth 1 -maxdepth 1 -+ test ! -d src/debug -o -n "$srcout" || find src/debug -mindepth 1 -maxdepth 1 - ) | sed 's,^,/usr/,' >> "$LISTFILE" - fi - -+if [ -n "$srcout" ]; then -+ > "$srcout" -+ if [ -d "${RPM_BUILD_ROOT}/usr/src/debug" ]; then -+ (cd "${RPM_BUILD_ROOT}/usr" -+ find src/debug -mindepth 1 -maxdepth 1 -+ ) | sed 's,^,/usr/,' >> "$srcout" -+ fi -+fi -+ - # Append to $1 only the lines from stdin not already in the file. - append_uniq() - { - -commit 980749fdce055254ca92ee7e2595b16750b699a2 -Author: Michael Schroeder -Date: Fri Mar 24 15:35:23 2017 +0100 - - Support debuginfo subpackages - - We do this by filtering the debuginfo files generated by find-debuginfo.sh - with the files from the (sub)packages. - - This commit is heavily based on a patch by Richard Biener. - -diff --git a/build/files.c b/build/files.c -index f58569e..e3fc8d6 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -40,6 +40,16 @@ - #define SKIPWHITE(_x) {while(*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;} - #define SKIPNONWHITE(_x){while(*(_x) &&!(risspace(*_x) || *(_x) == ',')) (_x)++;} - -+/* the following defines must be in sync with the equally hardcoded paths from -+ * scripts/find-debuginfo.sh -+ */ -+#define BUILD_ID_DIR "/usr/lib/.build-id" -+#define DEBUG_SRC_DIR "/usr/src/debug" -+#define DEBUG_LIB_DIR "/usr/lib/debug" -+#define DEBUG_LIB_PREFIX "/usr/lib/debug/" -+#define DEBUG_ID_DIR "/usr/lib/debug/.build-id" -+#define DEBUG_DWZ_DIR "/usr/lib/debug/.dwz" -+ - /** - */ - enum specfFlags_e { -@@ -1738,9 +1748,8 @@ static int generateBuildIDs(FileList fl) - if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) { - /* We determine whether this is a main or - debug ELF based on path. */ -- #define DEBUGPATH "/usr/lib/debug/" - int isDbg = strncmp (flp->cpioPath, -- DEBUGPATH, strlen (DEBUGPATH)) == 0; -+ DEBUG_LIB_PREFIX, strlen (DEBUG_LIB_PREFIX)) == 0; - - /* For the main package files mimic what find-debuginfo.sh does. - Only check build-ids for executable files. Debug files are -@@ -1833,8 +1842,6 @@ static int generateBuildIDs(FileList fl) - if (rc == 0) { - char *attrstr; - /* Add .build-id directories to hold the subdirs/symlinks. */ -- #define BUILD_ID_DIR "/usr/lib/.build-id" -- #define DEBUG_ID_DIR "/usr/lib/debug/.build-id" - - mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL); - debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL); -@@ -1898,8 +1905,8 @@ static int generateBuildIDs(FileList fl) - /* Don't add anything more when an error occured. But do - cleanup. */ - if (rc == 0) { -- int isDbg = strncmp (paths[i], DEBUGPATH, -- strlen (DEBUGPATH)) == 0; -+ int isDbg = strncmp (paths[i], DEBUG_LIB_PREFIX, -+ strlen (DEBUG_LIB_PREFIX)) == 0; - - char *buildidsubdir; - char subdir[4]; -@@ -2001,7 +2008,7 @@ static int generateBuildIDs(FileList fl) - which don't end in ".debug". */ - int pathlen = strlen(paths[i]); - int debuglen = strlen(".debug"); -- int prefixlen = strlen("/usr/lib/debug"); -+ int prefixlen = strlen(DEBUG_LIB_DIR); - int vralen = vra == NULL ? 0 : strlen(vra); - if (pathlen > prefixlen + debuglen + vralen - && strcmp ((paths[i] + pathlen - debuglen), -@@ -2659,24 +2666,273 @@ exit: - return rc; - } - -+static rpmTag copyTagsFromMainDebug[] = { -+ RPMTAG_ARCH, -+ RPMTAG_SUMMARY, -+ RPMTAG_DESCRIPTION, -+ RPMTAG_GROUP, -+ /* see addTargets */ -+ RPMTAG_OS, -+ RPMTAG_PLATFORM, -+ RPMTAG_OPTFLAGS, -+}; -+ -+/* this is a hack: patch the summary and the description to include -+ * the correct package name */ -+static void patchDebugPackageString(Package dbg, rpmTag tag, Package pkg, Package mainpkg) -+{ -+ const char *oldname, *newname, *old; -+ char *oldsubst = NULL, *newsubst = NULL, *p; -+ oldname = headerGetString(mainpkg->header, RPMTAG_NAME); -+ newname = headerGetString(pkg->header, RPMTAG_NAME); -+ rasprintf(&oldsubst, "package %s", oldname); -+ rasprintf(&newsubst, "package %s", newname); -+ old = headerGetString(dbg->header, tag); -+ p = old ? strstr(old, oldsubst) : NULL; -+ if (p) { -+ char *new = NULL; -+ rasprintf(&new, "%.*s%s%s", (int)(p - old), old, newsubst, p + strlen(oldsubst)); -+ headerDel(dbg->header, tag); -+ headerPutString(dbg->header, tag, new); -+ _free(new); -+ } -+ _free(oldsubst); -+ _free(newsubst); -+} -+ -+/* create a new debuginfo subpackage for package pkg from the -+ * main debuginfo package */ -+static Package cloneDebuginfoPackage(rpmSpec spec, Package pkg, Package maindbg) -+{ -+ const char *name = headerGetString(pkg->header, RPMTAG_NAME); -+ char *dbgname = NULL; -+ Package dbg; -+ -+ rasprintf(&dbgname, "%s-%s", name, "debuginfo"); -+ dbg = newPackage(dbgname, spec->pool, &spec->packages); -+ headerPutString(dbg->header, RPMTAG_NAME, dbgname); -+ copyInheritedTags(dbg->header, pkg->header); -+ headerDel(dbg->header, RPMTAG_GROUP); -+ headerCopyTags(maindbg->header, dbg->header, copyTagsFromMainDebug); -+ dbg->autoReq = maindbg->autoReq; -+ dbg->autoProv = maindbg->autoProv; -+ -+ /* patch summary and description strings */ -+ patchDebugPackageString(dbg, RPMTAG_SUMMARY, pkg, spec->packages); -+ patchDebugPackageString(dbg, RPMTAG_DESCRIPTION, pkg, spec->packages); -+ -+ /* Add self-provides (normally done by addTargets) */ -+ addPackageProvides(dbg); -+ dbg->ds = rpmdsThis(dbg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); -+ -+ _free(dbgname); -+ return dbg; -+} -+ -+/* add a directory to the file list */ -+static void argvAddDir(ARGV_t *filesp, const char *dir) -+{ -+ char *line = NULL; -+ rasprintf(&line, "%%dir %s", dir); -+ argvAdd(filesp, line); -+ _free(line); -+} -+ -+/* collect the debug files for package pkg and put them into -+ * a (possibly new) debuginfo subpackage */ -+static void filterDebuginfoPackage(rpmSpec spec, Package pkg, -+ Package maindbg, char *buildroot, char *uniquearch) -+{ -+ rpmfi fi; -+ ARGV_t files = NULL; -+ Package dbg = NULL; -+ char *path = NULL; -+ size_t buildrootlen = strlen(buildroot); -+ -+ /* ignore noarch subpackages */ -+ if (rstreq(headerGetString(pkg->header, RPMTAG_ARCH), "noarch")) -+ return; -+ -+ if (!uniquearch) -+ uniquearch = ""; -+ -+ fi = rpmfilesIter(pkg->cpioList, RPMFI_ITER_FWD); -+ /* Check if the current package has files with debug info -+ and add them to the file list */ -+ fi = rpmfiInit(fi, 0); -+ while (rpmfiNext(fi) >= 0) { -+ const char *name = rpmfiFN(fi); -+ int namel = strlen(name); -+ -+ /* strip trailing .debug like in find-debuginfo.sh */ -+ namel = strlen(name); -+ if (namel > 6 && !strcmp(name + namel - 6, ".debug")) -+ namel -= 6; -+ -+ /* generate path */ -+ rasprintf(&path, "%s%s%.*s%s.debug", buildroot, DEBUG_LIB_DIR, namel, name, uniquearch); -+ -+ /* If that file exists we have debug information for it */ -+ if (access(path, F_OK) == 0) { -+ /* Append the file list preamble */ -+ if (!files) { -+ argvAdd(&files, "%defattr(-,root,root)"); -+ argvAddDir(&files, DEBUG_LIB_DIR); -+ } -+ /* Add the files main debug-info file */ -+ argvAdd(&files, path + buildrootlen); -+ } -+ path = _free(path); -+ } -+ -+ if (files) { -+ /* we have collected some files. Now put them in a debuginfo -+ * package. If this is not the main package, clone the main -+ * debuginfo package */ -+ if (pkg == spec->packages) -+ maindbg->fileList = files; -+ else { -+ Package dbg = cloneDebuginfoPackage(spec, pkg, maindbg); -+ dbg->fileList = files; -+ } -+ } -+} -+ -+/* add the debug dwz files to package pkg. -+ * return 1 if something was added, 0 otherwise. */ -+static int addDebugDwz(Package pkg, char *buildroot) -+{ -+ int ret = 0; -+ char *path = NULL; -+ struct stat sbuf; -+ -+ rasprintf(&path, "%s%s", buildroot, DEBUG_DWZ_DIR); -+ if (lstat(path, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)) { -+ if (!pkg->fileList) { -+ argvAdd(&pkg->fileList, "%defattr(-,root,root)"); -+ argvAddDir(&pkg->fileList, DEBUG_LIB_DIR); -+ } -+ argvAdd(&pkg->fileList, DEBUG_DWZ_DIR); -+ ret = 1; -+ } -+ path = _free(path); -+ return ret; -+} -+ -+/* add the debug source files to package pkg. -+ * return 1 if something was added, 0 otherwise. */ -+static int addDebugSrc(Package pkg, char *buildroot) -+{ -+ int ret = 0; -+ char *path = NULL; -+ DIR *d; -+ struct dirent *de; -+ -+ /* not needed if we have an extra debugsource subpackage */ -+ if (rpmExpandNumeric("%{?_debugsource_packages}")) -+ return 0; -+ -+ rasprintf(&path, "%s%s", buildroot, DEBUG_SRC_DIR); -+ d = opendir(path); -+ path = _free(path); -+ if (d) { -+ while ((de = readdir(d)) != NULL) { -+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) -+ continue; -+ rasprintf(&path, "%s/%s", DEBUG_SRC_DIR, de->d_name); -+ if (!pkg->fileList) -+ argvAdd(&pkg->fileList, "%defattr(-,root,root)"); -+ argvAdd(&pkg->fileList, path); -+ path = _free(path); -+ ret = 1; -+ } -+ closedir(d); -+ } -+ return ret; -+} -+ -+/* find the main debuginfo package. We do this simply by -+ * searching for a package with the right name. */ -+static Package findDebuginfoPackage(rpmSpec spec) -+{ -+ Package pkg = NULL; -+ if (lookupPackage(spec, "debuginfo", PART_SUBNAME, &pkg)) -+ return NULL; -+ return pkg && pkg->fileList ? pkg : NULL; -+} -+ -+/* add a requires for package "to" into package "from". */ -+static void addPackageRequires(Package from, Package to) -+{ -+ const char *name; -+ char *evr, *isaprov; -+ name = headerGetString(to->header, RPMTAG_NAME); -+ evr = headerGetAsString(to->header, RPMTAG_EVR); -+ isaprov = rpmExpand(name, "%{?_isa}", NULL); -+ addReqProv(from, RPMTAG_REQUIRENAME, isaprov, evr, RPMSENSE_EQUAL, 0); -+ free(isaprov); -+ free(evr); -+} -+ - rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - int installSpecialDoc, int test) - { - Package pkg; - rpmRC rc = RPMRC_OK; -+ char *buildroot; -+ char *uniquearch = NULL; -+ Package maindbg = NULL; /* the (existing) main debuginfo package */ -+ Package deplink = NULL; /* create requires to this package */ - - #if HAVE_LIBDW - elf_version (EV_CURRENT); - #endif - check_fileList = newStringBuf(); - genSourceRpmName(spec); -+ buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL); - -+ if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) { -+ maindbg = findDebuginfoPackage(spec); -+ if (maindbg) { -+ /* move debuginfo package to back */ -+ if (maindbg->next) { -+ Package *pp; -+ /* dequeue */ -+ for (pp = &spec->packages; *pp != maindbg; pp = &(*pp)->next) -+ ; -+ *pp = maindbg->next; -+ maindbg->next = 0; -+ /* enqueue at tail */ -+ for (; *pp; pp = &(*pp)->next) -+ ; -+ *pp = maindbg; -+ } -+ /* delete unsplit file list, we will re-add files back later */ -+ maindbg->fileFile = argvFree(maindbg->fileFile); -+ maindbg->fileList = argvFree(maindbg->fileList); -+ if (rpmExpandNumeric("%{?_unique_debug_names}")) -+ uniquearch = rpmExpand("-%{VERSION}-%{RELEASE}.%{_arch}", NULL); -+ } -+ } -+ - for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { - char *nvr; - const char *a; - int header_color; - int arch_color; - -+ if (pkg == maindbg) { -+ /* if there is just one debuginfo package, we put our extra stuff -+ * in it. Otherwise we put it in the main debug package */ -+ Package extradbg = !maindbg->fileList && maindbg->next && !maindbg->next->next ? -+ maindbg->next : maindbg; -+ if (addDebugDwz(extradbg, buildroot)) -+ deplink = extradbg; -+ if (addDebugSrc(extradbg, buildroot)) -+ deplink = extradbg; -+ maindbg = NULL; /* all normal packages processed */ -+ } -+ - if (pkg->fileList == NULL) - continue; - -@@ -2685,9 +2941,16 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - nvr = headerGetAsString(pkg->header, RPMTAG_NVRA); - rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr); - free(nvr); -- -- if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK || -- (rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK) -+ -+ if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK) -+ goto exit; -+ -+ if (maindbg) -+ filterDebuginfoPackage(spec, pkg, maindbg, buildroot, uniquearch); -+ else if (deplink && pkg != deplink) -+ addPackageRequires(pkg, deplink); -+ -+ if ((rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK) - goto exit; - - a = headerGetString(pkg->header, RPMTAG_ARCH); -@@ -2722,6 +2985,8 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, - } - exit: - check_fileList = freeStringBuf(check_fileList); -+ _free(buildroot); -+ _free(uniquearch); - - return rc; - } -diff --git a/build/parsePreamble.c b/build/parsePreamble.c -index 6d25f4c..5715d25 100644 ---- a/build/parsePreamble.c -+++ b/build/parsePreamble.c -@@ -544,6 +544,13 @@ static void fillOutMainPackage(Header h) - - /** - */ -+void copyInheritedTags(Header h, Header fromh) -+{ -+ headerCopyTags(fromh, h, (rpmTagVal *)copyTagsDuringParse); -+} -+ -+/** -+ */ - static rpmRC readIcon(Header h, const char * file) - { - char *fn = NULL; -@@ -1197,8 +1204,7 @@ int parsePreamble(rpmSpec spec, int initialPackage) - } - - if (pkg != spec->packages) { -- headerCopyTags(spec->packages->header, pkg->header, -- (rpmTagVal *)copyTagsDuringParse); -+ copyInheritedTags(pkg->header, spec->packages->header); - } - - if (checkForRequired(pkg->header, NVR)) { -diff --git a/build/parseSpec.c b/build/parseSpec.c -index 2928e85..d0c42a4 100644 ---- a/build/parseSpec.c -+++ b/build/parseSpec.c -@@ -572,7 +572,7 @@ static void initSourceHeader(rpmSpec spec) - } - - /* Add extra provides to package. */ --static void addPackageProvides(Package pkg) -+void addPackageProvides(Package pkg) - { - const char *arch, *name; - char *evr, *isaprov; -diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h -index 948dc31..46d9676 100644 ---- a/build/rpmbuild_internal.h -+++ b/build/rpmbuild_internal.h -@@ -442,6 +442,13 @@ - - - /** \ingroup rpmbuild -+ * Add self-provides to package. -+ * @param pkg package -+ */ -+RPM_GNUC_INTERNAL -+void addPackageProvides(Package pkg); -+ -+/** \ingroup rpmbuild - * Add rpmlib feature dependency. - * @param pkg package - * @param feature rpm feature name (i.e. "rpmlib(Foo)" for feature Foo) -@@ -463,6 +470,16 @@ int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEV - - RPM_GNUC_INTERNAL - rpmRC checkForEncoding(Header h, int addtag); -+ -+ -+/** \ingroup rpmbuild -+ * Copy tags inherited by subpackages from the source header to the target header -+ * @param h target header -+ * @param fromh source header -+ */ -+RPM_GNUC_INTERNAL -+void copyInheritedTags(Header h, Header fromh); -+ - #ifdef __cplusplus - } - #endif -diff --git a/macros.in b/macros.in -index 007b8d4..cb65f4f 100644 ---- a/macros.in -+++ b/macros.in -@@ -549,6 +549,9 @@ package or when debugging this package.\ - # Whether rpm should put debug source files into its own subpackage - #%_debugsource_packages 1 - -+# Whether rpm should create extra debuginfo packages for each subpackage -+#%_debuginfo_subpackages 1 -+ - # - # Use internal dependency generator rather than external helpers? - %_use_internal_dependency_generator 1 - -commit a517554e36666f58724620347a4b8224471d2225 -Author: Michael Schroeder -Date: Wed Mar 29 14:55:10 2017 +0200 - - Also add directories to split debuginfo packages - - This gets rid of the last difference between debuginfo subpackages - and normal debuginfo packages. - -diff --git a/build/files.c b/build/files.c -index e3fc8d6..5022069 100644 ---- a/build/files.c -+++ b/build/files.c -@@ -2745,8 +2745,9 @@ static void filterDebuginfoPackage(rpmSpec spec, Package pkg, - { - rpmfi fi; - ARGV_t files = NULL; -- Package dbg = NULL; -- char *path = NULL; -+ ARGV_t dirs = NULL; -+ int lastdiridx = -1, dirsadded; -+ char *path = NULL, *p, *pmin; - size_t buildrootlen = strlen(buildroot); - - /* ignore noarch subpackages */ -@@ -2779,12 +2780,37 @@ static void filterDebuginfoPackage(rpmSpec spec, Package pkg, - argvAdd(&files, "%defattr(-,root,root)"); - argvAddDir(&files, DEBUG_LIB_DIR); - } -+ - /* Add the files main debug-info file */ - argvAdd(&files, path + buildrootlen); -+ -+ /* Add the dir(s) */ -+ dirsadded = 0; -+ pmin = path + buildrootlen + strlen(DEBUG_LIB_DIR); -+ while ((p = strrchr(path + buildrootlen, '/')) != NULL && p > pmin) { -+ *p = 0; -+ if (lastdiridx >= 0 && !strcmp(dirs[lastdiridx], path + buildrootlen)) -+ break; /* already added this one */ -+ argvAdd(&dirs, path + buildrootlen); -+ dirsadded++; -+ } -+ if (dirsadded) -+ lastdiridx = argvCount(dirs) - dirsadded; /* remember longest dir */ - } - path = _free(path); - } - -+ /* add collected directories to file list */ -+ if (dirs) { -+ int i; -+ argvSort(dirs, NULL); -+ for (i = 0; dirs[i]; i++) { -+ if (!i || strcmp(dirs[i], dirs[i - 1]) != 0) -+ argvAddDir(&files, dirs[i]); -+ } -+ dirs = argvFree(dirs); -+ } -+ - if (files) { - /* we have collected some files. Now put them in a debuginfo - * package. If this is not the main package, clone the main diff --git a/find-debuginfo-and-macro-docs.patch b/find-debuginfo-and-macro-docs.patch deleted file mode 100644 index 98197ae..0000000 --- a/find-debuginfo-and-macro-docs.patch +++ /dev/null @@ -1,106 +0,0 @@ -commit 173e5642a97c535f8bdaac5bf88854a103cc125b -Author: Mark Wielaard -Date: Mon Jun 26 13:35:48 2017 +0200 - - Update find-debuginfo.sh options and macros documentation. - - This adds some missing documentation for rpm macros and find-debuginfo.sh - options that were recently added (or renamed). -j N, --build-id-seed SEED, - --unique-debug-suffix SUFFIX and --unique-debug-src-base BASE. - - Signed-off-by: Mark Wielaard - -diff --git a/macros.in b/macros.in -index b095719..3e9b73f 100644 ---- a/macros.in -+++ b/macros.in -@@ -522,8 +522,9 @@ package or when debugging this package.\ - - # 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. -+# --build-id-seed "%{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 - - # Do not recompute build-ids but keep whatever is in the ELF file already. -@@ -533,15 +534,16 @@ package or when debugging this package.\ - - # Whether .debug files should be made unique between package version, - # release and architecture. If set to 1 this will pass --# --unique-debug-arch "%{_arch}" to find-debuginfo.sh to create --# debuginfo files which end in --..debug -+# --unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch} find-debuginfo.sh -+# to create debuginfo files which end in --..debug - # Requires _unique_build_ids. - %_unique_debug_names 1 - - # Whether the /usr/debug/src/ directories should be unique between - # package version, release and architecture. If set to 1 this will pass --# --unique-debug-src-base "%{name}" to find-debuginfo.sh to name the --# directory under /usr/debug/src as --. -+# --unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}" to -+# find-debuginfo.sh to name the directory under /usr/debug/src as -+# --.. - %_unique_debug_srcs 1 - - # Whether rpm should put debug source files into its own subpackage -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index 0233d92..85a862f 100755 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -3,11 +3,14 @@ - #for inclusion in an rpm spec file. - # - # Usage: find-debuginfo.sh [--strict-build-id] [-g] [-r] [-m] [-i] [-n] -+# [-j N] - # [-o debugfiles.list] - # [-S debugsourcefiles.list] - # [--run-dwz] [--dwz-low-mem-die-limit N] - # [--dwz-max-die-limit N] --# [--build-id-seed VERSION-RELEASE] -+# [--build-id-seed SEED] -+# [--unique-debug-suffix SUFFIX] -+# [--unique-debug-src-base BASE] - # [[-l filelist]... [-p 'pattern'] -o debuginfo.list] - # [builddir] - # -@@ -19,6 +22,9 @@ - # The -i flag says to include a .gdb_index section in the .debug file. - # The -n flag says to not recompute the build-id. - # -+# The -j N option will spawn N processes to do the debuginfo extraction -+# in parallel. -+# - # A single -o switch before any -l or -p switches simply renames - # the primary output file from debugfiles.list to something else. - # A -o switch that follows a -p switch or some -l switches produces -@@ -31,11 +37,21 @@ - # 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 --build-id-seed 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. -+# If --build-id-seed SEED is given then debugedit is called to -+# update the build-ids it finds adding the SEED 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. -+# (Use --build-id-seed "%{VERSION}-%{RELEASE}".) -+# -+# If --unique-debug-suffix SUFFIX is given then the debug files created -+# for will be named -.debug. This makes sure .debug -+# are unique between package version, release and architecture. -+# (Use --unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch}".) -+# -+# If --unique-debug-src-base BASE is given then the source directory -+# will be called /usr/debug/src/. This makes sure the debug source -+# directories are unique between package version, release and architecture. -+# (Use --unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}".) - # - # All file names in switches are relative to builddir (. if not given). - # diff --git a/find-debuginfo-dwz-multi.patch b/find-debuginfo-dwz-multi.patch deleted file mode 100644 index e7a8c83..0000000 --- a/find-debuginfo-dwz-multi.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 0f162dc41f2051eab237bd223356d88e94a07580 -Author: Mark Wielaard -Date: Mon Jun 26 17:38:30 2017 +0200 - - find-debuginfo.sh: Don't create dwz multi file if there is only one .debug. - - dwz -m multi only works when there are multiple .debug input files. - With just one .debug file it doesn't really make sense to extract - the shared debug info into a separate file and dwz will complain: - - dwz: Too few files for multifile optimization. - - So only add -m multi if there is more than one .debug file. - - Signed-off-by: Mark Wielaard - -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index 85a862f..360982d 100755 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -458,8 +458,8 @@ fi - # Invoke the DWARF Compressor utility. - if $run_dwz \ - && [ -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 -+ readarray dwz_files < <(cd "${RPM_BUILD_ROOT}/usr/lib/debug"; find -type f -name \*.debug) -+ if [ ${#dwz_files[@]} -gt 0 ]; then - dwz_multifile_name="${RPM_PACKAGE_NAME}-${RPM_PACKAGE_VERSION}-${RPM_PACKAGE_RELEASE}.${RPM_ARCH}" - dwz_multifile_suffix= - dwz_multifile_idx=0 -@@ -468,14 +468,16 @@ if $run_dwz \ - 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}" -+ dwz_opts="-h -q -r" -+ [ ${#dwz_files[@]} -gt 1 ] \ -+ && dwz_opts="${dwz_opts} -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}" - if type dwz >/dev/null 2>&1; then -- ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts $dwz_files ) -+ ( cd "${RPM_BUILD_ROOT}/usr/lib/debug" && dwz $dwz_opts ${dwz_files[@]} ) - else - echo >&2 "*** ERROR: DWARF compression requested, but no dwz installed" - exit 2 diff --git a/find-debuginfo-filter-built-ins.patch b/find-debuginfo-filter-built-ins.patch deleted file mode 100644 index 02903c2..0000000 --- a/find-debuginfo-filter-built-ins.patch +++ /dev/null @@ -1,36 +0,0 @@ -commit 78df22afc540c6c34003c3cb8ecc3ee686fbef76 -Author: Mark Wielaard -Date: Wed Jun 28 13:25:12 2017 +0200 - - find-debuginfo.sh: Filter out all like fake file names. - - There is no official way to mark an instruction range as being not - part of some actual source code, but as part of a compiler built-in - construct in DWARF. So different compilers have come up with fake - source file names like or <__thread_local_inner macros>. - We already filtered out the strings "" and "". - Just filter out all '(^|/)<[a-z _-]+>$'. They are fake files! - - This is mainly to appease the rustc compiler which generates lots of - different variants to encode some instruction sequence is part of an - compiler generated macro expansion. - - Signed-off-by: Mark Wielaard - -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index 0233d92..555e7b8 100755 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -502,7 +502,11 @@ if [ -s "$SOURCEFILE" ]; then - fi - - mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" -- LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(|)$' | -+ # Filter out anything compiler generated which isn't a source file. -+ # e.g. , , <__thread_local_inner macros>. -+ # Some compilers generate them as if they are part of the working -+ # directory (which is why we match against ^ or /). -+ LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(^|/)<[a-z _-]+>$' | - (cd "${debug_base_name}"; cpio -pd0mL "${RPM_BUILD_ROOT}${debug_dest_name}") - # stupid cpio creates new directories in mode 0700, - # and non-standard modes may be inherented from original directories, fixup diff --git a/find-debuginfo-process-files-in-parallel.patch b/find-debuginfo-process-files-in-parallel.patch deleted file mode 100644 index 030c5b2..0000000 --- a/find-debuginfo-process-files-in-parallel.patch +++ /dev/null @@ -1,113 +0,0 @@ -commit 1b338aa84d4c67fefa957352a028eaca1a45d1f6 -Author: Michal Marek -Date: Sat Sep 10 23:13:25 2016 +0200 - - find-debuginfo.sh: Process files in parallel - - Add a -j option, which, when used, will spawn processes to do the - debuginfo extraction in parallel. A pipe is used to dispatch the files among - the processes. - - Signed-off-by: Michal Marek - -diff --git a/macros.in b/macros.in -index b03c5a9..8bde2d7 100644 ---- a/macros.in -+++ b/macros.in -@@ -180,7 +180,7 @@ - # the script. See the script for details. - # - %__debug_install_post \ -- %{_rpmconfigdir}/find-debuginfo.sh %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh %{?_smp_mflags} %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_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 6dcd5a4..2016222 100644 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -74,6 +74,9 @@ - # Base given by --unique-debug-src-base - unique_debug_src_base= - -+# Number of parallel jobs to spawn -+n_jobs=1 -+ - BUILDDIR=. - out=debugfiles.list - nout=0 -@@ -137,6 +140,13 @@ - -r) - strip_r=true - ;; -+ -j) -+ n_jobs=$2 -+ shift -+ ;; -+ -j*) -+ n_jobs=${1#-j} -+ ;; - *) - BUILDDIR=$1 - shift -@@ -389,9 +399,56 @@ - fi - } - --while read nlinks inum f; do -- do_file "$nlinks" "$inum" "$f" --done <"$temp/primary" -+# 16^6 - 1 or about 16 milion files -+FILENUM_DIGITS=6 -+run_job() -+{ -+ local jobid=$1 filenum -+ local SOURCEFILE=$temp/debugsources.$jobid ELFBINSFILE=$temp/elfbins.$jobid -+ -+ >"$SOURCEFILE" -+ >"$ELFBINSFILE" -+ # can't use read -n , because it reads bytes one by one, allowing for -+ # races -+ while :; do -+ filenum=$(dd bs=$(( FILENUM_DIGITS + 1 )) count=1 status=none) -+ if test -z "$filenum"; then -+ break -+ fi -+ do_file $(sed -n "$(( 0x$filenum )) p" "$temp/primary") -+ done -+ echo 0 >"$temp/res.$jobid" -+} -+ -+n_files=$(wc -l <"$temp/primary") -+if [ $n_jobs -gt $n_files ]; then -+ n_jobs=$n_files -+fi -+if [ $n_jobs -le 1 ]; then -+ while read nlinks inum f; do -+ do_file "$nlinks" "$inum" "$f" -+ done <"$temp/primary" -+else -+ for ((i = 1; i <= n_files; i++)); do -+ printf "%0${FILENUM_DIGITS}x\\n" $i -+ done | ( -+ exec 3<&0 -+ for ((i = 0; i < n_jobs; i++)); do -+ # The shell redirects stdin to /dev/null for background jobs. Work -+ # around this by duplicating fd 0 -+ run_job $i <&3 & -+ done -+ wait -+ ) -+ for f in "$temp"/res.*; do -+ res=$(< "$f") -+ if [ "$res" != "0" ]; then -+ exit 1 -+ fi -+ done -+ cat "$temp"/debugsources.* >"$SOURCEFILE" -+ cat "$temp"/elfbins.* >"$ELFBINSFILE" -+fi - - # Invoke the DWARF Compressor utility. - if $run_dwz \ diff --git a/find-debuginfo-split-traversal-and-extraction-fix.patch b/find-debuginfo-split-traversal-and-extraction-fix.patch deleted file mode 100644 index 46fadc4..0000000 --- a/find-debuginfo-split-traversal-and-extraction-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- rpm-4.13.0.1/scripts/find-debuginfo.sh.orig 2017-06-28 13:00:10.780609617 +0200 -+++ rpm-4.13.0.1/scripts/find-debuginfo.sh 2017-06-28 13:00:38.331005393 +0200 -@@ -351,7 +351,7 @@ - # just has its file names collected and adjusted. - case "$dn" in - /usr/lib/debug/*) -- continue ;; -+ return ;; - esac - - mkdir -p "${debugdn}" diff --git a/find-debuginfo-split-traversal-and-extraction.patch b/find-debuginfo-split-traversal-and-extraction.patch deleted file mode 100644 index 6ceb7be..0000000 --- a/find-debuginfo-split-traversal-and-extraction.patch +++ /dev/null @@ -1,100 +0,0 @@ -commit 038bfe01796f751001e02de41c5d8678f511f366 -Author: Michal Marek -Date: Sat Sep 10 23:13:24 2016 +0200 - - find-debuginfo.sh: Split directory traversal and debuginfo extraction - - This siplifies the handling of hardlinks a bit and allows a later patch - to parallelize the debuginfo extraction. - - Signed-off-by: Michal Marek - -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -index d83c3e2..6dcd5a4 100644 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -283,32 +283,36 @@ - strict_error=ERROR - $strict || strict_error=WARNING - --# Strip ELF binaries -+temp=$(mktemp -d ${TMPDIR:-/tmp}/find-debuginfo.XXXXXX) -+trap 'rm -rf "$temp"' EXIT -+ -+# Build a list of unstripped ELF files and their hardlinks -+touch "$temp/primary" - find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \ - \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \ - -print | - file -N -f - | sed -n -e 's/^\(.*\):[ ]*.*ELF.*, not stripped.*/\1/p' | - xargs --no-run-if-empty stat -c '%h %D_%i %n' | - while read nlinks inum f; do -- get_debugfn "$f" -- [ -f "${debugfn}" ] && continue -- -- # If this file has multiple links, keep track and make -- # the corresponding .debug files all links to one file too. - if [ $nlinks -gt 1 ]; then -- eval linked=\$linked_$inum -- if [ -n "$linked" ]; then -- eval id=\$linkedid_$inum -- link=$debugfn -- get_debugfn "$linked" -- echo "hard linked $link to $debugfn" -- mkdir -p "$(dirname "$link")" && ln -nf "$debugfn" "$link" -+ var=seen_$inum -+ if test -n "${!var}"; then -+ echo "$inum $f" >>"$temp/linked" - continue - else -- eval linked_$inum=\$f -- echo "file $f has $[$nlinks - 1] other hard links" -+ read "$var" < <(echo 1) - fi - fi -+ echo "$nlinks $inum $f" >>"$temp/primary" -+done -+ -+# Strip ELF binaries -+do_file() -+{ -+ local nlinks=$1 inum=$2 f=$3 id link linked -+ -+ get_debugfn "$f" -+ [ -f "${debugfn}" ] && return - - echo "extracting debug info from $f" - build_id_seed= -@@ -328,9 +332,6 @@ - fi - id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ - $no_recompute -i $build_id_seed -l "$SOURCEFILE" "$f") || exit -- if [ $nlinks -gt 1 ]; then -- eval linkedid_$inum=\$id -- fi - if [ -z "$id" ]; then - echo >&2 "*** ${strict_error}: No build ID note found in $f" - $strict && exit 2 -@@ -376,7 +377,21 @@ - - echo "./${f#$RPM_BUILD_ROOT}" >> "$ELFBINSFILE" - --done || exit -+ # If this file has multiple links, make the corresponding .debug files -+ # all links to one file too. -+ if [ $nlinks -gt 1 ]; then -+ grep "^$inum " "$temp/linked" | while read inum linked; do -+ link=$debugfn -+ get_debugfn "$linked" -+ echo "hard linked $link to $debugfn" -+ mkdir -p "$(dirname "$debugfn")" && ln -nf "$link" "$debugfn" -+ done -+ fi -+} -+ -+while read nlinks inum f; do -+ do_file "$nlinks" "$inum" "$f" -+done <"$temp/primary" - - # Invoke the DWARF Compressor utility. - if $run_dwz \ diff --git a/find-debuginfo-untangle-unique-build-options.patch b/find-debuginfo-untangle-unique-build-options.patch deleted file mode 100644 index c0e06ad..0000000 --- a/find-debuginfo-untangle-unique-build-options.patch +++ /dev/null @@ -1,167 +0,0 @@ -commit 4842adfd91c3b37744c66d9f01c0112468fdbf37 -Author: Michael Schroeder -Date: Tue Mar 28 14:20:50 2017 +0200 - - Untangle unique build options in find-debuginfo.sh - - Rename --ver-rel option to --build-id-seed, so that it reflects what - it does, not how it is used. - - Remove implcit usage of the old --ver-rel option for --unique-debug-arch - and --unique-debug-src-base, instead already call find-debuginfo.sh with - the version included. - - Rename --unique-debug-arch to --unique-debug-suffix because it now - also contains the package version. - -diff --git a/macros.in b/macros.in -index 7656c06..0ddde29 100644 ---- a/macros.in -+++ b/macros.in -@@ -172,7 +172,18 @@ - # the script. See the script for details. - # - %__debug_install_post \ -- %{_rpmconfigdir}/find-debuginfo.sh %{?_smp_mflags} %{?_missing_build_ids_terminate_build:--strict-build-id} %{?_no_recompute_build_ids:-n} %{?_include_minidebuginfo:-m} %{?_include_gdb_index:-i} %{?_unique_build_ids:--ver-rel "%{VERSION}-%{RELEASE}"} %{?_unique_debug_names:--unique-debug-arch "%{_arch}"} %{?_unique_debug_srcs:--unique-debug-src-base "%{name}"} %{?_find_debuginfo_dwz_opts} %{?_find_debuginfo_opts} "%{_builddir}/%{?buildsubdir}"\ -+ %{_rpmconfigdir}/find-debuginfo.sh \\\ -+ %{?_smp_mflags} \\\ -+ %{?_missing_build_ids_terminate_build:--strict-build-id} \\\ -+ %{?_no_recompute_build_ids:-n} \\\ -+ %{?_include_minidebuginfo:-m} \\\ -+ %{?_include_gdb_index:-i} \\\ -+ %{?_unique_build_ids:--build-id-seed "%{VERSION}-%{RELEASE}"} \\\ -+ %{?_unique_debug_names:--unique-debug-suffix "-%{VERSION}-%{RELEASE}.%{_arch}"} \\\ -+ %{?_unique_debug_srcs:--unique-debug-src-base "%{name}-%{VERSION}-%{RELEASE}.%{_arch}"} \\\ -+ %{?_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 8effac8..1ebc159 100755 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -6,7 +6,7 @@ - # [-o debugfiles.list] - # [--run-dwz] [--dwz-low-mem-die-limit N] - # [--dwz-max-die-limit N] --# [--ver-rel VERSION-RELEASE] -+# [--build-id-seed VERSION-RELEASE] - # [[-l filelist]... [-p 'pattern'] -o debuginfo.list] - # [builddir] - # -@@ -30,7 +30,7 @@ - # 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 -+# If --build-id-seed 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 -@@ -65,11 +65,11 @@ run_dwz=false - dwz_low_mem_die_limit= - dwz_max_die_limit= - --# Version and release of the spec. Given by --ver-rel --ver_rel= -+# build id seed given by the --build-id-seed option -+build_id_seed= - - # Arch given by --unique-debug-arch --unique_debug_arch= -+unique_debug_suffix= - - # Base given by --unique-debug-src-base - unique_debug_src_base= -@@ -96,12 +96,12 @@ while [ $# -gt 0 ]; do - dwz_max_die_limit=$2 - shift - ;; -- --ver-rel) -- ver_rel=$2 -+ --build-id-seed) -+ build_id_seed=$2 - shift - ;; -- --unique-debug-arch) -- unique_debug_arch=$2 -+ --unique-debug-suffix) -+ unique_debug_suffix=$2 - shift - ;; - --unique-debug-src-base) -@@ -156,18 +156,8 @@ while [ $# -gt 0 ]; do - shift - done - --if test -z "$ver_rel" -a -n "$unique_debug_arch"; then -- echo >&2 "*** ERROR: --unique-debug-arch (${unique_debug_arch}) needs --ver-rel (${ver_rel})" -- exit 2 --fi -- --if test -z "$unique_debug_arch" -a -n "$unique_debug_src_base"; then -- echo >&2 "*** ERROR: --unique-debug-src-base (${unique_debug_src_base}) needs --unique-debug-arch (${unique_debug_arch})" -- exit 2 --fi -- --if test -n "$ver_rel" -a "$no_recompute_build_id" = "true"; then -- echo >&2 "*** ERROR: --ver-rel (unique build-ids) and -n (do not recompute build-id cannot be used together" -+if test -n "$build_id_seed" -a "$no_recompute_build_id" = "true"; then -+ echo >&2 "*** ERROR: --build-id-seed (unique build-ids) and -n (do not recompute build-id) cannot be used together" - exit 2 - fi - -@@ -278,12 +268,7 @@ debug_link() - get_debugfn() - { - dn=$(dirname "${1#$RPM_BUILD_ROOT}") -- if test -n "${unique_debug_arch}"; then -- bn=$(basename "$1" .debug)-${ver_rel}.${unique_debug_arch}.debug -- else -- bn=$(basename "$1" .debug).debug -- fi -- -+ bn=$(basename "$1" .debug)${unique_debug_suffix}.debug - debugdn=${debugdir}${dn} - debugfn=${debugdn}/${bn} - } -@@ -310,23 +310,21 @@ - [ -f "${debugfn}" ] && return - - echo "extracting debug info from $f" -- build_id_seed= -- if [ ! -z "$ver_rel" ]; then -- build_id_seed="--build-id-seed=$ver_rel" -- fi - # See also cpio SOURCEFILE copy. Directories must match up. - debug_base_name="$RPM_BUILD_DIR" - debug_dest_name="/usr/src/debug" - if [ ! -z "$unique_debug_src_base" ]; then - debug_base_name="$BUILDDIR" -- debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" -+ debug_dest_name="/usr/src/debug/${unique_debug_src_base}" - fi - no_recompute= - if [ "$no_recompute_build_id" = "true" ]; then - no_recompute="-n" - fi -- id=$(${lib_rpm_dir}/debugedit -b $debug_base_name -d $debug_dest_name \ -- $no_recompute -i $build_id_seed -l "$SOURCEFILE" "$f") || exit -+ id=$(${lib_rpm_dir}/debugedit -b "$debug_base_name" -d "$debug_dest_name" \ -+ $no_recompute -i \ -+ ${build_id_seed:+--build-id-seed="$build_id_seed"} \ -+ -l "$SOURCEFILE" "$f") || exit - if [ -z "$id" ]; then - echo >&2 "*** ${strict_error}: No build ID note found in $f" - $strict && exit 2 -@@ -509,7 +492,7 @@ if [ -s "$SOURCEFILE" ]; then - debug_dest_name="/usr/src/debug" - if [ ! -z "$unique_debug_src_base" ]; then - debug_base_name="$BUILDDIR" -- debug_dest_name="/usr/src/debug/${unique_debug_src_base}-${ver_rel}.${unique_debug_arch}" -+ debug_dest_name="/usr/src/debug/${unique_debug_src_base}" - fi - - mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" diff --git a/rpm-4.13.0-python-rpmsign.patch b/rpm-4.13.0-python-rpmsign.patch deleted file mode 100644 index 3e535b6..0000000 --- a/rpm-4.13.0-python-rpmsign.patch +++ /dev/null @@ -1,22 +0,0 @@ -From eb632e5158fa4ef993b0e5df2a354f0be7a7a71d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Nikola=20Forr=C3=B3?= -Date: Wed, 20 Apr 2016 15:39:36 +0200 -Subject: [PATCH] Use correct source file for rpmsign module - ---- - python/setup.py.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/python/setup.py.in b/python/setup.py.in -index b2c394136..f94873fe5 100644 ---- a/python/setup.py.in -+++ b/python/setup.py.in -@@ -48,7 +48,7 @@ rpmbuild_mod = Extension('rpm._rpmb', - ) - - rpmsign_mod = Extension('rpm._rpms', -- sources = ['rpmbmodule.c'], -+ sources = ['rpmsmodule.c'], - include_dirs = pkgconfig('--cflags'), - libraries = pkgconfig('--libs') + ['rpmsign'], - extra_compile_args = cflags, diff --git a/rpm-4.13.x-brp-python-bytecompile-Python3-only.patch b/rpm-4.13.x-brp-python-bytecompile-Python3-only.patch deleted file mode 100644 index 56bc857..0000000 --- a/rpm-4.13.x-brp-python-bytecompile-Python3-only.patch +++ /dev/null @@ -1,49 +0,0 @@ -From a8e51b3bb05c6acb1d9b2e3d34f859ddda1677be Mon Sep 17 00:00:00 2001 -From: Florian Festi -Date: Tue, 14 Feb 2017 14:04:35 +0100 -Subject: [PATCH] brp-python-bytecompile: Process python lib dirs even without - standard Python - -There is no need for /usr/bin/python when byte compiling files in -/usr/lib/pythonX.Y (only /usr/bin/pythonX.Y). Moved check so we do not exit -prematurely. - -Fixes: rhbz#1411588 ---- - scripts/brp-python-bytecompile | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/scripts/brp-python-bytecompile b/scripts/brp-python-bytecompile -index 838f23d..894fa34 100644 ---- a/scripts/brp-python-bytecompile -+++ b/scripts/brp-python-bytecompile -@@ -6,12 +6,6 @@ if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then - exit 0 - fi - --# If we don't have a python interpreter, avoid changing anything. --default_python=${1:-/usr/bin/python} --if [ ! -x "$default_python" ]; then -- exit 0 --fi -- - # Figure out how deep we need to descend. We could pick an insanely high - # number and hope it's enough, but somewhere, somebody's sure to run into it. - depth=`(find "$RPM_BUILD_ROOT" -type f -name "*.py" -print0 ; echo /) | \ -@@ -86,7 +80,12 @@ done - - - # Handle other locations in the filesystem using the default python --# implementation: -+# implementation - if we have a default python interpreter -+ -+default_python=${1:-/usr/bin/python} -+if [ ! -x "$default_python" ]; then -+ exit 0 -+fi - - # Generate normal (.pyc) byte-compiled files. - python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/" --- -2.5.5 - diff --git a/rpm-4.13.x-fix-refcount-for-spec_type.patch b/rpm-4.13.x-fix-refcount-for-spec_type.patch deleted file mode 100644 index 4d8a460..0000000 --- a/rpm-4.13.x-fix-refcount-for-spec_type.patch +++ /dev/null @@ -1,79 +0,0 @@ -From aaf691dbc85295aeb09e1ea4081089a24dc28759 Mon Sep 17 00:00:00 2001 -From: Pavlina Moravcova Varekova -Date: Tue, 21 Feb 2017 11:37:20 +0100 -Subject: [PATCH] Fix number of references on spec_Type (#114) - -After creating a specPkg from a spec file we must increase spec file reference counter. Otherwise spec file may be accidentally deallocated and usage of SpecPkg can cause an error. ---- - python/spec-py.c | 14 +++++++++++--- - python/spec-py.h | 2 +- - 2 files changed, 12 insertions(+), 4 deletions(-) - -diff --git a/python/spec-py.c b/python/spec-py.c -index f710f5c..753afba 100644 ---- a/python/spec-py.c -+++ b/python/spec-py.c -@@ -45,8 +45,14 @@ struct specPkgObject_s { - PyObject_HEAD - /*type specific fields */ - rpmSpecPkg pkg; -+ specObject *source_spec; - }; - -+static void specPkg_dealloc(specPkgObject * s) -+{ -+ Py_DECREF(s->source_spec); -+} -+ - static PyObject *pkgGetSection(rpmSpecPkg pkg, int section) - { - char *sect = rpmSpecPkgGetSection(pkg, section); -@@ -95,7 +101,7 @@ PyTypeObject specPkg_Type = { - "rpm.specpkg", /* tp_name */ - sizeof(specPkgObject), /* tp_size */ - 0, /* tp_itemsize */ -- 0, /* tp_dealloc */ -+ (destructor) specPkg_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ -@@ -227,7 +233,7 @@ static PyObject * spec_get_packages(specObject *s, void *closure) - iter = rpmSpecPkgIterInit(s->spec); - - while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) { -- PyObject *po = specPkg_Wrap(&specPkg_Type, pkg); -+ PyObject *po = specPkg_Wrap(&specPkg_Type, pkg, s); - if (!po) { - rpmSpecPkgIterFree(iter); - Py_DECREF(pkgList); -@@ -350,12 +356,14 @@ spec_Wrap(PyTypeObject *subtype, rpmSpec spec) - return (PyObject *) s; - } - --PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg) -+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source) - { - specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0); - if (s == NULL) return NULL; - - s->pkg = pkg; -+ s->source_spec = source; -+ Py_INCREF(s->source_spec); - return (PyObject *) s; - } - -diff --git a/python/spec-py.h b/python/spec-py.h -index 558fbf2..65b8dc3 100644 ---- a/python/spec-py.h -+++ b/python/spec-py.h -@@ -13,6 +13,6 @@ extern PyTypeObject specPkg_Type; - #define specPkgObject_Check(v) ((v)->ob_type == &specPkg_Type) - - PyObject * spec_Wrap(PyTypeObject *subtype, rpmSpec spec); --PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg); -+PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg, specObject *source); - - #endif /* RPMPYTHON_SPEC */ --- -2.7.4 - diff --git a/rpm-4.13.x-writable-tmp-dir.patch b/rpm-4.13.x-writable-tmp-dir.patch deleted file mode 100644 index f2dda3f..0000000 --- a/rpm-4.13.x-writable-tmp-dir.patch +++ /dev/null @@ -1,107 +0,0 @@ -commit c707ab26362e795d3f9dba4eb87dc7ed99a28bcb -Author: Robin Lee -Date: Sat Apr 8 21:21:39 2017 +0800 - - Fix non-standard inherented modes of directories in debuginfo - - In case that binary compiled from source generated in /tmp, a - /usr/src/debug/tmp directory will be created with the same mode as - /tmp, a.k.a 777, which should be avoided. - - Fixes: rhbz#641022 - -diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh -old mode 100644 -new mode 100755 -index 547dbd9..6f38e19 ---- a/scripts/find-debuginfo.sh -+++ b/scripts/find-debuginfo.sh -@@ -490,9 +490,10 @@ if [ -s "$SOURCEFILE" ]; then - mkdir -p "${RPM_BUILD_ROOT}${debug_dest_name}" - LC_ALL=C sort -z -u "$SOURCEFILE" | grep -E -v -z '(|)$' | - (cd "${debug_base_name}"; cpio -pd0mL "${RPM_BUILD_ROOT}${debug_dest_name}") -- # stupid cpio creates new directories in mode 0700, fixup -+ # stupid cpio creates new directories in mode 0700, -+ # and non-standard modes may be inherented from original directories, fixup - find "${RPM_BUILD_ROOT}${debug_dest_name}" -type d -print0 | -- xargs --no-run-if-empty -0 chmod a+rx -+ xargs --no-run-if-empty -0 chmod 0755 - fi - - if [ -d "${RPM_BUILD_ROOT}/usr/lib" -o -d "${RPM_BUILD_ROOT}/usr/src" ]; then - -commit e795899780337dea751d85db8f381eff3fe75275 -Author: Mark Wielaard -Date: Fri Apr 21 17:33:26 2017 +0200 - - debugedit: Only output comp_dir under build dir (once). - - The fix for rhbz#444310 (commit c1a5eb - Include empty CU current dirs) - was a little greedy. It would also include comp_dirs outside the build - root. Those are unnecessary and we don't have a good way to store them. - Such dirs (e.g. /tmp) would then show up at the root of /usr/src/debug. - - Fix this by including only comp_dirs under base_dir. Also only output - all dirs once (during phase zero) and don't output empty dirs (which - was harmless but would produce a warning from cpio). - - This still includes all empty dirs from the original rhbz#444310 - nodir testcase and it is an alternative fix for rhbz#641022 - (commit c707ab). - - Both fixes are necessary in case of an unexpected mode for a directory - actually in the build root that we want to include in the source list. - - Signed-off-by: Mark Wielaard - -diff --git a/tools/debugedit.c b/tools/debugedit.c -index 8444e03..bf11513 100644 ---- a/tools/debugedit.c -+++ b/tools/debugedit.c -@@ -1680,30 +1680,23 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) - /* Ensure the CU current directory will exist even if only empty. Source - filenames possibly located in its parent directories refer relatively to - it and the debugger (GDB) cannot safely optimize out the missing -- CU current dir subdirectories. */ -- if (comp_dir && list_file_fd != -1) -+ CU current dir subdirectories. Only do this once in phase one. And -+ only do this for dirs under our build/base_dir. Don't output the -+ empty string (in case the comp_dir == base_dir). */ -+ if (phase == 0 && base_dir && comp_dir && list_file_fd != -1) - { -- const char *p = NULL; -- size_t size; -- -- if (base_dir) -- { -- p = skip_dir_prefix (comp_dir, base_dir); -- if (p == NULL && dest_dir != NULL) -- p = skip_dir_prefix (comp_dir, dest_dir); -- } -- -- if (p == NULL) -- p = comp_dir; -- -- size = strlen (p) + 1; -- while (size > 0) -- { -- ssize_t ret = write (list_file_fd, p, size); -- if (ret == -1) -- break; -- size -= ret; -- p += ret; -+ const char *p = skip_dir_prefix (comp_dir, base_dir); -+ if (p != NULL && p[0] != '\0') -+ { -+ size_t size = strlen (p) + 1; -+ while (size > 0) -+ { -+ ssize_t ret = write (list_file_fd, p, size); -+ if (ret == -1) -+ break; -+ size -= ret; -+ p += ret; -+ } - } - } - diff --git a/rpm.spec b/rpm.spec index b0c7533..03e728c 100644 --- a/rpm.spec +++ b/rpm.spec @@ -56,74 +56,79 @@ Patch4: rpm-4.8.1-use-gpg2.patch Patch5: rpm-4.12.0-rpm2cpio-hack.patch # Patches already upstream: -Patch100: rpm-4.13.0-python-rpmsign.patch +# All patches are tracked on https://pagure.io/rpm-fedora +Patch100: 0001-Use-correct-source-file-for-rpmsign-module.patch -Patch140: rpm-4.13.x-brp-python-bytecompile-Python3-only.patch -Patch142: rpm-4.13.x-fix-refcount-for-spec_type.patch +Patch140: 0002-brp-python-bytecompile-Process-python-lib-dirs-even-.patch +Patch142: 0003-Fix-number-of-references-on-spec_Type-114.patch # debuginfo backports (#1427970) -Patch250: 0001-Add-build-id-links-to-rpm-for-all-ELF-files.patch -Patch251: 0002-Make-it-possible-to-have-unique-build-ids-across-bui.patch -Patch252: 0003-Make-adding-GDB-index-sections-configurable.patch -Patch253: 0004-Add-option-to-have-unique-debug-file-names-across-ve.patch -Patch254: 0005-Fix-behavior-when-_build_id_links-is-undefined.patch -Patch255: 0006-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch -Patch256: 0007-Only-process-regular-files-when-generating-build-ids.patch -Patch257: 0008-configure.ac-use-LIBDW-always-conditionally.patch -Patch258: 0009-Fix-libdw-configure-check.patch -Patch259: 0010-debugedit-Support-String-Line-table-rewriting-for-la.patch -Patch260: 0011-Add-option-to-have-unique-debug-source-dirs-across-v.patch +Patch250: 0004-Add-build-id-links-to-rpm-for-all-ELF-files.patch +Patch251: 0005-Make-it-possible-to-have-unique-build-ids-across-bui.patch +Patch252: 0006-Make-adding-GDB-index-sections-configurable.patch +Patch253: 0007-Add-option-to-have-unique-debug-file-names-across-ve.patch +Patch254: 0008-Fix-behavior-when-_build_id_links-is-undefined.patch +Patch255: 0009-Fix-debuginfo-etc-when-subpackages-have-different-ve.patch +Patch256: 0010-Only-process-regular-files-when-generating-build-ids.patch +Patch257: 0011-configure.ac-use-LIBDW-always-conditionally.patch +Patch258: 0012-Fix-libdw-configure-check.patch +Patch259: 0013-debugedit-Support-String-Line-table-rewriting-for-la.patch +Patch260: 0014-Add-option-to-have-unique-debug-source-dirs-across-v.patch # debuginfo build-id warn/error fix (#1430587) -Patch261: 0012-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch -Patch262: 0013-missing_build_ids_terminate_build.patch -Patch263: 0014-generateBuildIDs-Fix-error-handling.patch -Patch264: 0015-reset-buildid-file-attrs.patch -Patch265: 0016-debugedit-replace-files.patch -Patch266: 0017-do-not-process-buildi-ds-for-noarch.patch -Patch267: 0018-update-build-id-endian.patch -Patch268: 0019-fix-sed-build-id-match-test.patch -Patch269: 0020-build-files-exec-build-id.patch -Patch270: 0021-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch -Patch271: 0022-unbreak-short-circuit.patch -Patch272: 0023-minisymtab-exe-sh.patch -Patch273: 0024-no-recompute-build-id.patch -Patch274: 0025-buildid-reset-attrs.patch +Patch261: 0015-generateBuildIDs-Don-t-warn-or-error-for-object-file.patch +Patch262: 0016-build-files.c-Unset-__debug_package-implies-missing-.patch +Patch263: 0017-generateBuildIDs-Fix-error-handling.patch +Patch264: 0018-Make-sure-to-reset-file-attributes-for-generated-bui.patch +Patch265: 0019-rpmbuild-Reset-attrFlags-in-generateBuildIDs.patch +Patch266: 0020-debugedit-Fix-edit_dwarf2_line-replace_dirs-replace_.patch +Patch267: 0021-build-files.c-processPackageFiles-Don-t-call-generat.patch +Patch268: 0022-debugedit-Fix-cross-endian-build-id-reading-and-upda.patch +Patch269: 0023-tests-tpmbuild.at-Make-file-sed-regexp-more-strict-t.patch +Patch270: 0024-tests-rpmbuildid.at-Make-file-sed-regexp-more-strict.patch +Patch271: 0025-build-files.c-Only-check-build-ids-for-executable-fi.patch +Patch272: 0026-debugedit-Fix-off-by-one-adding-DW_FORM_string-repla.patch +Patch273: 0027-Unbreak-short-circuited-binary-builds.patch +Patch274: 0028-find-debuginfo.sh-Only-add-minisymtab-for-executable.patch +Patch275: 0029-debugedit-Add-n-no-recompute-build-id.patch +Patch276: 0030-Fix-non-standard-inherented-modes-of-directories-in-.patch # World writable empty (tmp) dirs in debuginfo packages (#641022) -Patch280: rpm-4.13.x-writable-tmp-dir.patch +Patch280: 0031-debugedit-Only-output-comp_dir-under-build-dir-once.patch # Parallel debuginfo processing -Patch281: find-debuginfo-split-traversal-and-extraction.patch -Patch282: find-debuginfo-split-traversal-and-extraction-fix.patch -Patch283: find-debuginfo-process-files-in-parallel.patch +Patch281: 0032-find-debuginfo.sh-Split-directory-traversal-and-debu.patch +Patch282: 0033-find-debuginfo.sh-Use-return-not-continue-to-break-o.patch +Patch283: 0034-find-debuginfo.sh-Process-files-in-parallel.patch # Support debugsource and debuginfo subpackages -Patch285: find-debuginfo-untangle-unique-build-options.patch -Patch286: debugsrc-and-sub-debuginfo-packages.patch +Patch284: 0035-Untangle-unique-build-options-in-find-debuginfo.sh.patch +Patch285: 0036-Support-debugsource-subpackages.patch +Patch286: 0037-Support-debuginfo-subpackages.patch +Patch287: 0038-Also-add-directories-to-split-debuginfo-packages.patch # debugedit check prefix match ends with slash. -Patch290: debugedit-prefix.patch +Patch290: 0039-debugedit-skip_dir_prefix-should-check-for-dir-separ.patch # find-debuginfo.sh: Filter out all like fake file names. -Patch291: find-debuginfo-filter-built-ins.patch +Patch291: 0040-find-debuginfo.sh-Filter-out-all-built-in-like-fake-.patch # Don't create dwz multi file if there is only one .debug. -Patch292: find-debuginfo-dwz-multi.patch +Patch292: 0041-find-debuginfo.sh-Don-t-create-dwz-multi-file-if-the.patch # Update find-debuginfo.sh options and macros documentation. -Patch293: find-debuginfo-and-macro-docs.patch +Patch293: 0042-Update-find-debuginfo.sh-options-and-macros-document.patch # OpenSSL backend -Patch300: 0001-Add-OpenSSL-support-for-digest-and-signatures.patch +Patch300: 0043-Add-OpenSSL-support-for-digest-and-signatures.patch # Rich dependencies coming from dependency generatos -Patch310: 0001-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch -Patch311: 0002-Fix-check-for-weak-deps-in-external-dependency-gener.patch -Patch312: 0003-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch -Patch313: 0004-Re-enable-rich-dependecies-for-build-requires-and-co.patch -Patch314: 0005-add-support-for-rich-dependencies-from-dependency-ge.patch -Patch315: 0006-Pass-proper-file-index-when-recording-generated-depe.patch +Patch310: 0044-Use-RPMTAG_-NAME-instead-of-RPMTAG_-FLAGS-in-parsePr.patch +Patch311: 0045-Fix-check-for-weak-deps-in-external-dependency-gener.patch +Patch312: 0046-Fix-check-whether-to-allow-rich-deps-in-a-given-tag.patch +Patch313: 0047-Re-enable-rich-dependecies-for-build-requires-and-co.patch +Patch314: 0048-add-support-for-rich-dependencies-from-dependency-ge.patch +Patch315: 0049-Pass-proper-file-index-when-recording-generated-depe.patch # These are not yet upstream Patch902: rpm-4.7.1-geode-i686.patch