Added patchelf.h

Added a header file to make things easier to navigate.

Renamed findSection3 -> getSectionIndex since thats more sensible to
read.

Renamed findSection -> findSectionHeader to better distinguish sections
from headers.
This commit is contained in:
Farid Zakaria
2021-12-20 14:54:37 -08:00
parent b73dbc1c91
commit 05e8f673f7
2 changed files with 212 additions and 193 deletions

View File

@@ -41,6 +41,7 @@
#include <unistd.h> #include <unistd.h>
#include "elf.h" #include "elf.h"
#include "patchelf.h"
#ifndef PACKAGE_STRING #ifndef PACKAGE_STRING
#define PACKAGE_STRING "patchelf" #define PACKAGE_STRING "patchelf"
@@ -63,11 +64,6 @@ static int forcedPageSize = -1;
#define EM_LOONGARCH 258 #define EM_LOONGARCH 258
#endif #endif
using FileContents = std::shared_ptr<std::vector<unsigned char>>;
#define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym, class Elf_Verneed, class Elf_Versym
#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Verneed, Elf_Versym
static std::vector<std::string> splitColonDelimitedString(const char * s) static std::vector<std::string> splitColonDelimitedString(const char * s)
{ {
@@ -85,163 +81,6 @@ static bool hasAllowedPrefix(const std::string & s, const std::vector<std::strin
return std::any_of(allowedPrefixes.begin(), allowedPrefixes.end(), [&](const std::string & i) { return !s.compare(0, i.size(), i); }); return std::any_of(allowedPrefixes.begin(), allowedPrefixes.end(), [&](const std::string & i) { return !s.compare(0, i.size(), i); });
} }
template<ElfFileParams>
class ElfFile
{
public:
const FileContents fileContents;
private:
std::vector<Elf_Phdr> phdrs;
std::vector<Elf_Shdr> shdrs;
bool littleEndian;
bool changed = false;
bool isExecutable = false;
using SectionName = std::string;
using ReplacedSections = std::map<SectionName, std::string>;
ReplacedSections replacedSections;
std::string sectionNames; /* content of the .shstrtab section */
/* Align on 4 or 8 bytes boundaries on 32- or 64-bit platforms
respectively. */
size_t sectionAlignment = sizeof(Elf_Off);
std::vector<SectionName> sectionsByOldIndex;
public:
explicit ElfFile(FileContents fileContents);
bool isChanged()
{
return changed;
}
private:
struct CompPhdr
{
ElfFile * elfFile;
bool operator ()(const Elf_Phdr & x, const Elf_Phdr & y)
{
// A PHDR comes before everything else.
if (elfFile->rdi(y.p_type) == PT_PHDR) return false;
if (elfFile->rdi(x.p_type) == PT_PHDR) return true;
// Sort non-PHDRs by address.
return elfFile->rdi(x.p_paddr) < elfFile->rdi(y.p_paddr);
}
};
friend struct CompPhdr;
void sortPhdrs();
struct CompShdr
{
ElfFile * elfFile;
bool operator ()(const Elf_Shdr & x, const Elf_Shdr & y)
{
return elfFile->rdi(x.sh_offset) < elfFile->rdi(y.sh_offset);
}
};
friend struct CompShdr;
unsigned int getPageSize() const;
void sortShdrs();
void shiftFile(unsigned int extraPages, Elf_Addr startPage);
std::string getSectionName(const Elf_Shdr & shdr) const;
Elf_Shdr & findSection(const SectionName & sectionName);
std::optional<std::reference_wrapper<Elf_Shdr>> findSection2(const SectionName & sectionName);
unsigned int findSection3(const SectionName & sectionName);
std::string & replaceSection(const SectionName & sectionName,
unsigned int size);
bool haveReplacedSection(const SectionName & sectionName) const;
void writeReplacedSections(Elf_Off & curOff,
Elf_Addr startAddr, Elf_Off startOffset);
void rewriteHeaders(Elf_Addr phdrAddress);
void rewriteSectionsLibrary();
void rewriteSectionsExecutable();
void normalizeNoteSegments();
public:
void rewriteSections();
std::string getInterpreter();
typedef enum { printSoname, replaceSoname } sonameMode;
void modifySoname(sonameMode op, const std::string & newSoname);
void setInterpreter(const std::string & newInterpreter);
typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
void modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath);
std::string shrinkRPath(char* rpath, std::vector<std::string> &neededLibs, const std::vector<std::string> & allowedRpathPrefixes);
void removeRPath(Elf_Shdr & shdrDynamic);
void addNeeded(const std::set<std::string> & libs);
void removeNeeded(const std::set<std::string> & libs);
void replaceNeeded(const std::map<std::string, std::string> & libs);
void printNeededLibs() /* should be const */;
void noDefaultLib();
void clearSymbolVersions(const std::set<std::string> & syms);
private:
/* Convert an integer in big or little endian representation (as
specified by the ELF header) to this platform's integer
representation. */
template<class I>
I rdi(I i) const;
/* Convert back to the ELF representation. */
template<class I>
I wri(I & t, unsigned long long i) const
{
t = rdi((I) i);
return i;
}
Elf_Ehdr *hdr() {
return (Elf_Ehdr *)fileContents->data();
}
const Elf_Ehdr *hdr() const {
return (const Elf_Ehdr *)fileContents->data();
}
};
/* !!! G++ creates broken code if this function is inlined, don't know /* !!! G++ creates broken code if this function is inlined, don't know
why... */ why... */
template<ElfFileParams> template<ElfFileParams>
@@ -630,7 +469,7 @@ std::string ElfFile<ElfFileParamNames>::getSectionName(const Elf_Shdr & shdr) co
template<ElfFileParams> template<ElfFileParams>
Elf_Shdr & ElfFile<ElfFileParamNames>::findSection(const SectionName & sectionName) Elf_Shdr & ElfFile<ElfFileParamNames>::findSectionHeader(const SectionName & sectionName)
{ {
auto shdr = findSection2(sectionName); auto shdr = findSection2(sectionName);
if (!shdr) { if (!shdr) {
@@ -654,7 +493,7 @@ std::optional<std::reference_wrapper<Elf_Shdr>> ElfFile<ElfFileParamNames>::find
template<ElfFileParams> template<ElfFileParams>
unsigned int ElfFile<ElfFileParamNames>::findSection3(const SectionName & sectionName) unsigned int ElfFile<ElfFileParamNames>::getSectionIndex(const SectionName & sectionName)
{ {
for (unsigned int i = 1; i < rdi(hdr()->e_shnum); ++i) for (unsigned int i = 1; i < rdi(hdr()->e_shnum); ++i)
if (getSectionName(shdrs.at(i)) == sectionName) return i; if (getSectionName(shdrs.at(i)) == sectionName) return i;
@@ -677,7 +516,7 @@ std::string & ElfFile<ElfFileParamNames>::replaceSection(const SectionName & sec
if (i != replacedSections.end()) { if (i != replacedSections.end()) {
s = std::string(i->second); s = std::string(i->second);
} else { } else {
auto shdr = findSection(sectionName); auto shdr = findSectionHeader(sectionName);
s = std::string((char *) fileContents->data() + rdi(shdr.sh_offset), rdi(shdr.sh_size)); s = std::string((char *) fileContents->data() + rdi(shdr.sh_offset), rdi(shdr.sh_size));
} }
@@ -697,7 +536,7 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
clobbering previously written new section contents. */ clobbering previously written new section contents. */
for (auto & i : replacedSections) { for (auto & i : replacedSections) {
const std::string & sectionName = i.first; const std::string & sectionName = i.first;
Elf_Shdr & shdr = findSection(sectionName); Elf_Shdr & shdr = findSectionHeader(sectionName);
if (rdi(shdr.sh_type) != SHT_NOBITS) if (rdi(shdr.sh_type) != SHT_NOBITS)
memset(fileContents->data() + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size)); memset(fileContents->data() + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
} }
@@ -705,7 +544,7 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
std::set<unsigned int> noted_phdrs = {}; std::set<unsigned int> noted_phdrs = {};
for (auto & i : replacedSections) { for (auto & i : replacedSections) {
const std::string & sectionName = i.first; const std::string & sectionName = i.first;
auto & shdr = findSection(sectionName); auto & shdr = findSectionHeader(sectionName);
Elf_Shdr orig_shdr = shdr; Elf_Shdr orig_shdr = shdr;
debug("rewriting section '%s' from offset 0x%x (size %d) to offset 0x%x (size %d)\n", 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()); sectionName.c_str(), rdi(shdr.sh_offset), rdi(shdr.sh_size), curOff, i.second.size());
@@ -1024,7 +863,7 @@ void ElfFile<ElfFileParamNames>::normalizeNoteSegments()
/* We don't need to do anything if no note segments were replaced. */ /* We don't need to do anything if no note segments were replaced. */
bool replaced_note = std::any_of(replacedSections.begin(), replacedSections.end(), bool replaced_note = std::any_of(replacedSections.begin(), replacedSections.end(),
[this](std::pair<const std::string, std::string> & i) { return rdi(findSection(i.first).sh_type) == SHT_NOTE; }); [this](std::pair<const std::string, std::string> & i) { return rdi(findSectionHeader(i.first).sh_type) == SHT_NOTE; });
if (!replaced_note) return; if (!replaced_note) return;
std::vector<Elf_Phdr> newPhdrs; std::vector<Elf_Phdr> newPhdrs;
@@ -1134,13 +973,13 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
unsigned int d_tag; unsigned int d_tag;
for (auto dyn = dyn_table; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++) for (auto dyn = dyn_table; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++)
if (d_tag == DT_STRTAB) if (d_tag == DT_STRTAB)
dyn->d_un.d_ptr = findSection(".dynstr").sh_addr; dyn->d_un.d_ptr = findSectionHeader(".dynstr").sh_addr;
else if (d_tag == DT_STRSZ) else if (d_tag == DT_STRSZ)
dyn->d_un.d_val = findSection(".dynstr").sh_size; dyn->d_un.d_val = findSectionHeader(".dynstr").sh_size;
else if (d_tag == DT_SYMTAB) else if (d_tag == DT_SYMTAB)
dyn->d_un.d_ptr = findSection(".dynsym").sh_addr; dyn->d_un.d_ptr = findSectionHeader(".dynsym").sh_addr;
else if (d_tag == DT_HASH) else if (d_tag == DT_HASH)
dyn->d_un.d_ptr = findSection(".hash").sh_addr; dyn->d_un.d_ptr = findSectionHeader(".hash").sh_addr;
else if (d_tag == DT_GNU_HASH) { else if (d_tag == DT_GNU_HASH) {
auto shdr = findSection2(".gnu.hash"); auto shdr = findSection2(".gnu.hash");
// some binaries might this section stripped // some binaries might this section stripped
@@ -1172,15 +1011,15 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
dyn->d_un.d_ptr = (*shdr).get().sh_addr; dyn->d_un.d_ptr = (*shdr).get().sh_addr;
} }
else if (d_tag == DT_VERNEED) else if (d_tag == DT_VERNEED)
dyn->d_un.d_ptr = findSection(".gnu.version_r").sh_addr; dyn->d_un.d_ptr = findSectionHeader(".gnu.version_r").sh_addr;
else if (d_tag == DT_VERSYM) else if (d_tag == DT_VERSYM)
dyn->d_un.d_ptr = findSection(".gnu.version").sh_addr; dyn->d_un.d_ptr = findSectionHeader(".gnu.version").sh_addr;
else if (d_tag == DT_MIPS_RLD_MAP_REL) { else if (d_tag == DT_MIPS_RLD_MAP_REL) {
/* the MIPS_RLD_MAP_REL tag stores the offset to the debug /* the MIPS_RLD_MAP_REL tag stores the offset to the debug
pointer, relative to the address of the tag */ pointer, relative to the address of the tag */
auto shdr = findSection2(".rld_map"); auto shdr = findSection2(".rld_map");
if (shdr) { if (shdr) {
auto rld_map_addr = findSection(".rld_map").sh_addr; auto rld_map_addr = findSectionHeader(".rld_map").sh_addr;
auto dyn_offset = ((char*)dyn) - ((char*)dyn_table); auto dyn_offset = ((char*)dyn) - ((char*)dyn_table);
dyn->d_un.d_ptr = rld_map_addr + dyn_offset - (*shdrDynamic).get().sh_addr; dyn->d_un.d_ptr = rld_map_addr + dyn_offset - (*shdrDynamic).get().sh_addr;
} else { } else {
@@ -1236,7 +1075,7 @@ static void setSubstr(std::string & s, unsigned int pos, const std::string & t)
template<ElfFileParams> template<ElfFileParams>
std::string ElfFile<ElfFileParamNames>::getInterpreter() std::string ElfFile<ElfFileParamNames>::getInterpreter()
{ {
auto shdr = findSection(".interp"); auto shdr = findSectionHeader(".interp");
return std::string((char *) fileContents->data() + rdi(shdr.sh_offset), rdi(shdr.sh_size) - 1); return std::string((char *) fileContents->data() + rdi(shdr.sh_offset), rdi(shdr.sh_size) - 1);
} }
@@ -1248,8 +1087,8 @@ void ElfFile<ElfFileParamNames>::modifySoname(sonameMode op, const std::string &
return; return;
} }
auto shdrDynamic = findSection(".dynamic"); auto shdrDynamic = findSectionHeader(".dynamic");
auto shdrDynStr = findSection(".dynstr"); auto shdrDynStr = findSectionHeader(".dynstr");
char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset); char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset);
/* Walk through the dynamic section, look for the DT_SONAME entry. */ /* Walk through the dynamic section, look for the DT_SONAME entry. */
@@ -1401,7 +1240,7 @@ template<ElfFileParams>
void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath) const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath)
{ {
auto shdrDynamic = findSection(".dynamic"); auto shdrDynamic = findSectionHeader(".dynamic");
if (rdi(shdrDynamic.sh_type) == SHT_NOBITS) { if (rdi(shdrDynamic.sh_type) == SHT_NOBITS) {
debug("no dynamic section\n"); debug("no dynamic section\n");
@@ -1410,7 +1249,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
/* !!! We assume that the virtual address in the DT_STRTAB entry /* !!! We assume that the virtual address in the DT_STRTAB entry
of the dynamic section corresponds to the .dynstr section. */ of the dynamic section corresponds to the .dynstr section. */
auto shdrDynStr = findSection(".dynstr"); auto shdrDynStr = findSectionHeader(".dynstr");
char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset); char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset);
@@ -1549,8 +1388,8 @@ void ElfFile<ElfFileParamNames>::removeNeeded(const std::set<std::string> & libs
{ {
if (libs.empty()) return; if (libs.empty()) return;
auto shdrDynamic = findSection(".dynamic"); auto shdrDynamic = findSectionHeader(".dynamic");
auto shdrDynStr = findSection(".dynstr"); auto shdrDynStr = findSectionHeader(".dynstr");
char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset); char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset);
auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset)); auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset));
@@ -1577,8 +1416,8 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(const std::map<std::string, std::
{ {
if (libs.empty()) return; if (libs.empty()) return;
auto shdrDynamic = findSection(".dynamic"); auto shdrDynamic = findSectionHeader(".dynamic");
auto shdrDynStr = findSection(".dynstr"); auto shdrDynStr = findSectionHeader(".dynstr");
char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset); char * strTab = (char *) fileContents->data() + rdi(shdrDynStr.sh_offset);
auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset)); auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset));
@@ -1634,7 +1473,7 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(const std::map<std::string, std::
// be replaced. // be replaced.
if (verNeedNum) { if (verNeedNum) {
auto shdrVersionR = findSection(".gnu.version_r"); auto shdrVersionR = findSectionHeader(".gnu.version_r");
// The filename strings in the .gnu.version_r are different from the // The filename strings in the .gnu.version_r are different from the
// ones in .dynamic: instead of being in .dynstr, they're in some // ones in .dynamic: instead of being in .dynstr, they're in some
// arbitrary section and we have to look in ->sh_link to figure out // arbitrary section and we have to look in ->sh_link to figure out
@@ -1700,8 +1539,8 @@ void ElfFile<ElfFileParamNames>::addNeeded(const std::set<std::string> & libs)
{ {
if (libs.empty()) return; if (libs.empty()) return;
auto shdrDynamic = findSection(".dynamic"); auto shdrDynamic = findSectionHeader(".dynamic");
auto shdrDynStr = findSection(".dynstr"); auto shdrDynStr = findSectionHeader(".dynstr");
unsigned int length = 0; unsigned int length = 0;
@@ -1748,8 +1587,8 @@ void ElfFile<ElfFileParamNames>::addNeeded(const std::set<std::string> & libs)
template<ElfFileParams> template<ElfFileParams>
void ElfFile<ElfFileParamNames>::printNeededLibs() // const void ElfFile<ElfFileParamNames>::printNeededLibs() // const
{ {
const auto shdrDynamic = findSection(".dynamic"); const auto shdrDynamic = findSectionHeader(".dynamic");
const auto shdrDynStr = findSection(".dynstr"); const auto shdrDynStr = findSectionHeader(".dynstr");
const char *strTab = (char *)fileContents->data() + rdi(shdrDynStr.sh_offset); const char *strTab = (char *)fileContents->data() + rdi(shdrDynStr.sh_offset);
const Elf_Dyn *dyn = (Elf_Dyn *) (fileContents->data() + rdi(shdrDynamic.sh_offset)); const Elf_Dyn *dyn = (Elf_Dyn *) (fileContents->data() + rdi(shdrDynamic.sh_offset));
@@ -1766,7 +1605,7 @@ void ElfFile<ElfFileParamNames>::printNeededLibs() // const
template<ElfFileParams> template<ElfFileParams>
void ElfFile<ElfFileParamNames>::noDefaultLib() void ElfFile<ElfFileParamNames>::noDefaultLib()
{ {
auto shdrDynamic = findSection(".dynamic"); auto shdrDynamic = findSectionHeader(".dynamic");
auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset)); auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset));
auto dynFlags1 = (Elf_Dyn *)nullptr; auto dynFlags1 = (Elf_Dyn *)nullptr;
@@ -1807,9 +1646,9 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
{ {
if (syms.empty()) return; if (syms.empty()) return;
auto shdrDynStr = findSection(".dynstr"); auto shdrDynStr = findSectionHeader(".dynstr");
auto shdrDynsym = findSection(".dynsym"); auto shdrDynsym = findSectionHeader(".dynsym");
auto shdrVersym = findSection(".gnu.version"); auto shdrVersym = findSectionHeader(".gnu.version");
auto strTab = (char *)fileContents->data() + rdi(shdrDynStr.sh_offset); auto strTab = (char *)fileContents->data() + rdi(shdrDynStr.sh_offset);
auto dynsyms = (Elf_Sym *)(fileContents->data() + rdi(shdrDynsym.sh_offset)); auto dynsyms = (Elf_Sym *)(fileContents->data() + rdi(shdrDynsym.sh_offset));

180
src/patchelf.h Normal file
View File

@@ -0,0 +1,180 @@
using FileContents = std::shared_ptr<std::vector<unsigned char>>;
#define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym, class Elf_Verneed, class Elf_Versym
#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Verneed, Elf_Versym
template<ElfFileParams>
class ElfFile
{
/**
* @brief The ELF section header
*
*/
class Section {
public:
const std::string & getName() {
return name;
}
const Elf_Shdr * toStruct() {
return (Elf_Shdr *) this->data.data();
}
void resize(unsigned int size) {
data.resize(size, '\0');
}
private:
std::string name;
std::vector<unsigned char> data;
};
public:
const FileContents fileContents;
private:
std::vector<Elf_Phdr> phdrs;
std::vector<Elf_Shdr> shdrs;
bool littleEndian;
bool changed = false;
bool isExecutable = false;
using SectionName = std::string;
using ReplacedSections = std::map<SectionName, std::string>;
ReplacedSections replacedSections;
std::string sectionNames; /* content of the .shstrtab section */
/* Align on 4 or 8 bytes boundaries on 32- or 64-bit platforms
respectively. */
size_t sectionAlignment = sizeof(Elf_Off);
std::vector<SectionName> sectionsByOldIndex;
public:
explicit ElfFile(FileContents fileContents);
bool isChanged()
{
return changed;
}
private:
struct CompPhdr
{
ElfFile * elfFile;
bool operator ()(const Elf_Phdr & x, const Elf_Phdr & y)
{
// A PHDR comes before everything else.
if (elfFile->rdi(y.p_type) == PT_PHDR) return false;
if (elfFile->rdi(x.p_type) == PT_PHDR) return true;
// Sort non-PHDRs by address.
return elfFile->rdi(x.p_paddr) < elfFile->rdi(y.p_paddr);
}
};
friend struct CompPhdr;
void sortPhdrs();
struct CompShdr
{
ElfFile * elfFile;
bool operator ()(const Elf_Shdr & x, const Elf_Shdr & y)
{
return elfFile->rdi(x.sh_offset) < elfFile->rdi(y.sh_offset);
}
};
friend struct CompShdr;
unsigned int getPageSize() const;
void sortShdrs();
void shiftFile(unsigned int extraPages, Elf_Addr startPage);
std::string getSectionName(const Elf_Shdr & shdr) const;
Elf_Shdr & findSectionHeader(const SectionName & sectionName);
std::optional<std::reference_wrapper<Elf_Shdr>> findSection2(const SectionName & sectionName);
unsigned int getSectionIndex(const SectionName & sectionName);
std::string & replaceSection(const SectionName & sectionName,
unsigned int size);
bool haveReplacedSection(const SectionName & sectionName) const;
void writeReplacedSections(Elf_Off & curOff,
Elf_Addr startAddr, Elf_Off startOffset);
void rewriteHeaders(Elf_Addr phdrAddress);
void rewriteSectionsLibrary();
void rewriteSectionsExecutable();
void normalizeNoteSegments();
public:
void rewriteSections();
std::string getInterpreter();
typedef enum { printSoname, replaceSoname } sonameMode;
void modifySoname(sonameMode op, const std::string & newSoname);
void setInterpreter(const std::string & newInterpreter);
typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
void modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath);
std::string shrinkRPath(char* rpath, std::vector<std::string> &neededLibs, const std::vector<std::string> & allowedRpathPrefixes);
void removeRPath(Elf_Shdr & shdrDynamic);
void addNeeded(const std::set<std::string> & libs);
void removeNeeded(const std::set<std::string> & libs);
void replaceNeeded(const std::map<std::string, std::string> & libs);
void printNeededLibs() /* should be const */;
void noDefaultLib();
void clearSymbolVersions(const std::set<std::string> & syms);
private:
/* Convert an integer in big or little endian representation (as
specified by the ELF header) to this platform's integer
representation. */
template<class I>
I rdi(I i) const;
/* Convert back to the ELF representation. */
template<class I>
I wri(I & t, unsigned long long i) const
{
t = rdi((I) i);
return i;
}
Elf_Ehdr *hdr() {
return (Elf_Ehdr *)fileContents->data();
}
const Elf_Ehdr *hdr() const {
return (const Elf_Ehdr *)fileContents->data();
}
};