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.
This commit is contained in:
Efraim Flashner 2019-11-09 20:19:11 +02:00
parent 4e4f3a6b76
commit 0d01a5a9d4
No known key found for this signature in database
GPG key ID: 41AAE7DCCA3D8351
4 changed files with 19 additions and 567 deletions

View file

@ -1205,8 +1205,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 \

View file

@ -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 @@ (define-module (gnu packages elf)
#: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 @@ (define-public libelf
(define-public patchelf
(package
(name "patchelf")
(version "0.8")
(version "0.10")
(source (origin
(method url-fetch)
(uri (string-append
@ -207,28 +208,24 @@ (define-public patchelf
"/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"
;; Disable checking for an empty runpath:
(("^if test.*") "")
;; Find libgcc_s.so, which is necessary for the 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

View file

@ -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

View file

@ -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