diff --git a/mozglue/linker/CustomElf.cpp b/mozglue/linker/CustomElf.cpp index f0286d2b0e1..efd1a576552 100644 --- a/mozglue/linker/CustomElf.cpp +++ b/mozglue/linker/CustomElf.cpp @@ -64,6 +64,13 @@ void debug_phdr(const char *type, const Phdr *phdr) phdr->p_flags & PF_W ? 'w' : '-', phdr->p_flags & PF_X ? 'x' : '-'); } +static int p_flags_to_mprot(Word flags) +{ + return ((flags & PF_X) ? PROT_EXEC : 0) | + ((flags & PF_W) ? PROT_WRITE : 0) | + ((flags & PF_R) ? PROT_READ : 0); +} + void __void_stub(void) { @@ -225,6 +232,28 @@ CustomElf::Load(Mappable *mappable, const char *path, int flags) if (!elf->InitDyn(dyn)) return nullptr; + if (elf->has_text_relocs) { + for (std::vector::iterator it = pt_loads.begin(); + it < pt_loads.end(); ++it) + mprotect(PageAlignedPtr(elf->GetPtr((*it)->p_vaddr)), + PageAlignedEndPtr((*it)->p_memsz), + p_flags_to_mprot((*it)->p_flags) | PROT_WRITE); + } + + if (!elf->Relocate() || !elf->RelocateJumps()) + return nullptr; + + if (elf->has_text_relocs) { + for (std::vector::iterator it = pt_loads.begin(); + it < pt_loads.end(); ++it) + mprotect(PageAlignedPtr(elf->GetPtr((*it)->p_vaddr)), + PageAlignedEndPtr((*it)->p_memsz), + p_flags_to_mprot((*it)->p_flags)); + } + + if (!elf->CallInit()) + return nullptr; + #ifdef __ARM_EABI__ if (arm_exidx_phdr) elf->arm_exidx.InitSize(elf->GetPtr(arm_exidx_phdr->p_vaddr), @@ -423,9 +452,7 @@ CustomElf::LoadSegment(const Phdr *pt_load) const return false;; } - int prot = ((pt_load->p_flags & PF_X) ? PROT_EXEC : 0) | - ((pt_load->p_flags & PF_W) ? PROT_WRITE : 0) | - ((pt_load->p_flags & PF_R) ? PROT_READ : 0); + int prot = p_flags_to_mprot(pt_load->p_flags); /* Mmap at page boundary */ Addr align = PageSize(); @@ -549,8 +576,8 @@ CustomElf::InitDyn(const Phdr *pt_dyn) } break; case DT_TEXTREL: - LOG("%s: Text relocations are not supported", GetPath()); - return false; + has_text_relocs = true; + break; case DT_STRSZ: /* Ignored */ debug_dyn("DT_STRSZ", dyn); break; @@ -620,8 +647,7 @@ CustomElf::InitDyn(const Phdr *pt_dyn) Addr flags = dyn->d_un.d_val; /* Treat as a DT_TEXTREL tag */ if (flags & DF_TEXTREL) { - LOG("%s: Text relocations are not supported", GetPath()); - return false; + has_text_relocs = true; } /* we can treat this like having a DT_SYMBOLIC tag */ flags &= ~DF_SYMBOLIC; @@ -677,8 +703,7 @@ CustomElf::InitDyn(const Phdr *pt_dyn) dependencies.push_back(handle); } - /* Finish initialization */ - return Relocate() && RelocateJumps() && CallInit(); + return true; } bool diff --git a/mozglue/linker/CustomElf.h b/mozglue/linker/CustomElf.h index 11de68abef1..1853d7f3bbb 100644 --- a/mozglue/linker/CustomElf.h +++ b/mozglue/linker/CustomElf.h @@ -76,7 +76,12 @@ private: * Private constructor */ CustomElf(Mappable *mappable, const char *path) - : LibHandle(path), mappable(mappable), init(0), fini(0), initialized(false) + : LibHandle(path) + , mappable(mappable) + , init(0) + , fini(0) + , initialized(false) + , has_text_relocs(false) { } /** @@ -193,6 +198,8 @@ private: bool initialized; + bool has_text_relocs; + #ifdef __ARM_EABI__ /* ARM.exidx information used by FindExidx */ Array arm_exidx;