all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#38055: patchelf: Assertion failed when setting interpreter
@ 2019-11-04  4:56 Ivan Vilata i Balaguer
  2019-11-05 14:12 ` Ludovic Courtès
  2019-11-09 18:25 ` bug#38055: (no subject) Efraim Flashner
  0 siblings, 2 replies; 11+ messages in thread
From: Ivan Vilata i Balaguer @ 2019-11-04  4:56 UTC (permalink / raw)
  To: 38055

Hi, I'm using patchelf 0.8 from Guix commit 7f81cce3 on Debian Sid.  When
trying to patch the `go` binary from
<https://dl.google.com/go/go1.12.3.linux-amd64.tar.gz>, I get the following
error:

    ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --print-interpreter $SHELL
    /gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib/ld-linux-x86-64.so.2
    ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --set-interpreter $(patchelf --print-interpreter $SHELL) /tmp/tmps2Cv6w/golang/bin/go
    patchelf: patchelf.cc:701: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() \
     [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; \
     Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `(off_t) rdi(hdr->e_shoff) >= startOffset' failed.
    Aborted

(I know Go is packed for Guix, my need arises from trying to build an
unrelated project which relies on binary Go for its build process.)

It may be the problem described here regarding Go-produced binaries:
<https://github.com/NixOS/patchelf/issues/66>.  It seems to be fixed in
patchelf 0.10, and indeed trying the same operation with patchelf 0.10 from
Debian does succeed to patch the binary.

As an aside, I tried to build `--with-source` for 0.10 and it succeeds to
compile, but tests fail to pass.

Thank you very much!

-- 
Ivan Vilata i Balaguer -- https://elvil.net/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: patchelf: Assertion failed when setting interpreter
  2019-11-04  4:56 bug#38055: patchelf: Assertion failed when setting interpreter Ivan Vilata i Balaguer
@ 2019-11-05 14:12 ` Ludovic Courtès
  2019-11-05 16:18   ` Efraim Flashner
  2019-11-09 18:25 ` bug#38055: (no subject) Efraim Flashner
  1 sibling, 1 reply; 11+ messages in thread
From: Ludovic Courtès @ 2019-11-05 14:12 UTC (permalink / raw)
  To: Ivan Vilata i Balaguer; +Cc: 38055

Hi Ivan,

Ivan Vilata i Balaguer <ivan@selidor.net> skribis:

> Hi, I'm using patchelf 0.8 from Guix commit 7f81cce3 on Debian Sid.  When
> trying to patch the `go` binary from
> <https://dl.google.com/go/go1.12.3.linux-amd64.tar.gz>, I get the following
> error:
>
>     ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --print-interpreter $SHELL
>     /gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib/ld-linux-x86-64.so.2
>     ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --set-interpreter $(patchelf --print-interpreter $SHELL) /tmp/tmps2Cv6w/golang/bin/go
>     patchelf: patchelf.cc:701: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() \
>      [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; \
>      Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `(off_t) rdi(hdr->e_shoff) >= startOffset' failed.
>     Aborted

I think it’s a bug you should report upstream to the PatchELF
maintainers; it’s probably not Guix-specific.

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: patchelf: Assertion failed when setting interpreter
  2019-11-05 14:12 ` Ludovic Courtès
@ 2019-11-05 16:18   ` Efraim Flashner
  2019-11-06 21:42     ` Ivan Vilata i Balaguer
  0 siblings, 1 reply; 11+ messages in thread
From: Efraim Flashner @ 2019-11-05 16:18 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 38055, Ivan Vilata i Balaguer

[-- Attachment #1: Type: text/plain, Size: 1545 bytes --]

On Tue, Nov 05, 2019 at 03:12:23PM +0100, Ludovic Courtès wrote:
> Hi Ivan,
> 
> Ivan Vilata i Balaguer <ivan@selidor.net> skribis:
> 
> > Hi, I'm using patchelf 0.8 from Guix commit 7f81cce3 on Debian Sid.  When
> > trying to patch the `go` binary from
> > <https://dl.google.com/go/go1.12.3.linux-amd64.tar.gz>, I get the following
> > error:
> >
> >     ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --print-interpreter $SHELL
> >     /gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib/ld-linux-x86-64.so.2
> >     ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --set-interpreter $(patchelf --print-interpreter $SHELL) /tmp/tmps2Cv6w/golang/bin/go
> >     patchelf: patchelf.cc:701: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() \
> >      [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; \
> >      Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `(off_t) rdi(hdr->e_shoff) >= startOffset' failed.
> >     Aborted
> 
> I think it’s a bug you should report upstream to the PatchELF
> maintainers; it’s probably not Guix-specific.
> 

On the other hand, if I were the patchelf maintainers, I'd suggest
upgrading our package from 0.8 to a newer version.

-- 
Efraim Flashner   <efraim@flashner.co.il>   אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D  14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: patchelf: Assertion failed when setting interpreter
  2019-11-05 16:18   ` Efraim Flashner
@ 2019-11-06 21:42     ` Ivan Vilata i Balaguer
  2019-11-07 20:55       ` Ludovic Courtès
  0 siblings, 1 reply; 11+ messages in thread
From: Ivan Vilata i Balaguer @ 2019-11-06 21:42 UTC (permalink / raw)
  To: Efraim Flashner; +Cc: 38055, Ivan Vilata i Balaguer

Efraim Flashner (2019-11-05 18:18:22 +0200) wrote:

> On Tue, Nov 05, 2019 at 03:12:23PM +0100, Ludovic Courtès wrote:
> > 
> > Ivan Vilata i Balaguer <ivan@selidor.net> skribis:
> > 
> > > Hi, I'm using patchelf 0.8 from Guix commit 7f81cce3 on Debian Sid.
> > > When trying to patch the `go` binary from
> > > <https://dl.google.com/go/go1.12.3.linux-amd64.tar.gz>, I get the
> > > following error:
> > >
> > >     ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --print-interpreter $SHELL
> > >     /gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib/ld-linux-x86-64.so.2
> > >     ivan@sax /tmp/tmps2Cv6w [env]$ patchelf --set-interpreter $(patchelf --print-interpreter $SHELL) /tmp/tmps2Cv6w/golang/bin/go
> > >     patchelf: patchelf.cc:701: void ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym>::rewriteSectionsExecutable() \
> > >      [with Elf_Ehdr = Elf64_Ehdr; Elf_Phdr = Elf64_Phdr; Elf_Shdr = Elf64_Shdr; Elf_Addr = long unsigned int; Elf_Off = long unsigned int; \
> > >      Elf_Dyn = Elf64_Dyn; Elf_Sym = Elf64_Sym]: Assertion `(off_t) rdi(hdr->e_shoff) >= startOffset' failed.
> > >     Aborted
> > 
> > I think it’s a bug you should report upstream to the PatchELF
> > maintainers; it’s probably not Guix-specific.
> 
> On the other hand, if I were the patchelf maintainers, I'd suggest
> upgrading our package from 0.8 to a newer version.

Yeah, as I mentioned in the original mail that particular problem does indeed
seem to be fixed in 0.10.  However when I try to build that source with `guix
build patchelf --with-source=…`, tests fail.

If I run `guix environment -C --pure patchelf` then unpack and build the
source, the only test that actually fails is `no-rpath.sh`.  If I run `sh -x
no-rpath.sh` I get this:

```
++ basename no-rpath.sh .sh
+ SCRATCH=scratch/no-rpath
+ rm -rf scratch/no-rpath
+ mkdir -p scratch/no-rpath
+ cp no-rpath scratch/no-rpath/
++ ../src/patchelf --print-rpath scratch/no-rpath/no-rpath
+ oldRPath=/gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../..:/gnu/store/dcrwf5irwh39knld1wim1qkny659af9g-profile/lib
+ test -n /gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../..:/gnu/store/dcrwf5irwh39knld1wim1qkny659af9g-profile/lib
+ exit 1
```

To succeed, the output of `…/patchelf --print-rpath …/no-rpath`
(i.e. `oldRPath`) should be empty.  I'm not that familiar with Guix's GNU
build system, but is that at all possible under Guix?  I mean, maybe the test
is pointless or must be altered in some Guix-specific way for the `no-rpath`
binary not to have an rpath.

Cheers,

-- 
Ivan Vilata i Balaguer -- https://elvil.net/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: patchelf: Assertion failed when setting interpreter
  2019-11-06 21:42     ` Ivan Vilata i Balaguer
@ 2019-11-07 20:55       ` Ludovic Courtès
  0 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2019-11-07 20:55 UTC (permalink / raw)
  To: Ivan Vilata i Balaguer; +Cc: 38055

Bona nit!

Ivan Vilata i Balaguer <ivan@selidor.net> skribis:

> Yeah, as I mentioned in the original mail that particular problem does indeed
> seem to be fixed in 0.10.  However when I try to build that source with `guix
> build patchelf --with-source=…`, tests fail.
>
> If I run `guix environment -C --pure patchelf` then unpack and build the
> source, the only test that actually fails is `no-rpath.sh`.  If I run `sh -x
> no-rpath.sh` I get this:
>
> ```
> ++ basename no-rpath.sh .sh
> + SCRATCH=scratch/no-rpath
> + rm -rf scratch/no-rpath
> + mkdir -p scratch/no-rpath
> + cp no-rpath scratch/no-rpath/
> ++ ../src/patchelf --print-rpath scratch/no-rpath/no-rpath
> + oldRPath=/gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../..:/gnu/store/dcrwf5irwh39knld1wim1qkny659af9g-profile/lib
> + test -n /gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib:/gnu/store/2plcy91lypnbbysb18ymnhaw3zwk8pg1-gcc-7.4.0-lib/lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../..:/gnu/store/dcrwf5irwh39knld1wim1qkny659af9g-profile/lib
> + exit 1
> ```
>
> To succeed, the output of `…/patchelf --print-rpath …/no-rpath`
> (i.e. `oldRPath`) should be empty.  I'm not that familiar with Guix's GNU
> build system, but is that at all possible under Guix?  I mean, maybe the test
> is pointless or must be altered in some Guix-specific way for the `no-rpath`
> binary not to have an rpath.

Guix’ ‘gcc’ automatically adds RUNPATH entries to glibc/lib and
gcc:lib/lib:

--8<---------------cut here---------------start------------->8---
$ gcc -dumpspecs |grep -e -rpath
%{!mandroid|tno-android-ld:-L/gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib %{!static:-rpath=/gnu/store/ahqgl4h89xqj695lgqvsaf6zh2nhy4pj-glibc-2.29/lib %{!static-libgcc:-rpath=/gnu/store/347y0zr1a9s2f5pkcncgi3gd0r33qq81-gcc-9.2.0-lib/lib -lgcc_s}} %{pthread:-lpthread} %{shared:-lc}    %{!shared:%{profile:-lc_p}%{!profile:-lc}};:%{shared:-lc}    %{!shared:%{profile:-lc_p}%{!profile:-lc}} %{!static: -ldl}}
--8<---------------cut here---------------end--------------->8---

The code that modifies GCC to do that is in (gnu packages gcc).

Thus, RUNPATH is never empty, and the test above is bound to fail.

Two possibilities: change the test to ensure that ‘--print-rpath’
returns precisely libc/lib:gcc/lib, or, if that turns out to be tricky,
skip the test (in both cases, add a comment linking to this discussion
for future reference.)

How does that sound?

Thank you!

Ludo’.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: (no subject)
  2019-11-04  4:56 bug#38055: patchelf: Assertion failed when setting interpreter Ivan Vilata i Balaguer
  2019-11-05 14:12 ` Ludovic Courtès
@ 2019-11-09 18:25 ` Efraim Flashner
  2019-11-10 14:14   ` bug#38055: none Ludovic Courtès
  1 sibling, 1 reply; 11+ messages in thread
From: Efraim Flashner @ 2019-11-09 18:25 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 38055, Ivan Vilata i Balaguer


[-- Attachment #1.1: Type: text/plain, Size: 770 bytes --]

guix-patches@gnu.org
Bcc: 
Subject: Re: bug#38055: patchelf: Assertion failed when setting interpreter
Reply-To: 
In-Reply-To: <87zhh7mmoo.fsf@gnu.org>
X-PGP-Key-ID: 0x41AAE7DCCA3D8351
X-PGP-Key: https://flashner.co.il/~efraim/efraim_flashner.asc
X-PGP-Fingerprint: A28B F40C 3E55 1372 662D  14F7 41AA E7DC CA3D 8351
I put together a patch to bump patchelf to 0.10. 'guix refresh -l
patchelf' says there's 614 dependent packages, but 'git grep ,patchelf'
and 'git grep guix\ build\ rpath' it looks like there's julia and 613
haskell packages.


-- 
Efraim Flashner   <efraim@flashner.co.il>   אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D  14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted

[-- Attachment #1.2: 0001-gnu-patchelf-Update-to-0.10.patch --]
[-- Type: text/plain, Size: 28682 bytes --]

From 2db156170a24fea36aced781faf96c839a3b7d15 Mon Sep 17 00:00:00 2001
From: Efraim Flashner <efraim@flashner.co.il>
Date: Sat, 9 Nov 2019 20:19:11 +0200
Subject: [PATCH] gnu: patchelf: Update to 0.10.

* gnu/packages/elf.scm (patchelf): Update to 0.10.
[source]: Remove patches.
[arguments]: Remove patch/rework-for-arm phase. Add phase to modify
tests for our modified GCC package.
[native-inputs]: Add gcc:lib.
* gnu/packages/patches/patchelf-page-size.patch,
* gnu/packages/patches/patchelf-rework-for-arm.patch: Remove files.
* gnu/local.mk (dist_patch_DATA): Remove them.
---
 gnu/local.mk                                  |   2 -
 gnu/packages/elf.scm                          |  39 +-
 gnu/packages/patches/patchelf-page-size.patch |  70 ---
 .../patches/patchelf-rework-for-arm.patch     | 473 ------------------
 4 files changed, 17 insertions(+), 567 deletions(-)
 delete mode 100644 gnu/packages/patches/patchelf-page-size.patch
 delete mode 100644 gnu/packages/patches/patchelf-rework-for-arm.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 0f02c4b6be..1e6ab0dc66 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1204,8 +1204,6 @@ dist_patch_DATA =						\
   %D%/packages/patches/p7zip-CVE-2016-9296.patch		\
   %D%/packages/patches/p7zip-CVE-2017-17969.patch		\
   %D%/packages/patches/p7zip-remove-unused-code.patch		\
-  %D%/packages/patches/patchelf-page-size.patch			\
-  %D%/packages/patches/patchelf-rework-for-arm.patch		\
   %D%/packages/patches/patchutils-test-perms.patch		\
   %D%/packages/patches/patch-hurd-path-max.patch		\
   %D%/packages/patches/pcre2-fix-jit_match-crash.patch		\
diff --git a/gnu/packages/elf.scm b/gnu/packages/elf.scm
index 4f365cf205..f494d1bc85 100644
--- a/gnu/packages/elf.scm
+++ b/gnu/packages/elf.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
-;;; Copyright © 2017, 2018 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2017, 2018, 2019 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
 ;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
 ;;; Copyright © 2018 Marius Bakke <mbakke@fastmail.com>
@@ -31,6 +31,7 @@
   #:use-module (gnu packages)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages documentation)
+  #:use-module (gnu packages gcc)
   #:use-module (gnu packages m4)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages python)
@@ -198,7 +199,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 +208,22 @@ static analysis of the ELF binaries at hand.")
                    "/patchelf-" version ".tar.bz2"))
              (sha256
               (base32
-               "1rqpg84wrd3fa16wa9vqdvasnc05yz49w207cz1l0wrl4k8q97y9"))
-             (patches (search-patches "patchelf-page-size.patch"))))
+               "1wzwvnlyf853hw9zgqq5522bvf8gqadk8icgqa41a5n7593csw7n"))))
     (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))))))
-         '()))
-
+     '(#:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'fix-tests
+           ;; Our GCC code ensures that RUNPATH is never empty, it includes
+           ;; at least glibc/lib and gcc:lib/lib.
+           (lambda* (#:key inputs #:allow-other-keys)
+             (substitute* "tests/no-rpath.sh"
+               (("^if test.*") "")
+               (("/xxxxxxxxxxxxxxx") (string-append (assoc-ref inputs "gcc:lib")
+                                                    "/lib")))
+             #t)))))
+    (native-inputs
+     `(("gcc:lib" ,gcc "lib")))
     (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 <mhw@netris.org>.
-
---- 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 <s.parschauer@gmx.de>
-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
-
-- 
2.24.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* bug#38055: none
  2019-11-09 18:25 ` bug#38055: (no subject) Efraim Flashner
@ 2019-11-10 14:14   ` Ludovic Courtès
  2019-11-11  9:27     ` Efraim Flashner
  0 siblings, 1 reply; 11+ messages in thread
From: Ludovic Courtès @ 2019-11-10 14:14 UTC (permalink / raw)
  To: Efraim Flashner; +Cc: 38055, Ivan Vilata i Balaguer

Hi,

Efraim Flashner <efraim@flashner.co.il> skribis:

> From 2db156170a24fea36aced781faf96c839a3b7d15 Mon Sep 17 00:00:00 2001
> From: Efraim Flashner <efraim@flashner.co.il>
> Date: Sat, 9 Nov 2019 20:19:11 +0200
> Subject: [PATCH] gnu: patchelf: Update to 0.10.
>
> * gnu/packages/elf.scm (patchelf): Update to 0.10.
> [source]: Remove patches.
> [arguments]: Remove patch/rework-for-arm phase. Add phase to modify
> tests for our modified GCC package.
> [native-inputs]: Add gcc:lib.
> * gnu/packages/patches/patchelf-page-size.patch,
> * gnu/packages/patches/patchelf-rework-for-arm.patch: Remove files.
> * gnu/local.mk (dist_patch_DATA): Remove them.

[...]

> +       (modify-phases %standard-phases
> +         (add-after 'unpack 'fix-tests
> +           ;; Our GCC code ensures that RUNPATH is never empty, it includes
> +           ;; at least glibc/lib and gcc:lib/lib.
> +           (lambda* (#:key inputs #:allow-other-keys)
> +             (substitute* "tests/no-rpath.sh"
> +               (("^if test.*") "")
> +               (("/xxxxxxxxxxxxxxx") (string-append (assoc-ref inputs "gcc:lib")
> +                                                    "/lib")))

Could you complement the above comment with something like: “Thus,
disable the test that checks for an empty RUNPATH.”, or whatever is
appropriate?  That will clarify the intent because it’s not obvious what
the substitution is doing if you don’t have the file at hand.  :-)

Otherwise LGTM, thanks for addressing this issue!

Ludo’.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: none
  2019-11-10 14:14   ` bug#38055: none Ludovic Courtès
@ 2019-11-11  9:27     ` Efraim Flashner
  2019-11-11 15:10       ` Ivan Vilata i Balaguer
  0 siblings, 1 reply; 11+ messages in thread
From: Efraim Flashner @ 2019-11-11  9:27 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 38055-done, Ivan Vilata i Balaguer

[-- Attachment #1: Type: text/plain, Size: 256 bytes --]

Some inline comments added. Patch pushed.

-- 
Efraim Flashner   <efraim@flashner.co.il>   אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D  14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: none
  2019-11-11  9:27     ` Efraim Flashner
@ 2019-11-11 15:10       ` Ivan Vilata i Balaguer
  2019-11-11 15:30         ` Ivan Vilata i Balaguer
  2019-11-12  5:19         ` Ivan Vilata i Balaguer
  0 siblings, 2 replies; 11+ messages in thread
From: Ivan Vilata i Balaguer @ 2019-11-11 15:10 UTC (permalink / raw)
  To: Efraim Flashner; +Cc: 38055-done, Ivan Vilata i Balaguer

Efraim Flashner (2019-11-11 11:27:30 +0200) wrote:

> Some inline comments added. Patch pushed.

Wow, thank you so much for taking care of this!  I did prepare a patch on
Friday but I didn't have the time to send it, plus it pales in comparison to
Efraim's and it also had the `ipfs` binary segfault after patching.  I'm still
attaching it in case you're curious (of course I don't expect any of it to get
merged `;)`).

I'll try to find a moment to test your patch and see if the `ipfs` binary
doesn't segfault, then report back.

Thanks again!

-- 
Ivan Vilata i Balaguer -- https://elvil.net/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#38055: none
  2019-11-11 15:10       ` Ivan Vilata i Balaguer
@ 2019-11-11 15:30         ` Ivan Vilata i Balaguer
  2019-11-12  5:19         ` Ivan Vilata i Balaguer
  1 sibling, 0 replies; 11+ messages in thread
From: Ivan Vilata i Balaguer @ 2019-11-11 15:30 UTC (permalink / raw)
  To: Ivan Vilata i Balaguer; +Cc: 38055-done

[-- Attachment #1: Type: text/plain, Size: 261 bytes --]

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/

[-- Attachment #2: 0001-gnu-patchelf-Update-to-0.10.patch --]
[-- Type: text/plain, Size: 27356 bytes --]

From 2e4cca87b865dbd26ee417775d543abab7ba4f53 Mon Sep 17 00:00:00 2001
From: Ivan Vilata-i-Balaguer <ivan@selidor.net>
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 <mhw@netris.org>.
-
---- 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 <s.parschauer@gmx.de>
-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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* bug#38055: none
  2019-11-11 15:10       ` Ivan Vilata i Balaguer
  2019-11-11 15:30         ` Ivan Vilata i Balaguer
@ 2019-11-12  5:19         ` Ivan Vilata i Balaguer
  1 sibling, 0 replies; 11+ messages in thread
From: Ivan Vilata i Balaguer @ 2019-11-12  5:19 UTC (permalink / raw)
  To: Ivan Vilata i Balaguer; +Cc: 38055-done

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

> Efraim Flashner (2019-11-11 11:27:30 +0200) wrote:
> 
> > Some inline comments added. Patch pushed.
> 
> […] I'll try to find a moment to test your patch and see if the `ipfs`
> binary doesn't segfault, then report back. […]

I tried your patch, the following command in a pure container environment:

    $ patchelf --set-interpreter "$(patchelf --print-interpreter /bin/sh)" /path/to/bin/go

does not trigger the assertion error (both `--set-interpreter` and
`--set-rpath` suffered from the same failure), and the resulting `go` binary
can be executed without issues.

Thank you very much for fixing this! `:)`

-- 
Ivan Vilata i Balaguer -- https://elvil.net/

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-11-12  5:21 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-11-04  4:56 bug#38055: patchelf: Assertion failed when setting interpreter Ivan Vilata i Balaguer
2019-11-05 14:12 ` Ludovic Courtès
2019-11-05 16:18   ` Efraim Flashner
2019-11-06 21:42     ` Ivan Vilata i Balaguer
2019-11-07 20:55       ` Ludovic Courtès
2019-11-09 18:25 ` bug#38055: (no subject) Efraim Flashner
2019-11-10 14:14   ` bug#38055: none Ludovic Courtès
2019-11-11  9:27     ` Efraim Flashner
2019-11-11 15:10       ` Ivan Vilata i Balaguer
2019-11-11 15:30         ` Ivan Vilata i Balaguer
2019-11-12  5:19         ` Ivan Vilata i Balaguer

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.