~ehmry/sigil

ebc724565bc5cbb0b99e1988c9d5d14cb15d7dad — Emery Hemingway 1 year, 9 months ago ba1d50a
Patchelf: Expand LOAD segment to cover new .dynstr and .dynsym sections
2 files changed, 65 insertions(+), 0 deletions(-)

M overlay/default.nix
A overlay/patchelf/dynstr.patch
M overlay/default.nix => overlay/default.nix +2 -0
@@ 167,6 167,8 @@ in nullPkgs // {
        "rm $out/bin/c_rehash"; # eliminate the perl runtime dependency
    }) openssl);

  patchelf = addPatchesTarget [ ./patchelf/dynstr.patch ] prev.patchelf;

  rsync = overrideHost {
    enableACLs = false;
    popt = null;

A overlay/patchelf/dynstr.patch => overlay/patchelf/dynstr.patch +63 -0
@@ 0,0 1,63 @@
From c66ec32bbdb88b0b4be0203c539bc6e91b471554 Mon Sep 17 00:00:00 2001
From: Emery Hemingway <ehmry@posteo.net>
Date: Fri, 19 Feb 2021 14:52:25 +0100
Subject: [PATCH] Expand LOAD segment to cover new .dynstr and .dynsym sections

---
 src/patchelf.cc | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/src/patchelf.cc b/src/patchelf.cc
index 50eb13a..f13f460 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -760,6 +760,46 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
         curOff += roundUp(i.second.size(), sectionAlignment);
     }
 
+    /* Expand the LOAD segment as neccessary */
+    for (auto & i : replacedSections) {
+        std::string sectionName = i.first;
+
+        /* If this is the .dynstr or .dynsym section, then a PT_LOAD segment
+           must contain it. */
+        if (sectionName == ".dynstr" || sectionName == ".dynsym") {
+            auto const & shdr = findSection(sectionName);
+            bool loaded = false;
+            for (auto & phdr : phdrs) {
+                if (rdi(phdr.p_type) == PT_LOAD) {
+                    if (rdi(phdr.p_offset) <= rdi(shdr.sh_offset) &&
+                        rdi(shdr.sh_size) <= rdi(phdr.p_filesz)) {
+                        debug("'%s' section is loaded\n", sectionName.c_str());
+                        loaded = true;
+                        break;
+                    }
+                }
+            }
+
+            if (!loaded) {
+                debug("'%s' was moved out of a load segment…\n", sectionName.c_str());
+                for (auto & phdr : phdrs) {
+                    if (rdi(phdr.p_type) == PT_LOAD) {
+                        if (rdi(shdr.sh_offset) < rdi(phdr.p_offset)) {
+                            Elf64_Xword gap = rdi(phdr.p_offset) - rdi(shdr.sh_offset);
+                            debug("grow PT_LOAD segment by 0x%x to cover '%s'\n",
+                                gap, sectionName.c_str());
+                            wri(phdr.p_filesz, rdi(phdr.p_filesz) + gap);
+                            wri(phdr.p_memsz, rdi(phdr.p_memsz) + gap);
+                            phdr.p_vaddr = phdr.p_paddr = shdr.sh_addr;
+                            phdr.p_offset = shdr.sh_offset;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     replacedSections.clear();
 }
 
-- 
2.29.2