Bug 956398 - Support text relocations in the custom linker. r=nfroyd

This commit is contained in:
Mike Hommey 2014-01-16 09:13:42 +09:00
parent 3e1e04b07b
commit b0ff197fa9
2 changed files with 42 additions and 10 deletions

View File

@ -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<const Phdr *>::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<const Phdr *>::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

View File

@ -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<uint32_t[2]> arm_exidx;