From: Efraim Flashner <efraim@flashner.co.il>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: 38055@debbugs.gnu.org, Ivan Vilata i Balaguer <ivan@selidor.net>
Subject: bug#38055: (no subject)
Date: Sat, 9 Nov 2019 20:25:10 +0200 [thread overview]
Message-ID: <20191109182510.GA3954@E5400> (raw)
In-Reply-To: <20191104045614.GI17621@sax.terramar.selidor.net>
[-- 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 --]
next prev parent reply other threads:[~2019-11-09 18:27 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Efraim Flashner [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191109182510.GA3954@E5400 \
--to=efraim@flashner.co.il \
--cc=38055@debbugs.gnu.org \
--cc=ivan@selidor.net \
--cc=ludo@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).