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

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();
}
};