Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions ElfReader.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ ElfReader::~ElfReader() {
}
}

bool ElfReader::Load() {
bool ElfReader::Load(size_t page_size) {
// try open
return ReadElfHeader() &&
VerifyElfHeader() &&
ReadProgramHeader() &&
// TODO READ dynamic from SECTION header (>= __ANDROID_API_O__)
ReserveAddressSpace() &&
ReserveAddressSpace(page_size) &&
LoadSegments() &&
FindPhdr();
}
Expand Down Expand Up @@ -212,6 +212,7 @@ bool ElfReader::ReadProgramHeader() {
*/
size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table,
size_t phdr_count,
size_t page_size,
Elf_Addr* out_min_vaddr,
Elf_Addr* out_max_vaddr)
{
Expand Down Expand Up @@ -243,8 +244,8 @@ size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table,
min_vaddr = 0x00000000U;
}

min_vaddr = PAGE_START(min_vaddr);
max_vaddr = PAGE_END(max_vaddr);
min_vaddr = PAGE_START(min_vaddr, page_size);
max_vaddr = PAGE_END(max_vaddr, page_size);

if (out_min_vaddr != NULL) {
*out_min_vaddr = min_vaddr;
Expand All @@ -258,9 +259,9 @@ size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table,
// Reserve a virtual address range big enough to hold all loadable
// segments of a program header table. This is done by creating a
// private anonymous mmap() with PROT_NONE.
bool ElfReader::ReserveAddressSpace(uint32_t padding_size) {
bool ElfReader::ReserveAddressSpace(size_t page_size, uint32_t padding_size) {
Elf_Addr min_vaddr;
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, page_size, &min_vaddr);
if (load_size_ == 0) {
FLOGE("\"%s\" has no loadable segments", name_);
return false;
Expand Down Expand Up @@ -325,7 +326,7 @@ bool ElfReader::LoadSegments() {
// if the segment is writable, and does not end on a page boundary,
// zero-fill it until the page limit.
// if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
// memset(seg_file_end + reinterpret_cast<uint8_t *>(load_bias_), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
// memset(seg_file_end + reinterpret_cast<uint8_t *>(load_bias_), 0, page_size - PAGE_OFFSET(seg_file_end));
// }

// seg_file_end = PAGE_END(seg_file_end);
Expand All @@ -351,7 +352,8 @@ static int
_phdr_table_set_load_prot(const Elf_Phdr* phdr_table,
int phdr_count,
uint8_t *load_bias,
int extra_prot_flags)
int extra_prot_flags,
size_t page_size)
{
const Elf_Phdr* phdr = phdr_table;
const Elf_Phdr* phdr_limit = phdr + phdr_count;
Expand All @@ -360,8 +362,8 @@ _phdr_table_set_load_prot(const Elf_Phdr* phdr_table,
if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0)
continue;

auto seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
auto seg_page_start = PAGE_START(phdr->p_vaddr, page_size) + load_bias;
auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz, page_size) + load_bias;

auto ret = 0;

Expand Down Expand Up @@ -389,10 +391,11 @@ _phdr_table_set_load_prot(const Elf_Phdr* phdr_table,
int
phdr_table_protect_segments(const Elf_Phdr* phdr_table,
int phdr_count,
uint8_t *load_bias)
uint8_t *load_bias,
size_t page_size)
{
return _phdr_table_set_load_prot(phdr_table, phdr_count,
load_bias, 0);
load_bias, 0, page_size);
}

/* Change the protection of all loaded segments in memory to writable.
Expand All @@ -414,10 +417,11 @@ phdr_table_protect_segments(const Elf_Phdr* phdr_table,
int
phdr_table_unprotect_segments(const Elf_Phdr* phdr_table,
int phdr_count,
uint8_t *load_bias)
uint8_t *load_bias,
size_t page_size)
{
return _phdr_table_set_load_prot(phdr_table, phdr_count,
load_bias, /*PROT_WRITE*/0);
load_bias, /*PROT_WRITE*/0, page_size);
}

/* Used internally by phdr_table_protect_gnu_relro and
Expand All @@ -427,7 +431,8 @@ static int
_phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table,
int phdr_count,
uint8_t *load_bias,
int prot_flags)
int prot_flags,
size_t page_size)
{
const Elf_Phdr* phdr = phdr_table;
const Elf_Phdr* phdr_limit = phdr + phdr_count;
Expand All @@ -453,8 +458,8 @@ _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table,
* linker must only emit a PT_GNU_RELRO segment if it ensures
* that it starts on a page boundary.
*/
auto seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
auto seg_page_start = PAGE_START(phdr->p_vaddr, page_size) + load_bias;
auto seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz, page_size) + load_bias;

auto ret = 0;
// int ret = mprotect((void*)seg_page_start,
Expand Down Expand Up @@ -486,12 +491,13 @@ _phdr_table_set_gnu_relro_prot(const Elf_Phdr* phdr_table,
int
phdr_table_protect_gnu_relro(const Elf_Phdr* phdr_table,
int phdr_count,
uint8_t *load_bias)
uint8_t *load_bias,
size_t page_size)
{
return _phdr_table_set_gnu_relro_prot(phdr_table,
phdr_count,
load_bias,
/*PROT_READ*/0);
/*PROT_READ*/0, page_size);
}


Expand Down
5 changes: 3 additions & 2 deletions ElfReader.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ElfReader {
ElfReader();
virtual ~ElfReader();

virtual bool Load();
virtual bool Load(size_t page_size);
bool setSource(const char* source);

size_t phdr_count() { return phdr_num_; }
Expand All @@ -41,7 +41,7 @@ class ElfReader {
bool ReadElfHeader();
bool VerifyElfHeader();
bool ReadProgramHeader();
bool ReserveAddressSpace(uint32_t padding_size = 0);
bool ReserveAddressSpace(size_t page_size, uint32_t padding_size = 0);
bool LoadSegments();
bool FindPhdr();
bool CheckPhdr(uint8_t *);
Expand Down Expand Up @@ -85,6 +85,7 @@ class ElfReader {
size_t
phdr_table_get_load_size(const Elf_Phdr* phdr_table,
size_t phdr_count,
size_t page_size,
Elf_Addr* min_vaddr = NULL,
Elf_Addr* max_vaddr = NULL);

Expand Down
44 changes: 22 additions & 22 deletions ElfRebuilder.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ElfRebuilder::ElfRebuilder(ObElfReader *elf_reader) {
elf_reader_ = elf_reader;
}

bool ElfRebuilder::RebuildPhdr() {
bool ElfRebuilder::RebuildPhdr(size_t page_size) {
FLOGD("=============LoadDynamicSectionFromBaseSource==========RebuildPhdr=========================");


Expand All @@ -38,7 +38,7 @@ bool ElfRebuilder::RebuildPhdr() {
return true;
}

bool ElfRebuilder::RebuildShdr() {
bool ElfRebuilder::RebuildShdr(size_t page_size) {
FLOGD("=======================RebuildShdr=========================");
// rebuilding shdr, link information
auto base = si.load_bias;
Expand Down Expand Up @@ -361,31 +361,31 @@ bool ElfRebuilder::RebuildShdr() {
// // global_offset_table
// sGOT = shdrs.size();
// auto sLast = sGOT - 1;
//

// Elf_Shdr shdr;
// shdr.sh_name = shstrtab.length();
// shstrtab.append(".got");
// shstrtab.push_back('\0');
//

// shdr.sh_type = SHT_PROGBITS;
// shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
// shdr.sh_addr = shdrs[sLast].sh_addr + shdrs[sLast].sh_size;
// // Align8??
// while (shdr.sh_addr & 0x7) {
// shdr.sh_addr ++;
// }
//

// shdr.sh_offset = shdr.sh_addr;
// shdr.sh_size = (uintptr_t)(si.plt_got + si.plt_rel_count) - shdr.sh_addr - (uintptr_t)base + 3 * sizeof(Elf_Addr);
// shdr.sh_link = 0;
// shdr.sh_info = 0;
//#ifdef __SO64__
// #ifdef __SO64__
// shdr.sh_addralign = 8;
//#else
// #else
// shdr.sh_addralign = 4;
//#endif
// #endif
// shdr.sh_entsize = 0x0;
//

// shdrs.push_back(shdr);
// }

Expand Down Expand Up @@ -415,12 +415,12 @@ bool ElfRebuilder::RebuildShdr() {
// gen .bss
// if(true) {
// sBSS = shdrs.size();
//

// Elf_Shdr shdr;
// shdr.sh_name = shstrtab.length();
// shstrtab.append(".bss");
// shstrtab.push_back('\0');
//

// shdr.sh_type = SHT_NOBITS;
// shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
// shdr.sh_addr = si.max_load;
Expand All @@ -430,7 +430,7 @@ bool ElfRebuilder::RebuildShdr() {
// shdr.sh_info = 0;
// shdr.sh_addralign = 8;
// shdr.sh_entsize = 0x0;
//

// shdrs.push_back(shdr);
// }

Expand Down Expand Up @@ -537,21 +537,21 @@ bool ElfRebuilder::RebuildShdr() {
return true;
}

bool ElfRebuilder::Rebuild() {
return RebuildPhdr() &&
ReadSoInfo() &&
RebuildShdr() &&
RebuildRelocs() &&
RebuildFin();
bool ElfRebuilder::Rebuild(size_t page_size) {
return RebuildPhdr(page_size) &&
ReadSoInfo(page_size) &&
RebuildShdr(page_size) &&
RebuildRelocs(page_size) &&
RebuildFin(page_size);
}

bool ElfRebuilder::ReadSoInfo() {
bool ElfRebuilder::ReadSoInfo(size_t page_size) {
FLOGD("=======================ReadSoInfo=========================");
si.base = si.load_bias = elf_reader_->load_bias();
si.phdr = elf_reader_->loaded_phdr();
si.phnum = elf_reader_->phdr_count();
auto base = si.load_bias;
phdr_table_get_load_size(si.phdr, si.phnum, &si.min_load, &si.max_load);
phdr_table_get_load_size(si.phdr, si.phnum, page_size, &si.min_load, &si.max_load);
si.max_load += elf_reader_->pad_size_;

/* Extract dynamic section */
Expand Down Expand Up @@ -705,7 +705,7 @@ bool ElfRebuilder::ReadSoInfo() {
}

// Finally, generate rebuild_data
bool ElfRebuilder::RebuildFin() {
bool ElfRebuilder::RebuildFin(size_t page_size) {
FLOGD("=======================try to finish file rebuild =========================");
auto load_size = si.max_load - si.min_load;
rebuild_size = load_size + shstrtab.length() +
Expand Down Expand Up @@ -778,7 +778,7 @@ void ElfRebuilder::relocate(uint8_t * base, Elf_Rel* rel, Elf_Addr dump_base) {
};


bool ElfRebuilder::RebuildRelocs() {
bool ElfRebuilder::RebuildRelocs(size_t page_size) {
if(elf_reader_->dump_so_base_ == 0) return true;
FLOGD("=======================RebuildRelocs=========================");
if (si.plt_type == DT_REL) {
Expand Down
12 changes: 6 additions & 6 deletions ElfRebuilder.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ class ElfRebuilder {
public:
ElfRebuilder(ObElfReader* elf_reader);
~ElfRebuilder() { if(rebuild_data != nullptr) delete []rebuild_data; }
bool Rebuild();
bool Rebuild(size_t page_size);

void* getRebuildData() { return rebuild_data; }
size_t getRebuildSize() { return rebuild_size; }
private:
bool RebuildPhdr();
bool RebuildShdr();
bool ReadSoInfo();
bool RebuildRelocs();
bool RebuildFin();
bool RebuildPhdr(size_t page_size);
bool RebuildShdr(size_t page_size);
bool ReadSoInfo(size_t page_size);
bool RebuildRelocs(size_t page_size);
bool RebuildFin(size_t page_size);

template <bool isRela>
void relocate(uint8_t * base, Elf_Rel* rel, Elf_Addr dump_base);
Expand Down
10 changes: 5 additions & 5 deletions ObElfReader.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ void ObElfReader::FixDumpSoPhdr() {
}
}

bool ObElfReader::Load() {
bool ObElfReader::Load(size_t page_size) {
// try open
if (!ReadElfHeader() || !VerifyElfHeader() || !ReadProgramHeader())
return false;
FixDumpSoPhdr();

bool has_base_dynamic_info = false;
uint32_t base_dynamic_size = 0;
if (!haveDynamicSectionInLoadableSegment()) {
if (!haveDynamicSectionInLoadableSegment(page_size)) {
// try to get dynamic information from base so file.
// TODO fix bug in dynamic section rebuild.
LoadDynamicSectionFromBaseSource();
Expand All @@ -69,7 +69,7 @@ bool ObElfReader::Load() {
"argument baseso will be ignored.");
}

if (!ReserveAddressSpace(base_dynamic_size) ||
if (!ReserveAddressSpace(page_size, base_dynamic_size) ||
!LoadSegments() ||
!FindPhdr()) {
return false;
Expand Down Expand Up @@ -162,9 +162,9 @@ void ObElfReader::ApplyDynamicSection() {
}
}

bool ObElfReader::haveDynamicSectionInLoadableSegment() {
bool ObElfReader::haveDynamicSectionInLoadableSegment(size_t page_size) {
Elf_Addr min_vaddr, max_vaddr;
phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr, &max_vaddr);
phdr_table_get_load_size(phdr_table_, phdr_num_, page_size, &min_vaddr, &max_vaddr);

const Elf_Phdr* phdr = phdr_table_;
const Elf_Phdr* phdr_limit = phdr + phdr_num_;
Expand Down
4 changes: 2 additions & 2 deletions ObElfReader.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ObElfReader: public ElfReader {
// try to fix it
void FixDumpSoPhdr();

bool Load() override;
bool Load(size_t page_size) override;
bool LoadDynamicSectionFromBaseSource();

void setDumpSoBaseAddr(Elf_Addr base) { dump_so_base_ = base; }
Expand All @@ -27,7 +27,7 @@ class ObElfReader: public ElfReader {
}

// void GetDynamicSection(Elf_Dyn** dynamic, size_t* dynamic_count, Elf_Word* dynamic_flags) override;
bool haveDynamicSectionInLoadableSegment();
bool haveDynamicSectionInLoadableSegment(size_t page_size);

private:
void ApplyDynamicSection();
Expand Down
Loading