From mboxrd@z Thu Jan 1 00:00:00 1970 From: Efraim Flashner Subject: bug#38055: (no subject) Date: Sat, 9 Nov 2019 20:25:10 +0200 Message-ID: <20191109182510.GA3954@E5400> References: <20191104045614.GI17621@sax.terramar.selidor.net> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="ftEhullJWpWg/VHq" Return-path: Received: from eggs.gnu.org ([2001:470:142:3::10]:38809) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iTVRz-0006zt-CM for bug-guix@gnu.org; Sat, 09 Nov 2019 13:27:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iTVRv-0000zM-Q1 for bug-guix@gnu.org; Sat, 09 Nov 2019 13:27:07 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:41449) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iTVRu-0000yK-GE for bug-guix@gnu.org; Sat, 09 Nov 2019 13:27:03 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iTVRu-00028C-Ah for bug-guix@gnu.org; Sat, 09 Nov 2019 13:27:02 -0500 In-Reply-To: <20191104045614.GI17621@sax.terramar.selidor.net> Sender: "Debbugs-submit" Resent-Message-ID: Content-Disposition: inline List-Id: Bug reports for GNU Guix List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guix-bounces+gcggb-bug-guix=m.gmane.org@gnu.org Sender: "bug-Guix" To: Ludovic =?UTF-8?Q?Court=C3=A8s?= Cc: 38055@debbugs.gnu.org, Ivan Vilata i Balaguer --ftEhullJWpWg/VHq Content-Type: multipart/mixed; boundary="KsGdsel6WgEHnImy" Content-Disposition: inline --KsGdsel6WgEHnImy Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable guix-patches@gnu.org Bcc:=20 Subject: Re: bug#38055: patchelf: Assertion failed when setting interpreter Reply-To:=20 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. --=20 Efraim Flashner =D7=90=D7=A4=D7=A8=D7=99=D7=9D = =D7=A4=D7=9C=D7=A9=D7=A0=D7=A8 GPG key =3D A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351 Confidentiality cannot be guaranteed on emails sent or received unencrypted --KsGdsel6WgEHnImy Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0001-gnu-patchelf-Update-to-0.10.patch" Content-Transfer-Encoding: quoted-printable =46rom 2db156170a24fea36aced781faf96c839a3b7d15 Mon Sep 17 00:00:00 2001 =46rom: Efraim Flashner 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 =3D \ %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 =C2=A9 2013, 2014, 2015 Ludovic Court=C3=A8s ;;; Copyright =C2=A9 2014, 2015 Mark H Weaver ;;; Copyright =C2=A9 2015 Andreas Enge -;;; Copyright =C2=A9 2017, 2018 Efraim Flashner +;;; Copyright =C2=A9 2017, 2018, 2019 Efraim Flashner ;;; Copyright =C2=A9 2017 Leo Famulari ;;; Copyright =C2=A9 2018 Tobias Geerinckx-Rice ;;; Copyright =C2=A9 2018 Marius Bakke @@ -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 availab= le - ;; 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/p= atches/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 . - ---- 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; -=20 -=20 --#ifdef MIPSEL --/* The lemote fuloong 2f kernel defconfig sets a page size of 16KB */ --const unsigned int pageSize =3D 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 =3D 65536; -+#elif defined __x86_64__ || defined __i386__ || defined __arm__ - const unsigned int pageSize =3D 4096; -+#else -+# error maximum architectural page size unknown for this platform - #endif -=20 -=20 ---- 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=3Dscratch/$(basename $0 .sh) -=20 --rm -rf ${SCRATCH} --mkdir -p ${SCRATCH} -+if [ "$(uname -m)" =3D i686 -a "$(uname -s)" =3D Linux ]; then -+ rm -rf ${SCRATCH} -+ mkdir -p ${SCRATCH} -=20 --cp ${srcdir}/no-rpath ${SCRATCH}/ -+ cp ${srcdir}/no-rpath ${SCRATCH}/ -=20 --oldRPath=3D$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) --if test -n "$oldRPath"; then exit 1; fi --../src/patchelf \ -- --set-interpreter "$(../src/patchelf --print-interpreter ../src/patchel= f)" \ -- --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath -+ oldRPath=3D$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) -+ if test -n "$oldRPath"; then exit 1; fi -+ ../src/patchelf \ -+ --set-interpreter "$(../src/patchelf --print-interpreter ../src/pat= chelf)" \ -+ --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath -=20 --newRPath=3D$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) --if ! echo "$newRPath" | grep -q '/foo:/bar'; then -- echo "incomplete RPATH" -- exit 1 --fi -+ newRPath=3D$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) -+ if ! echo "$newRPath" | grep -q '/foo:/bar'; then -+ echo "incomplete RPATH" -+ exit 1 -+ fi -=20 --if [ "$(uname -m)" =3D i686 -a "$(uname -s)" =3D Linux ]; then - cd ${SCRATCH} && ./no-rpath - fi diff --git a/gnu/packages/patches/patchelf-rework-for-arm.patch b/gnu/packa= ges/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 . -This patch copied from: - - -From 0a96239cea6b97b9a0fff80da576e58ca2dfb2a2 Mon Sep 17 00:00:00 2001 -From: Sebastian Parschauer -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: -=20 - void sortShdrs(); -=20 -- 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); -=20 - string getSectionName(const Elf_Shdr & shdr); -=20 -@@ -130,13 +134,11 @@ private: - unsigned int size); -=20 - void writeReplacedSections(Elf_Off & curOff, -- Elf_Addr startAddr, Elf_Off startOffset); -+ Elf_Addr startAddr, Elf_Off startOffset, bool isData); -=20 - void rewriteHeaders(Elf_Addr phdrAddress); -=20 -- void rewriteSectionsLibrary(); -- -- void rewriteSectionsExecutable(); -+ void rewriteSectionsBinary(); -=20 - public: -=20 -@@ -391,46 +393,119 @@ static unsigned int roundUp(unsigned int n, unsigne= d int m) -=20 -=20 - template --void ElfFile::shiftFile(unsigned int extraPages, Elf_A= ddr startPage) -+void ElfFile::shiftFileSingle(size_t fileShift, -+ Elf_Off insertOff) - { -- /* Move the entire contents of the file `extraPages' pages -- further. */ - unsigned int oldSize =3D fileSize; -- unsigned int shift =3D 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); -=20 - /* 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) >=3D insertOff) -+ wri(hdr->e_shoff, rdi(hdr->e_shoff) + fileShift); -=20 - /* Update the offsets in the section headers. */ -- for (int i =3D 1; i < rdi(hdr->e_shnum); ++i) -- wri(shdrs[i].sh_offset, rdi(shdrs[i].sh_offset) + shift); -+ for (int i =3D 1; i < rdi(hdr->e_shnum); ++i) { -+ if (rdi(shdrs[i].sh_offset) >=3D insertOff) -+ wri(shdrs[i].sh_offset, rdi(shdrs[i].sh_offset) + fileShift); -+ } -=20 - /* Update the offsets in the program headers. */ - for (int i =3D 0; i < rdi(hdr->e_phnum); ++i) { -- wri(phdrs[i].p_offset, rdi(phdrs[i].p_offset) + shift); -- if (rdi(phdrs[i].p_align) !=3D 0 && -- (rdi(phdrs[i].p_vaddr) - rdi(phdrs[i].p_offset)) % rdi(phdrs[= i].p_align) !=3D 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) >=3D 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) =3D=3D PT_LOAD && ((rdi(phdrs[i].p_vaddr= ) - -+ rdi(phdrs[i].p_offset)) & (rdi(phdrs[i].p_align) - 1)) !=3D 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 -+void ElfFile::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 ar= ea -+ * for code and one for data. There is virtual memory space between -+ * these which we can use due to alignment. -+ */ -+ unsigned int memShift =3D neededCode; -+ unsigned int fileShift =3D roundUp(neededCode, pageSize); -+ unsigned int maxMemShift =3D 0; -+ -+ if (neededCode > 0) { -+ /* find the LOAD program header for code and extend it */ -+ for (int i =3D 0; i < rdi(hdr->e_phnum); ++i) { -+ if (rdi(phdrs[i].p_type) =3D=3D PT_LOAD && -+ rdi(phdrs[i].p_flags) & PF_X) { -+ codeOff[1] =3D rdi(phdrs[i].p_filesz); -+ codeOff[0] =3D codeOff[1] + rdi(phdrs[i].p_offset); -+ maxMemShift =3D rdi(phdrs[i].p_memsz) % rdi(phdrs[i].p_al= ign); -+ if (maxMemShift =3D=3D 0) -+ continue; -+ maxMemShift =3D rdi(phdrs[i].p_align) - maxMemShift; -+ if (maxMemShift =3D=3D 0 || memShift > maxMemShift) -+ continue; -+ *codePage =3D 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] =3D=3D 0 || maxMemShift =3D=3D 0) -+ goto out; -+ -+ shiftFileSingle(fileShift, codeOff[0]); -+ } -+ -+ /* +++ Do the same for the data LOAD area +++ */ -+ memShift =3D neededData; -+ fileShift =3D roundUp(neededData, pageSize); -+ maxMemShift =3D 0; -+ if (neededData > 0) { -+ /* find the LOAD program header for data and extend it */ -+ for (int i =3D 0; i < rdi(hdr->e_phnum); ++i) { -+ if (rdi(phdrs[i].p_type) =3D=3D PT_LOAD && -+ rdi(phdrs[i].p_flags) & PF_W) { -+ dataOff[1] =3D rdi(phdrs[i].p_filesz); -+ dataOff[0] =3D dataOff[1] + rdi(phdrs[i].p_offset); -+ maxMemShift =3D rdi(phdrs[i].p_memsz) % rdi(phdrs[i].p_al= ign); -+ if (maxMemShift =3D=3D 0) -+ continue; -+ maxMemShift =3D rdi(phdrs[i].p_align) - maxMemShift; -+ if (maxMemShift =3D=3D 0 || memShift > maxMemShift) -+ continue; -+ *dataPage =3D 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] =3D=3D 0 || maxMemShift =3D=3D 0) -+ goto out; -=20 -- /* 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 =3D 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; - } -=20 -=20 -@@ -491,7 +566,7 @@ string & ElfFile::replaceSection(co= nst SectionName & sectionN -=20 - template - void ElfFile::writeReplacedSections(Elf_Off & curOff, -- Elf_Addr startAddr, Elf_Off startOffset) -+ Elf_Addr startAddr, Elf_Off startOffset, bool isData =3D 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::writeReplacedSections= (Elf_Off & curOff, - { - string sectionName =3D i->first; - Elf_Shdr & shdr =3D 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)); - } -=20 -@@ -509,6 +587,9 @@ void ElfFile::writeReplacedSections= (Elf_Off & curOff, - { - string sectionName =3D i->first; - Elf_Shdr & shdr =3D 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 offse= t 0x%x (size %d)\n", - sectionName.c_str(), rdi(shdr.sh_offset), rdi(shdr.sh_size), = curOff, i->second.size()); -=20 -@@ -546,201 +627,47 @@ void ElfFile::writeReplacedSecti= ons(Elf_Off & curOff, - curOff +=3D roundUp(i->second.size(), sectionAlignment); - } -=20 -- replacedSections.clear(); -+ if (isData) -+ replacedSections.clear(); - } -=20 -=20 - template --void ElfFile::rewriteSectionsLibrary() -+void ElfFile::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 =3D 0; -- for (unsigned int i =3D 0; i < phdrs.size(); ++i) { -- Elf_Addr thisPage =3D roundUp(rdi(phdrs[i].p_vaddr) + rdi(phdrs[i= ].p_memsz), pageSize); -- if (thisPage > startPage) startPage =3D thisPage; -- } -- -- debug("last page is 0x%llx\n", (unsigned long long) startPage); -+ Elf_Off codeOff[2] =3D {0}, dataOff[2] =3D {0}; -+ Elf_Addr codePage =3D 0, dataPage =3D 0; -+ size_t neededCode =3D 0, neededData =3D 0, oldCode =3D 0, oldData =3D= 0; -+ Elf_Shdr shdr =3D findSection(".text"); -+ Elf_Addr firstPage =3D rdi(shdr.sh_addr) - rdi(shdr.sh_offset); -=20 -+ debug("first page is 0x%llx\n", (unsigned long long) firstPage); -=20 -- /* Compute the total space needed for the replaced sections and -- the program headers. */ -- off_t neededSpace =3D (phdrs.size() + 1) * sizeof(Elf_Phdr); -+ /* Compute the total space needed for the replaced sections */ - for (ReplacedSections::iterator i =3D replacedSections.begin(); -- i !=3D replacedSections.end(); ++i) -- neededSpace +=3D roundUp(i->second.size(), sectionAlignment); -- debug("needed space is %d\n", neededSpace); -- -- -- size_t startOffset =3D 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 >=3D startPage) { -- debug("shifting new PT_LOAD segment by %d bytes to work aroun= d a Linux kernel bug\n", startOffset - startPage); -- } else { -- size_t hole =3D startPage - startOffset; -- /* Print a warning, because the hole could be very big. */ -- fprintf(stderr, "warning: working around a Linux kernel bug b= y creating a hole of %zu bytes in =E2=80=98%s=E2=80=99\n", hole, fileName.c= _str()); -- assert(hole % pageSize =3D=3D 0); -- /* !!! We could create an actual hole in the file here, -- but it's probably not worth the effort. */ -- growFile(fileSize + hole); -- startOffset +=3D hole; -- } -- startPage =3D 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 =3D 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 =3D startOffset + phdrs.size() * sizeof(Elf_Phdr); -- writeReplacedSections(curOff, startPage, startOffset); -- assert((off_t) curOff =3D=3D startOffset + neededSpace); -- -- -- /* Move the program header to the start of the new area. */ -- wri(hdr->e_phoff, startOffset); -- -- rewriteHeaders(startPage); --} -- -- --template --void ElfFile::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 =3D 0; -- for (unsigned int i =3D 1; i < rdi(hdr->e_shnum); ++i) { -- string sectionName =3D getSectionName(shdrs[i]); -- if (replacedSections.find(sectionName) !=3D replacedSections.end(= )) { -- debug("using replaced section `%s'\n", sectionName.c_str()); -- lastReplaced =3D i; -- } -- } -- -- assert(lastReplaced !=3D 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 =3D rdi(shdrs[lastReplaced + 1].sh_offset); -- Elf_Addr startAddr =3D rdi(shdrs[lastReplaced + 1].sh_addr); -- string prevSection; -- for (unsigned int i =3D 1; i <=3D lastReplaced; ++i) { -- Elf_Shdr & shdr(shdrs[i]); -- string sectionName =3D 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) =3D=3D SHT_PROGBITS && sectionName !=3D ".= interp") -- || prevSection =3D=3D ".dynstr") -- { -- startOffset =3D rdi(shdr.sh_offset); -- startAddr =3D rdi(shdr.sh_addr); -- lastReplaced =3D i - 1; -- break; -+ i !=3D replacedSections.end(); ++i) { -+ shdr =3D findSection(i->first); -+ if (rdi(shdr.sh_flags) & SHF_WRITE) { -+ oldData +=3D rdi(shdr.sh_size); -+ neededData +=3D roundUp(i->second.size(), sectionAlignment); - } else { -- if (replacedSections.find(sectionName) =3D=3D replacedSection= s.end()) { -- debug("replacing section `%s' which is in the way\n", sec= tionName.c_str()); -- replaceSection(sectionName, rdi(shdr.sh_size)); -- } -+ oldCode +=3D rdi(shdr.sh_size); -+ neededCode +=3D roundUp(i->second.size(), sectionAlignment); - } -- prevSection =3D sectionName; - } -=20 -- debug("first reserved offset/addr is 0x%x/0x%llx\n", -- startOffset, (unsigned long long) startAddr); -- -- assert(startAddr % pageSize =3D=3D startOffset % pageSize); -- Elf_Addr firstPage =3D 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) >=3D startOffset); -- -- -- /* Compute the total space needed for the replaced sections, the -- ELF header, and the program headers. */ -- size_t neededSpace =3D sizeof(Elf_Ehdr) + phdrs.size() * sizeof(Elf_P= hdr); -- for (ReplacedSections::iterator i =3D replacedSections.begin(); -- i !=3D replacedSections.end(); ++i) -- neededSpace +=3D 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 +=3D sizeof(Elf_Phdr); -- debug("needed space is %d\n", neededSpace); -- -- unsigned int neededPages =3D roundUp(neededSpace - startOffset, p= ageSize) / pageSize; -- debug("needed pages is %d\n", neededPages); -- if (neededPages * pageSize > firstPage) -- error("virtual address space underrun!"); -- -- firstPage -=3D neededPages * pageSize; -- startOffset +=3D neededPages * pageSize; -- -- shiftFile(neededPages, firstPage); -- } -- -- -- /* Clear out the free space. */ -- Elf_Off curOff =3D 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); -=20 -+ /* 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); -=20 - /* Write out the replaced sections. */ -- writeReplacedSections(curOff, firstPage, 0); -- assert((off_t) curOff =3D=3D 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); -=20 - rewriteHeaders(firstPage + rdi(hdr->e_phoff)); - } -@@ -758,10 +685,10 @@ void ElfFile::rewriteSections() -=20 - if (rdi(hdr->e_type) =3D=3D ET_DYN) { - debug("this is a dynamic library\n"); -- rewriteSectionsLibrary(); -+ rewriteSectionsBinary(); - } else if (rdi(hdr->e_type) =3D=3D ET_EXEC) { - debug("this is an executable\n"); -- rewriteSectionsExecutable(); -+ rewriteSectionsBinary(); - } else error("unknown ELF type"); - } -=20 ---=20 -2.1.2 - --=20 2.24.0 --KsGdsel6WgEHnImy-- --ftEhullJWpWg/VHq Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEoov0DD5VE3JmLRT3Qarn3Mo9g1EFAl3HBIYACgkQQarn3Mo9 g1FAdQ/9FfEXXZeUzthfZinUEVdX77z+XUPlcWXkwnmdfJZO0tJVdUqfS58edp3r 7Ttxh/ApYJ2sQX30BZINvD6kIvrLVFEqfVjUHjhk23QoNJo9qO6FPXJ2yaP+Ama0 lefX52cw1x6ibJFDiZQvRgsQakJz0JTu96777HZvIG50ZsJ8E7hvirIGl2ut881L BYN2Q1JBARttfRzxkSm9ZBMOvQOjqPgmSTGHnrRB7Jh5x5nHMXQrcVOcysKKctDy 9VhLWzQhR6Rbnv347aB9d+Q2xyZeVJDH/CE2fv9JRsW3M43IqhPipxCIy+dxa/yJ AOBGDWubP7GqREPo/VwjEzzutW1bRqwuyaequX/T5rcnYM1rUoA5/YPc4iL09XPf T8iWKX8OAqM9Ypr0XmmLwZudzc6aAGtvPA5g8i2/nHUxszkig/Cz4jjVsTHlQZKC JAKAvRqpmd84xht450HCmA+FmSyiDeENqTforiSOJW9eQRdTcoE0RiNL7VJNTI2m 1fAb8m3MEdGdSHte0L999TT5EG3ITebQsM/AjpJGb95kfWXT0iTWx0Y9EazKKfuk t7SVpxZ2v+hvgjeBtQ40qhvqpi4kzInUVIPtKgOS1h194M2AQpsqx5UpOP99beg8 jOqar6t78dP9/URIoVs3jf9WWbA/QgTZCZ2jLMVjUGkml+pVglk= =GFta -----END PGP SIGNATURE----- --ftEhullJWpWg/VHq--