summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-03-20 07:48:00 -0300
committerJörg Thalheim <joerg@thalheim.io>2023-04-23 13:13:07 +0200
commit65cdee904431d16668f95d816a495bc35a05a192 (patch)
tree5b526a78bec49c80da4aefb0b4d1c2065702eae0
parent6e7b82e839414b8a2a47a9ff3a2bf90b091479ac (diff)
downloadpatchelf-65cdee904431d16668f95d816a495bc35a05a192.tar.gz
Resize segment mapping rewritten sections if needed
-rw-r--r--src/patchelf.cc12
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/short-first-segment.gzbin0 -> 170253 bytes
-rwxr-xr-xtests/short-first-segment.sh31
4 files changed, 45 insertions, 1 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc
index ee00918..82b4b46 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -1030,6 +1030,18 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
firstPage -= neededPages * getPageSize();
startOffset += neededPages * getPageSize();
+ } else {
+ Elf_Off rewrittenSectionsOffset = sizeof(Elf_Ehdr) + phdrs.size() * sizeof(Elf_Phdr);
+ for (auto& phdr : phdrs)
+ if (rdi(phdr.p_type) == PT_LOAD &&
+ rdi(phdr.p_offset) <= rewrittenSectionsOffset &&
+ rdi(phdr.p_offset) + rdi(phdr.p_filesz) > rewrittenSectionsOffset &&
+ rdi(phdr.p_filesz) < neededSpace)
+ {
+ wri(phdr.p_filesz, neededSpace);
+ wri(phdr.p_memsz, neededSpace);
+ break;
+ }
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5dba804..a68d2e2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -50,6 +50,7 @@ src_TESTS = \
rename-dynamic-symbols.sh \
overlapping-segments-after-rounding.sh \
shared-rpath.sh \
+ short-first-segment.sh \
empty-note.sh
build_TESTS = \
@@ -58,7 +59,7 @@ build_TESTS = \
TESTS = $(src_TESTS) $(build_TESTS)
EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness empty-note \
- overlapping-segments-after-rounding
+ overlapping-segments-after-rounding short-first-segment.gz
TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 STRIP=$(STRIP) OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY)
diff --git a/tests/short-first-segment.gz b/tests/short-first-segment.gz
new file mode 100755
index 0000000..c7ffdca
--- /dev/null
+++ b/tests/short-first-segment.gz
Binary files differ
diff --git a/tests/short-first-segment.sh b/tests/short-first-segment.sh
new file mode 100755
index 0000000..07019fc
--- /dev/null
+++ b/tests/short-first-segment.sh
@@ -0,0 +1,31 @@
+#! /bin/sh -e
+
+PATCHELF=$(readlink -f "../src/patchelf")
+SCRATCH="scratch/$(basename "$0" .sh)"
+READELF=${READELF:-readelf}
+
+EXEC_NAME="short-first-segment"
+
+if ! gzip --version >/dev/null; then
+ echo "skipping test: gzip not found"
+ exit 77
+fi
+
+if test "$(uname -i)" != x86_64 || test "$(uname)" != Linux; then
+ echo "skipping test: not supported on x86_64 Linux"
+ exit 77
+fi
+
+rm -rf "${SCRATCH}"
+mkdir -p "${SCRATCH}"
+
+gzip -c -d "${srcdir:?}/${EXEC_NAME}.gz" > "${SCRATCH}/${EXEC_NAME}"
+cd "${SCRATCH}"
+
+ldd "${EXEC_NAME}"
+
+${PATCHELF} --add-rpath lalalalalalalala --output modified1 "${EXEC_NAME}"
+ldd modified1
+
+${PATCHELF} --add-needed "libXcursor.so.1" --output modified2 modified1
+ldd modified2