Skip to content

Commit

Permalink
Merge pull request #2 from cmatsuoka/0.9+snapcraft
Browse files Browse the repository at this point in the history
Local patches for patchelf 0.9
  • Loading branch information
sergiusens authored Apr 10, 2019
2 parents 44b7f95 + 27c0ba1 commit c102bf9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AM_CXXFLAGS = -Wall
AM_CXXFLAGS = -Wall -std=c++11

bin_PROGRAMS = patchelf

Expand Down
88 changes: 47 additions & 41 deletions src/patchelf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ class ElfFile
string & replaceSection(const SectionName & sectionName,
unsigned int size);

bool haveReplacedSection(const SectionName & sectionName);

void writeReplacedSections(Elf_Off & curOff,
Elf_Addr startAddr, Elf_Off startOffset);

Expand Down Expand Up @@ -366,7 +368,7 @@ void ElfFile<ElfFileParamNames>::sortShdrs()
/* Sort the sections by offset. */
CompShdr comp;
comp.elfFile = this;
sort(shdrs.begin(), shdrs.end(), comp);
sort(shdrs.begin() + 1, shdrs.end(), comp);

/* Restore the sh_link mappings. */
for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i)
Expand Down Expand Up @@ -483,6 +485,15 @@ unsigned int ElfFile<ElfFileParamNames>::findSection3(const SectionName & sectio
return 0;
}

template<ElfFileParams>
bool ElfFile<ElfFileParamNames>::haveReplacedSection(const SectionName & sectionName)
{
ReplacedSections::iterator i = replacedSections.find(sectionName);

if (i != replacedSections.end())
return true;
return false;
}

template<ElfFileParams>
string & ElfFile<ElfFileParamNames>::replaceSection(const SectionName & sectionName,
Expand Down Expand Up @@ -517,7 +528,8 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
{
string sectionName = i->first;
Elf_Shdr & shdr = findSection(sectionName);
memset(contents + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
if (shdr.sh_type != SHT_NOBITS)
memset(contents + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
}

for (ReplacedSections::iterator i = replacedSections.begin();
Expand Down Expand Up @@ -581,52 +593,49 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()

debug("last page is 0x%llx\n", (unsigned long long) startPage);

/* Because we're adding a new section header, we're necessarily increasing
the size of the program header table. This can cause the first section
to overlap the program header table in memory; we need to shift the first
few segments to someplace else. */
/* Some sections may already be replaced so account for that */
unsigned int i = 1;
Elf_Addr pht_size = sizeof(Elf_Ehdr) + (phdrs.size() + 1)*sizeof(Elf_Phdr);
while( shdrs[i].sh_addr <= pht_size && i < rdi(hdr->e_shnum) ) {
if (not haveReplacedSection(getSectionName(shdrs[i])))
replaceSection(getSectionName(shdrs[i]), shdrs[i].sh_size);
i++;
}

/* Compute the total space needed for the replaced sections and
the program headers. */
off_t neededSpace = (phdrs.size() + 1) * sizeof(Elf_Phdr);
for (ReplacedSections::iterator i = replacedSections.begin();
i != replacedSections.end(); ++i)
neededSpace += roundUp(i->second.size(), sectionAlignment);
/* Compute the total space needed for the replaced sections */
off_t neededSpace = 0;
for (auto & i : replacedSections)
neededSpace += roundUp(i.second.size(), sectionAlignment);
debug("needed space is %d\n", neededSpace);


size_t startOffset = roundUp(fileSize, getPageSize());

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
ET_DYN as does LD when linking with pie. If we move PT_PHDR, it
has to stay in the first PT_LOAD segment or any subsequent ones
if they're continuous in memory due to linux kernel constraints
(see BUGS). Since the end of the file would be after bss, we can't
move PHDR there, we therefore choose to leave PT_PHDR where it is but
move enough following sections such that we can add the extra PT_LOAD
section to it. This PT_LOAD segment ensures the sections at the end of
the file are mapped into memory for ld.so to process.
We can't use the approach in rewriteSectionsExecutable()
since DYN executables 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 % getPageSize() == 0);
/* !!! We could create an actual hole in the file here,
but it's probably not worth the effort. */
growFile(fileSize + hole);
startOffset += hole;
}
any virtual address space to grow downwards into. */
if (isExecutable && startOffset > startPage) {
debug("shifting new PT_LOAD segment by %d bytes to work around a Linux kernel bug\n", startOffset - startPage);
startPage = startOffset;
}


/* Add a segment that maps the replaced sections and program
headers into memory. */
/* Add a segment that maps the replaced sections 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];
Expand All @@ -639,15 +648,12 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()


/* Write out the replaced sections. */
Elf_Off curOff = startOffset + phdrs.size() * sizeof(Elf_Phdr);
Elf_Off curOff = startOffset;
writeReplacedSections(curOff, startPage, startOffset);
assert(curOff == startOffset + neededSpace);


/* Move the program header to the start of the new area. */
wri(hdr->e_phoff, startOffset);

rewriteHeaders(startPage);
/* Write out the updated program and section headers */
rewriteHeaders(hdr->e_phoff);
}


Expand Down
9 changes: 5 additions & 4 deletions tests/no-rpath-prebuild.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#! /bin/sh -e
set -x
ARCH="$1"
PAGESIZE=4096

if [ -z "$ARCH" ]; then
ARCH=$(basename $0 .sh | sed -e 's/.*-//')
Expand All @@ -25,13 +26,13 @@ mkdir -p ${SCRATCH}

cp $no_rpath_bin ${SCRATCH}/no-rpath

oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath)
oldRPath=$(../src/patchelf --page-size ${PAGESIZE} --print-rpath ${SCRATCH}/no-rpath)
if test -n "$oldRPath"; then exit 1; fi
../src/patchelf \
--set-interpreter "$(../src/patchelf --print-interpreter ../src/patchelf)" \
../src/patchelf --page-size ${PAGESIZE} \
--set-interpreter "$(../src/patchelf --page-size ${PAGESIZE} --print-interpreter ../src/patchelf)" \
--set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath

newRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath)
newRPath=$(../src/patchelf --page-size ${PAGESIZE} --print-rpath ${SCRATCH}/no-rpath)
if ! echo "$newRPath" | grep -q '/foo:/bar'; then
echo "incomplete RPATH"
exit 1
Expand Down

0 comments on commit c102bf9

Please sign in to comment.