* More duplicate code removal.

This commit is contained in:
Eelco Dolstra
2008-05-28 13:59:34 +00:00
parent 656349fd15
commit 0bba0e8b14

View File

@@ -57,11 +57,16 @@ class ElfFile
string sectionNames; /* content of the .shstrtab section */ string sectionNames; /* content of the .shstrtab section */
/* Align on 4 or 8 bytes boundaries on 32- or 64-bit platforms
respectively. */
unsigned int sectionAlignment;
public: public:
ElfFile() ElfFile()
{ {
changed = false; changed = false;
sectionAlignment = sizeof(Elf_Off);
} }
bool isChanged() bool isChanged()
@@ -114,12 +119,19 @@ private:
string & replaceSection(const SectionName & sectionName, string & replaceSection(const SectionName & sectionName,
unsigned int size); unsigned int size);
void writeReplacedSections(Elf_Off & curOff,
Elf_Addr startAddr, Elf_Off startOffset);
void rewriteHeaders(Elf_Addr phdrAddress);
void rewriteSectionsLibrary();
void rewriteSectionsExecutable();
public: public:
void rewriteSections(); void rewriteSections();
void rewriteHeaders(Elf_Addr phdrAddress);
string getInterpreter(); string getInterpreter();
void setInterpreter(const string & newInterpreter); void setInterpreter(const string & newInterpreter);
@@ -459,126 +471,115 @@ string & ElfFile<ElfFileParamNames>::replaceSection(const SectionName & sectionN
template<ElfFileParams> template<ElfFileParams>
void ElfFile<ElfFileParamNames>::rewriteSections() void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
Elf_Addr startAddr, Elf_Off startOffset)
{ {
if (replacedSections.empty()) return;
for (ReplacedSections::iterator i = replacedSections.begin(); for (ReplacedSections::iterator i = replacedSections.begin();
i != replacedSections.end(); ++i) i != replacedSections.end(); ++i)
debug("replacing section `%s' with size %d\n", {
i->first.c_str(), i->second.size()); string sectionName = i->first;
Elf_Shdr & shdr = findSection(sectionName);
debug("rewriting section `%s' from offset %d to offset %d\n",
/* Align on 4 or 8 bytes boundaries on 32- or 64-bit platforms sectionName.c_str(), rdi(shdr.sh_offset), curOff);
respectively. */
unsigned int sectionAlignment = sizeof(Elf_Off);
if (!findSection2(".interp")) {
debug("no .interp section; this is a dynamic library\n");
/* For dynamic libraries, we just place the replacement memset(contents + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
sections at the end of the file. They're mapped into memcpy(contents + curOff, (unsigned char *) i->second.c_str(),
memory by a PT_LOAD segment located directly after the last i->second.size());
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);
/* Update the section header for this section. */
/* Compute the total space needed for the replaced sections wri(shdr.sh_offset, curOff);
and the program headers. */ wri(shdr.sh_addr, startAddr + (curOff - startOffset));
off_t neededSpace = (phdrs.size() + 1) * sizeof(Elf_Phdr); wri(shdr.sh_size, i->second.size());
for (ReplacedSections::iterator i = replacedSections.begin(); wri(shdr.sh_addralign, sectionAlignment);
i != replacedSections.end(); ++i)
neededSpace += roundUp(i->second.size(), sectionAlignment);
debug("needed space is %d\n", neededSpace);
/* If this is the .interp section, then the PT_INTERP segment
off_t startOffset = roundUp(fileSize, pageSize); must be sync'ed with it. */
if (sectionName == ".interp") {
growFile(startOffset + neededSpace); for (unsigned int j = 0; j < phdrs.size(); ++j)
if (rdi(phdrs[j].p_type) == PT_INTERP) {
phdrs[j].p_offset = shdr.sh_offset;
/* Add a segment that maps the replaced sections and program phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
headers into memory.. */ phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
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, 4096);
/* Write out the replaced sections. */
off_t curOff = startOffset + phdrs.size() * sizeof(Elf_Phdr);
for (ReplacedSections::iterator i = replacedSections.begin();
i != replacedSections.end(); )
{
string sectionName = i->first;
Elf_Shdr & shdr = findSection(sectionName);
debug("rewriting section `%s' from offset %d to offset %d\n",
sectionName.c_str(), rdi(shdr.sh_offset), curOff);
memset(contents + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
memcpy(contents + curOff, (unsigned char *) i->second.c_str(),
i->second.size());
/* Update the section header for this section. */
wri(shdr.sh_offset, curOff);
wri(shdr.sh_addr, startPage + (curOff - startOffset));
wri(shdr.sh_size, i->second.size());
wri(shdr.sh_addralign, sectionAlignment);
/* If this is the .interp section, then the PT_INTERP segment
must be sync'ed with it. */
if (sectionName == ".interp") {
for (unsigned int j = 0; j < phdrs.size(); ++j)
if (rdi(phdrs[j].p_type) == PT_INTERP) {
phdrs[j].p_offset = shdr.sh_offset;
phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
}
}
/* If this is the .dynamic section, then the PT_DYNAMIC segment
must be sync'ed with it. */
if (sectionName == ".dynamic") {
for (unsigned int j = 0; j < phdrs.size(); ++j)
if (rdi(phdrs[j].p_type) == PT_DYNAMIC) {
phdrs[j].p_offset = shdr.sh_offset;
phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
}
}
curOff += roundUp(i->second.size(), sectionAlignment);
++i;
replacedSections.erase(sectionName);
} }
assert(replacedSections.empty()); /* If this is the .dynamic section, then the PT_DYNAMIC segment
assert((off_t) curOff == startOffset + neededSpace); must be sync'ed with it. */
if (sectionName == ".dynamic") {
for (unsigned int j = 0; j < phdrs.size(); ++j)
if (rdi(phdrs[j].p_type) == PT_DYNAMIC) {
phdrs[j].p_offset = shdr.sh_offset;
phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
}
}
curOff += roundUp(i->second.size(), sectionAlignment);
/* Move the program header to the start of the new area. */
wri(hdr->e_phoff, startOffset);
rewriteHeaders(startPage);
return;
} }
replacedSections.clear();
}
template<ElfFileParams>
void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
{
/* 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);
/* 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);
debug("needed space is %d\n", neededSpace);
off_t startOffset = roundUp(fileSize, pageSize);
growFile(startOffset + neededSpace);
/* 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, 4096);
/* 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 /* Sort the sections by offset, otherwise we won't correctly find
all the sections before the last replaced section. */ all the sections before the last replaced section. */
sortShdrs(); sortShdrs();
@@ -679,57 +680,33 @@ void ElfFile<ElfFileParamNames>::rewriteSections()
/* Write out the replaced sections. */ /* Write out the replaced sections. */
for (ReplacedSections::iterator i = replacedSections.begin(); writeReplacedSections(curOff, firstPage, 0);
i != replacedSections.end(); )
{
string sectionName = i->first;
debug("rewriting section `%s' to offset %d\n",
sectionName.c_str(), curOff);
memcpy(contents + curOff, (unsigned char *) i->second.c_str(),
i->second.size());
/* Update the section header for this section. */
Elf_Shdr & shdr = findSection(sectionName);
wri(shdr.sh_offset, curOff);
wri(shdr.sh_addr, firstPage + curOff);
wri(shdr.sh_size, i->second.size());
wri(shdr.sh_addralign, sectionAlignment);
/* If this is the .interp section, then the PT_INTERP segment
must be sync'ed with it. */
if (sectionName == ".interp") {
for (unsigned int j = 0; j < phdrs.size(); ++j)
if (rdi(phdrs[j].p_type) == PT_INTERP) {
phdrs[j].p_offset = shdr.sh_offset;
phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
}
}
/* If this is the .dynamic section, then the PT_DYNAMIC segment
must be sync'ed with it. */
if (sectionName == ".dynamic") {
for (unsigned int j = 0; j < phdrs.size(); ++j)
if (rdi(phdrs[j].p_type) == PT_DYNAMIC) {
phdrs[j].p_offset = shdr.sh_offset;
phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
}
}
curOff += roundUp(i->second.size(), sectionAlignment);
++i;
replacedSections.erase(sectionName);
}
assert(replacedSections.empty());
assert((off_t) curOff == neededSpace); assert((off_t) curOff == neededSpace);
rewriteHeaders(firstPage + rdi(hdr->e_phoff)); rewriteHeaders(firstPage + rdi(hdr->e_phoff));
} }
template<ElfFileParams>
void ElfFile<ElfFileParamNames>::rewriteSections()
{
if (replacedSections.empty()) return;
for (ReplacedSections::iterator i = replacedSections.begin();
i != replacedSections.end(); ++i)
debug("replacing section `%s' with size %d\n",
i->first.c_str(), i->second.size());
if (!findSection2(".interp")) {
debug("no .interp section; this is a dynamic library\n");
rewriteSectionsLibrary();
} else {
debug("found .interp section; this is an executable\n");
rewriteSectionsExecutable();
}
}
template<ElfFileParams> template<ElfFileParams>
void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress) void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)