Subject: bug#38055: none

From: Ivan Vilata i Balaguer <[email-masked]>
Date: Mon, 11 Nov 2019 10:30:30 -0500

Ivan Vilata i Balaguer (2019-11-11 10:10:10 -0500) wrote:

> […] I'm still attaching it in case you're curious (of course I don't expect
> any of it to get merged `;)`). […]

Forgot the attachment… `:P`

-- 
Ivan Vilata i Balaguer -- https://elvil.net/
>From 2e4cca87b865dbd26ee417775d543abab7ba4f53 Mon Sep 17 00:00:00 2001
From: Ivan Vilata-i-Balaguer <[email-masked]>
Date: Fri, 8 Nov 2019 13:59:53 -0500
Subject: [PATCH] gnu: patchelf: Update to 0.10.

Besides the update, the patches for "page size" and "rework for ARM" were
removed since they can no longer be applied to upstream source.

Also, the "no-rpath.sh" test was skipped since it would fail under Guix, see
<https://issues.guix.gnu.org/issue/38055>.

* gnu/packages/elf.scm (patchelf): Update to 0.10.
* gnu/packages/patches/patchelf-page-size.patch: Delete file.
* gnu/packages/patches/patchelf-rework-for-arm.patch: Delete file.
* gnu/packages/patches/patchelf-skip-no-rpath-test.patch: New file.
---
 gnu/packages/elf.scm                          |  25 +-
 gnu/packages/patches/patchelf-page-size.patch |  70 ---
 .../patches/patchelf-rework-for-arm.patch     | 473 ------------------
 .../patches/patchelf-skip-no-rpath-test.patch |  18 +
 4 files changed, 21 insertions(+), 565 deletions(-)
 delete mode 100644 gnu/packages/patches/patchelf-page-size.patch
 delete mode 100644 gnu/packages/patches/patchelf-rework-for-arm.patch
 create mode 100644 gnu/packages/patches/patchelf-skip-no-rpath-test.patch

diff --git a/gnu/packages/elf.scm b/gnu/packages/elf.scm
index 4f365cf205..28bdcedcd2 100644
--- a/gnu/packages/elf.scm
+++ b/gnu/packages/elf.scm
@@ -198,7 +198,7 @@ static analysis of the ELF binaries at hand.")
 (define-public patchelf
   (package
     (name "patchelf")
-    (version "0.8")
+    (version "0.10")
     (source (origin
              (method url-fetch)
              (uri (string-append
@@ -207,28 +207,9 @@ static analysis of the ELF binaries at hand.")
                    "/patchelf-" version ".tar.bz2"))
              (sha256
               (base32
-               "1rqpg84wrd3fa16wa9vqdvasnc05yz49w207cz1l0wrl4k8q97y9"))
-             (patches (search-patches "patchelf-page-size.patch"))))
+               "1wzwvnlyf853hw9zgqq5522bvf8gqadk8icgqa41a5n7593csw7n"))
+             (patches (search-patches "patchelf-skip-no-rpath-test.patch"))))
     (build-system gnu-build-system)
-
-    ;; XXX: The upstream 'patchelf' doesn't support ARM.  The only available
-    ;;      patch makes significant changes to the algorithm, possibly
-    ;;      introducing bugs.  So, we apply the patch only on ARM systems.
-    (inputs
-     (if (target-arm32?)
-         `(("patch/rework-for-arm" ,(search-patch
-                                     "patchelf-rework-for-arm.patch")))
-         '()))
-    (arguments
-     (if (target-arm32?)
-         `(#:phases
-           (modify-phases %standard-phases
-             (add-after 'unpack 'patch/rework-for-arm
-               (lambda* (#:key inputs #:allow-other-keys)
-                 (let ((patch-file (assoc-ref inputs "patch/rework-for-arm")))
-                   (invoke "patch" "--force" "-p1" "--input" patch-file))))))
-         '()))
-
     (home-page "https://nixos.org/patchelf.html")
     (synopsis "Modify the dynamic linker and RPATH of ELF executables")
     (description
diff --git a/gnu/packages/patches/patchelf-page-size.patch b/gnu/packages/patches/patchelf-page-size.patch
deleted file mode 100644
index 1c14047512..0000000000
--- a/gnu/packages/patches/patchelf-page-size.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-Improve the determination of pageSize in patchelf.cc.
-
-Patch by Mark H Weaver <[email-masked]>.
-
---- patchelf/src/patchelf.cc.orig	1969-12-31 19:00:01.000000000 -0500
-+++ patchelf/src/patchelf.cc	2014-02-16 20:15:06.283203125 -0500
-@@ -21,11 +21,19 @@
- using namespace std;
- 
- 
--#ifdef MIPSEL
--/* The lemote fuloong 2f kernel defconfig sets a page size of 16KB */
--const unsigned int pageSize = 4096*4;
--#else
-+/* Note that some platforms support multiple page sizes.  Therefore,
-+   it is not enough to query the current page size.  'pageSize' must
-+   be the maximum architectural page size for the platform, which is
-+   typically defined in the corresponding ABI document.
-+
-+   XXX FIXME: This won't work when we're cross-compiling.  */
-+
-+#if defined __MIPSEL__ || defined __MIPSEB__ || defined __aarch64__
-+const unsigned int pageSize = 65536;
-+#elif defined __x86_64__ || defined __i386__ || defined __arm__
- const unsigned int pageSize = 4096;
-+#else
-+# error maximum architectural page size unknown for this platform
- #endif
- 
- 
---- patchelf/tests/no-rpath.sh.orig	2014-01-14 08:17:47.000000000 -0500
-+++ patchelf/tests/no-rpath.sh	2015-01-06 18:31:53.418172797 -0500
-@@ -1,23 +1,23 @@
- #! /bin/sh -e
- SCRATCH=scratch/$(basename $0 .sh)
- 
--rm -rf ${SCRATCH}
--mkdir -p ${SCRATCH}
-+if [ "$(uname -m)" = i686 -a "$(uname -s)" = Linux ]; then
-+    rm -rf ${SCRATCH}
-+    mkdir -p ${SCRATCH}
- 
--cp ${srcdir}/no-rpath ${SCRATCH}/
-+    cp ${srcdir}/no-rpath ${SCRATCH}/
- 
--oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath)
--if test -n "$oldRPath"; then exit 1; fi
--../src/patchelf \
--  --set-interpreter "$(../src/patchelf --print-interpreter ../src/patchelf)" \
--  --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath
-+    oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath)
-+    if test -n "$oldRPath"; then exit 1; fi
-+    ../src/patchelf \
-+      --set-interpreter "$(../src/patchelf --print-interpreter ../src/patchelf)" \
-+      --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath
- 
--newRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath)
--if ! echo "$newRPath" | grep -q '/foo:/bar'; then
--    echo "incomplete RPATH"
--    exit 1
--fi
-+    newRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath)
-+    if ! echo "$newRPath" | grep -q '/foo:/bar'; then
-+        echo "incomplete RPATH"
-+        exit 1
-+    fi
- 
--if [ "$(uname -m)" = i686 -a "$(uname -s)" = Linux ]; then
-     cd ${SCRATCH} && ./no-rpath
- fi
diff --git a/gnu/packages/patches/patchelf-rework-for-arm.patch b/gnu/packages/patches/patchelf-rework-for-arm.patch
deleted file mode 100644
index 6f4eb8f72b..0000000000
--- a/gnu/packages/patches/patchelf-rework-for-arm.patch
+++ /dev/null
@@ -1,473 +0,0 @@
-Rework the growing algorithm in patchelf to support ARM systems.
-See <https://github.com/NixOS/patchelf/issues/8>.
-This patch copied from:
-<https://github.com/sriemer/patchelf/commit/0a96239cea6b97b9a0fff80da576e58ca2dfb2a2>
-
-From 0a96239cea6b97b9a0fff80da576e58ca2dfb2a2 Mon Sep 17 00:00:00 2001
-From: Sebastian Parschauer <[email-masked]>
-Date: Sat, 28 Jun 2014 01:24:57 +0200
-Subject: [PATCH] Rework the growing algorithm
-
-On ARM systems there is no space in virtual memory for another LOAD
-area in front of the code LOAD area. So insert data to its end
-instead. At this location there should be enough space in virtual
-memory due to alignment. We can extend it until the end of the
-alignment but the file shift may be greater as it must be aligned
-to the page size. Do the same for the data LOAD area.
----
- src/patchelf.cc | 357 ++++++++++++++++++++++----------------------------------
- 1 file changed, 142 insertions(+), 215 deletions(-)
-
-diff --git a/src/patchelf.cc b/src/patchelf.cc
-index dcbfd38..4fce9e6 100644
---- a/src/patchelf.cc
-+++ b/src/patchelf.cc
-@@ -116,7 +116,11 @@ private:
- 
-     void sortShdrs();
- 
--    void shiftFile(unsigned int extraPages, Elf_Addr startPage);
-+    void shiftFileSingle(size_t fileShift, Elf_Off insertOff);
-+
-+    void shiftFile(size_t neededCode, size_t neededData,
-+                   Elf_Off codeOff[], Elf_Off dataOff[],
-+                   Elf_Addr *codePage, Elf_Addr *dataPage);
- 
-     string getSectionName(const Elf_Shdr & shdr);
- 
-@@ -130,13 +134,11 @@ private:
-         unsigned int size);
- 
-     void writeReplacedSections(Elf_Off & curOff,
--        Elf_Addr startAddr, Elf_Off startOffset);
-+        Elf_Addr startAddr, Elf_Off startOffset, bool isData);
- 
-     void rewriteHeaders(Elf_Addr phdrAddress);
- 
--    void rewriteSectionsLibrary();
--
--    void rewriteSectionsExecutable();
-+    void rewriteSectionsBinary();
- 
- public:
- 
-@@ -391,46 +393,119 @@ static unsigned int roundUp(unsigned int n, unsigned int m)
- 
- 
- template<ElfFileParams>
--void ElfFile<ElfFileParamNames>::shiftFile(unsigned int extraPages, Elf_Addr startPage)
-+void ElfFile<ElfFileParamNames>::shiftFileSingle(size_t fileShift,
-+        Elf_Off insertOff)
- {
--    /* Move the entire contents of the file `extraPages' pages
--       further. */
-     unsigned int oldSize = fileSize;
--    unsigned int shift = extraPages * pageSize;
--    growFile(fileSize + extraPages * pageSize);
--    memmove(contents + extraPages * pageSize, contents, oldSize);
--    memset(contents + sizeof(Elf_Ehdr), 0, shift - sizeof(Elf_Ehdr));
-+
-+    /* Grow at the end */
-+    growFile(fileSize + fileShift);
-+
-+    /* move the data from the insertion point
-+       to the end and zero inserted space */
-+    memmove(contents + insertOff + fileShift,
-+            contents + insertOff, oldSize - insertOff);
-+    memset(contents + insertOff, 0, fileShift);
- 
-     /* Adjust the ELF header. */
-     wri(hdr->e_phoff, sizeof(Elf_Ehdr));
--    wri(hdr->e_shoff, rdi(hdr->e_shoff) + shift);
-+    if (rdi(hdr->e_shoff) >= insertOff)
-+        wri(hdr->e_shoff, rdi(hdr->e_shoff) + fileShift);
- 
-     /* Update the offsets in the section headers. */
--    for (int i = 1; i < rdi(hdr->e_shnum); ++i)
--        wri(shdrs[i].sh_offset, rdi(shdrs[i].sh_offset) + shift);
-+    for (int i = 1; i < rdi(hdr->e_shnum); ++i) {
-+        if (rdi(shdrs[i].sh_offset) >= insertOff)
-+            wri(shdrs[i].sh_offset, rdi(shdrs[i].sh_offset) + fileShift);
-+    }
- 
-     /* Update the offsets in the program headers. */
-     for (int i = 0; i < rdi(hdr->e_phnum); ++i) {
--        wri(phdrs[i].p_offset, rdi(phdrs[i].p_offset) + shift);
--        if (rdi(phdrs[i].p_align) != 0 &&
--            (rdi(phdrs[i].p_vaddr) - rdi(phdrs[i].p_offset)) % rdi(phdrs[i].p_align) != 0) {
--            debug("changing alignment of program header %d from %d to %d\n", i,
--                rdi(phdrs[i].p_align), pageSize);
--            wri(phdrs[i].p_align, pageSize);
-+        if (rdi(phdrs[i].p_offset) >= insertOff)
-+            wri(phdrs[i].p_offset, rdi(phdrs[i].p_offset) + fileShift);
-+        /* Check for ELF load command alignment issue the same
-+           way as glibc/elf/dl-load.c does. This gives us the
-+           chance to run an interpreter explicitly. */
-+        if (rdi(phdrs[i].p_type) == PT_LOAD && ((rdi(phdrs[i].p_vaddr) -
-+          rdi(phdrs[i].p_offset)) & (rdi(phdrs[i].p_align) - 1)) != 0) {
-+             debug("changing alignment of program header %d from %d to %d\n",
-+                   i, rdi(phdrs[i].p_align), pageSize);
-+             wri(phdrs[i].p_align, pageSize);
-         }
-     }
-+}
-+
-+template<ElfFileParams>
-+void ElfFile<ElfFileParamNames>::shiftFile(size_t neededCode,
-+        size_t neededData, Elf_Off codeOff[], Elf_Off dataOff[],
-+        Elf_Addr *codePage, Elf_Addr *dataPage)
-+{
-+    /* Move some contents of the file further. The binary has one LOAD area
-+     * for code and one for data. There is virtual memory space between
-+     * these which we can use due to alignment.
-+     */
-+    unsigned int memShift = neededCode;
-+    unsigned int fileShift = roundUp(neededCode, pageSize);
-+    unsigned int maxMemShift = 0;
-+
-+    if (neededCode > 0) {
-+        /* find the LOAD program header for code and extend it */
-+        for (int i = 0; i < rdi(hdr->e_phnum); ++i) {
-+            if (rdi(phdrs[i].p_type) == PT_LOAD &&
-+              rdi(phdrs[i].p_flags) & PF_X) {
-+                codeOff[1] = rdi(phdrs[i].p_filesz);
-+                codeOff[0] = codeOff[1] + rdi(phdrs[i].p_offset);
-+                maxMemShift = rdi(phdrs[i].p_memsz) % rdi(phdrs[i].p_align);
-+                if (maxMemShift == 0)
-+                    continue;
-+                maxMemShift = rdi(phdrs[i].p_align) - maxMemShift;
-+                if (maxMemShift == 0 || memShift > maxMemShift)
-+                    continue;
-+                *codePage = rdi(phdrs[i].p_vaddr);
-+                wri(phdrs[i].p_filesz, rdi(phdrs[i].p_filesz) + memShift);
-+                wri(phdrs[i].p_memsz, rdi(phdrs[i].p_memsz) + memShift);
-+                break;
-+            }
-+        }
-+        debug("codeOff: %#lx, memShift: %d, maxMemShift: %d, fileShift: %d\n",
-+              codeOff[1], memShift, maxMemShift, fileShift);
-+        if (codeOff[1] == 0 || maxMemShift == 0)
-+            goto out;
-+
-+        shiftFileSingle(fileShift, codeOff[0]);
-+    }
-+
-+    /* +++ Do the same for the data LOAD area  +++ */
-+    memShift = neededData;
-+    fileShift = roundUp(neededData, pageSize);
-+    maxMemShift = 0;
-+    if (neededData > 0) {
-+        /* find the LOAD program header for data and extend it */
-+        for (int i = 0; i < rdi(hdr->e_phnum); ++i) {
-+            if (rdi(phdrs[i].p_type) == PT_LOAD &&
-+              rdi(phdrs[i].p_flags) & PF_W) {
-+                dataOff[1] = rdi(phdrs[i].p_filesz);
-+                dataOff[0] = dataOff[1] + rdi(phdrs[i].p_offset);
-+                maxMemShift = rdi(phdrs[i].p_memsz) % rdi(phdrs[i].p_align);
-+                if (maxMemShift == 0)
-+                    continue;
-+                maxMemShift = rdi(phdrs[i].p_align) - maxMemShift;
-+                if (maxMemShift == 0 || memShift > maxMemShift)
-+                    continue;
-+                *dataPage = rdi(phdrs[i].p_vaddr);
-+                wri(phdrs[i].p_filesz, rdi(phdrs[i].p_filesz) + memShift);
-+                wri(phdrs[i].p_memsz, rdi(phdrs[i].p_memsz) + memShift);
-+                break;
-+            }
-+        }
-+        debug("dataOff: %#lx, memShift: %d, maxMemShift: %d, fileShift: %d\n",
-+              dataOff[1], memShift, maxMemShift, fileShift);
-+        if (dataOff[1] == 0 || maxMemShift == 0)
-+            goto out;
- 
--    /* Add a segment that maps the new program/section headers and
--       PT_INTERP segment into memory.  Otherwise glibc will choke. */
--    phdrs.resize(rdi(hdr->e_phnum) + 1);
--    wri(hdr->e_phnum, rdi(hdr->e_phnum) + 1);
--    Elf_Phdr & phdr = phdrs[rdi(hdr->e_phnum) - 1];
--    wri(phdr.p_type, PT_LOAD);
--    wri(phdr.p_offset, 0);
--    wri(phdr.p_vaddr, wri(phdr.p_paddr, startPage));
--    wri(phdr.p_filesz, wri(phdr.p_memsz, shift));
--    wri(phdr.p_flags, PF_R | PF_W);
--    wri(phdr.p_align, pageSize);
-+        shiftFileSingle(fileShift, dataOff[0]);
-+    }
-+out:
-+    return;
- }
- 
- 
-@@ -491,7 +566,7 @@ string & ElfFile<ElfFileParamNames>::replaceSection(const SectionName & sectionN
- 
- template<ElfFileParams>
- void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
--    Elf_Addr startAddr, Elf_Off startOffset)
-+    Elf_Addr startAddr, Elf_Off startOffset, bool isData = false)
- {
-     /* Overwrite the old section contents with 'X's.  Do this
-        *before* writing the new section contents (below) to prevent
-@@ -501,6 +576,9 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
-     {
-         string sectionName = i->first;
-         Elf_Shdr & shdr = findSection(sectionName);
-+        if ((!isData && rdi(shdr.sh_flags) & SHF_WRITE) ||
-+         (isData && ~(rdi(shdr.sh_flags)) & SHF_WRITE))
-+            continue;
-         memset(contents + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
-     }
- 
-@@ -509,6 +587,9 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
-     {
-         string sectionName = i->first;
-         Elf_Shdr & shdr = findSection(sectionName);
-+        if ((!isData && rdi(shdr.sh_flags) & SHF_WRITE) ||
-+         (isData && ~(rdi(shdr.sh_flags)) & SHF_WRITE))
-+            continue;
-         debug("rewriting section `%s' from offset 0x%x (size %d) to offset 0x%x (size %d)\n",
-             sectionName.c_str(), rdi(shdr.sh_offset), rdi(shdr.sh_size), curOff, i->second.size());
- 
-@@ -546,201 +627,47 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
-         curOff += roundUp(i->second.size(), sectionAlignment);
-     }
- 
--    replacedSections.clear();
-+    if (isData)
-+        replacedSections.clear();
- }
- 
- 
- template<ElfFileParams>
--void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
-+void ElfFile<ElfFileParamNames>::rewriteSectionsBinary()
- {
--    /* For dynamic libraries, we just place the replacement sections
--       at the end of the file.  They're mapped into memory by a
--       PT_LOAD segment located directly after the last virtual address
--       page of other segments. */
--    Elf_Addr startPage = 0;
--    for (unsigned int i = 0; i < phdrs.size(); ++i) {
--        Elf_Addr thisPage = roundUp(rdi(phdrs[i].p_vaddr) + rdi(phdrs[i].p_memsz), pageSize);
--        if (thisPage > startPage) startPage = thisPage;
--    }
--
--    debug("last page is 0x%llx\n", (unsigned long long) startPage);
-+    Elf_Off codeOff[2] = {0}, dataOff[2] = {0};
-+    Elf_Addr codePage = 0, dataPage = 0;
-+    size_t neededCode = 0, neededData = 0, oldCode = 0, oldData = 0;
-+    Elf_Shdr shdr = findSection(".text");
-+    Elf_Addr firstPage = rdi(shdr.sh_addr) - rdi(shdr.sh_offset);
- 
-+    debug("first page is 0x%llx\n", (unsigned long long) firstPage);
- 
--    /* Compute the total space needed for the replaced sections and
--       the program headers. */
--    off_t neededSpace = (phdrs.size() + 1) * sizeof(Elf_Phdr);
-+    /* Compute the total space needed for the replaced sections */
-     for (ReplacedSections::iterator i = replacedSections.begin();
--         i != replacedSections.end(); ++i)
--        neededSpace += roundUp(i->second.size(), sectionAlignment);
--    debug("needed space is %d\n", neededSpace);
--
--
--    size_t startOffset = roundUp(fileSize, pageSize);
--
--    growFile(startOffset + neededSpace);
--
--
--    /* Even though this file is of type ET_DYN, it could actually be
--       an executable.  For instance, Gold produces executables marked
--       ET_DYN.  In that case we can still hit the kernel bug that
--       necessitated rewriteSectionsExecutable().  However, such
--       executables also tend to start at virtual address 0, so
--       rewriteSectionsExecutable() won't work because it doesn't have
--       any virtual address space to grow downwards into.  As a
--       workaround, make sure that the virtual address of our new
--       PT_LOAD segment relative to the first PT_LOAD segment is equal
--       to its offset; otherwise we hit the kernel bug.  This may
--       require creating a hole in the executable.  The bigger the size
--       of the uninitialised data segment, the bigger the hole. */
--    if (isExecutable) {
--        if (startOffset >= startPage) {
--            debug("shifting new PT_LOAD segment by %d bytes to work around a Linux kernel bug\n", startOffset - startPage);
--        } else {
--            size_t hole = startPage - startOffset;
--            /* Print a warning, because the hole could be very big. */
--            fprintf(stderr, "warning: working around a Linux kernel bug by creating a hole of %zu bytes in ‘%s’\n", hole, fileName.c_str());
--            assert(hole % pageSize == 0);
--            /* !!! We could create an actual hole in the file here,
--               but it's probably not worth the effort. */
--            growFile(fileSize + hole);
--            startOffset += hole;
--        }
--        startPage = startOffset;
--    }
--
--
--    /* Add a segment that maps the replaced sections and program
--       headers into memory. */
--    phdrs.resize(rdi(hdr->e_phnum) + 1);
--    wri(hdr->e_phnum, rdi(hdr->e_phnum) + 1);
--    Elf_Phdr & phdr = phdrs[rdi(hdr->e_phnum) - 1];
--    wri(phdr.p_type, PT_LOAD);
--    wri(phdr.p_offset, startOffset);
--    wri(phdr.p_vaddr, wri(phdr.p_paddr, startPage));
--    wri(phdr.p_filesz, wri(phdr.p_memsz, neededSpace));
--    wri(phdr.p_flags, PF_R | PF_W);
--    wri(phdr.p_align, pageSize);
--
--
--    /* Write out the replaced sections. */
--    Elf_Off curOff = startOffset + phdrs.size() * sizeof(Elf_Phdr);
--    writeReplacedSections(curOff, startPage, startOffset);
--    assert((off_t) curOff == startOffset + neededSpace);
--
--
--    /* Move the program header to the start of the new area. */
--    wri(hdr->e_phoff, startOffset);
--
--    rewriteHeaders(startPage);
--}
--
--
--template<ElfFileParams>
--void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
--{
--    /* Sort the sections by offset, otherwise we won't correctly find
--       all the sections before the last replaced section. */
--    sortShdrs();
--
--
--    /* What is the index of the last replaced section? */
--    unsigned int lastReplaced = 0;
--    for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i) {
--        string sectionName = getSectionName(shdrs[i]);
--        if (replacedSections.find(sectionName) != replacedSections.end()) {
--            debug("using replaced section `%s'\n", sectionName.c_str());
--            lastReplaced = i;
--        }
--    }
--
--    assert(lastReplaced != 0);
--
--    debug("last replaced is %d\n", lastReplaced);
--
--    /* Try to replace all sections before that, as far as possible.
--       Stop when we reach an irreplacable section (such as one of type
--       SHT_PROGBITS).  These cannot be moved in virtual address space
--       since that would invalidate absolute references to them. */
--    assert(lastReplaced + 1 < shdrs.size()); /* !!! I'm lazy. */
--    size_t startOffset = rdi(shdrs[lastReplaced + 1].sh_offset);
--    Elf_Addr startAddr = rdi(shdrs[lastReplaced + 1].sh_addr);
--    string prevSection;
--    for (unsigned int i = 1; i <= lastReplaced; ++i) {
--        Elf_Shdr & shdr(shdrs[i]);
--        string sectionName = getSectionName(shdr);
--        debug("looking at section `%s'\n", sectionName.c_str());
--        /* !!! Why do we stop after a .dynstr section? I can't
--           remember! */
--        if ((rdi(shdr.sh_type) == SHT_PROGBITS && sectionName != ".interp")
--            || prevSection == ".dynstr")
--        {
--            startOffset = rdi(shdr.sh_offset);
--            startAddr = rdi(shdr.sh_addr);
--            lastReplaced = i - 1;
--            break;
-+         i != replacedSections.end(); ++i) {
-+        shdr = findSection(i->first);
-+        if (rdi(shdr.sh_flags) & SHF_WRITE) {
-+            oldData += rdi(shdr.sh_size);
-+            neededData += roundUp(i->second.size(), sectionAlignment);
-         } else {
--            if (replacedSections.find(sectionName) == replacedSections.end()) {
--                debug("replacing section `%s' which is in the way\n", sectionName.c_str());
--                replaceSection(sectionName, rdi(shdr.sh_size));
--            }
-+            oldCode += rdi(shdr.sh_size);
-+            neededCode += roundUp(i->second.size(), sectionAlignment);
-         }
--        prevSection = sectionName;
-     }
- 
--    debug("first reserved offset/addr is 0x%x/0x%llx\n",
--        startOffset, (unsigned long long) startAddr);
--
--    assert(startAddr % pageSize == startOffset % pageSize);
--    Elf_Addr firstPage = startAddr - startOffset;
--    debug("first page is 0x%llx\n", (unsigned long long) firstPage);
--
--    /* Right now we assume that the section headers are somewhere near
--       the end, which appears to be the case most of the time.
--       Therefore they're not accidentally overwritten by the replaced
--       sections. !!!  Fix this. */
--    assert((off_t) rdi(hdr->e_shoff) >= startOffset);
--
--
--    /* Compute the total space needed for the replaced sections, the
--       ELF header, and the program headers. */
--    size_t neededSpace = sizeof(Elf_Ehdr) + phdrs.size() * sizeof(Elf_Phdr);
--    for (ReplacedSections::iterator i = replacedSections.begin();
--         i != replacedSections.end(); ++i)
--        neededSpace += roundUp(i->second.size(), sectionAlignment);
--
--    debug("needed space is %d\n", neededSpace);
--
--    /* If we need more space at the start of the file, then grow the
--       file by the minimum number of pages and adjust internal
--       offsets. */
--    if (neededSpace > startOffset) {
--
--        /* We also need an additional program header, so adjust for that. */
--        neededSpace += sizeof(Elf_Phdr);
--        debug("needed space is %d\n", neededSpace);
--
--        unsigned int neededPages = roundUp(neededSpace - startOffset, pageSize) / pageSize;
--        debug("needed pages is %d\n", neededPages);
--        if (neededPages * pageSize > firstPage)
--            error("virtual address space underrun!");
--
--        firstPage -= neededPages * pageSize;
--        startOffset += neededPages * pageSize;
--
--        shiftFile(neededPages, firstPage);
--    }
--
--
--    /* Clear out the free space. */
--    Elf_Off curOff = sizeof(Elf_Ehdr) + phdrs.size() * sizeof(Elf_Phdr);
--    debug("clearing first %d bytes\n", startOffset - curOff);
--    memset(contents + curOff, 0, startOffset - curOff);
-+    debug("needed space is C: %d, D: %d\n", neededCode, neededData);
- 
-+    /* If we need more space within the file, then grow the
-+       file and adjust internal offsets. */
-+    shiftFile(neededCode, neededData, codeOff, dataOff, &codePage,
-+              &dataPage);
-+    assert(codeOff[0] > 0);
- 
-     /* Write out the replaced sections. */
--    writeReplacedSections(curOff, firstPage, 0);
--    assert((off_t) curOff == neededSpace);
--
-+    debug("codePage: %#lx, dataPage: %#lx\n", codePage, dataPage);
-+    writeReplacedSections(codeOff[0], codePage + codeOff[1], codeOff[0]);
-+    writeReplacedSections(dataOff[0], dataPage + dataOff[1], dataOff[0], true);
- 
-     rewriteHeaders(firstPage + rdi(hdr->e_phoff));
- }
-@@ -758,10 +685,10 @@ void ElfFile<ElfFileParamNames>::rewriteSections()
- 
-     if (rdi(hdr->e_type) == ET_DYN) {
-         debug("this is a dynamic library\n");
--        rewriteSectionsLibrary();
-+        rewriteSectionsBinary();
-     } else if (rdi(hdr->e_type) == ET_EXEC) {
-         debug("this is an executable\n");
--        rewriteSectionsExecutable();
-+        rewriteSectionsBinary();
-     } else error("unknown ELF type");
- }
- 
--- 
-2.1.2
-
diff --git a/gnu/packages/patches/patchelf-skip-no-rpath-test.patch b/gnu/packages/patches/patchelf-skip-no-rpath-test.patch
new file mode 100644
index 0000000000..7b49f7aead
--- /dev/null
+++ b/gnu/packages/patches/patchelf-skip-no-rpath-test.patch
@@ -0,0 +1,18 @@
+diff -Nur patchelf-0.10.orig/tests/no-rpath.sh patchelf-0.10/tests/no-rpath.sh
+--- patchelf-0.10.orig/tests/no-rpath.sh	1969-12-31 19:00:01.000000000 -0500
++++ patchelf-0.10/tests/no-rpath.sh	2019-11-08 13:46:44.132511756 -0500
+@@ -1,4 +1,14 @@
+ #! /bin/sh -e
++# This test would fail under Guix since gcc always adds RUNPATH entries,
++# so `$oldRPath` below for the built `no-rpath` binary is never empty.
++#
++# Hopefully the `no-rpath-prebuild.sh` test does include a binary
++# for this architecture without a RUNPATH, and this test is redundant,
++# so just skip it (see "Scripts-based Testsuites" in Automake's manual).
++#
++# See <https://issues.guix.gnu.org/issue/38055> for more info.
++exit 77
++
+ SCRATCH=scratch/$(basename $0 .sh)
+ 
+ rm -rf ${SCRATCH}
-- 
2.23.0