Bug 628283 - Make elfhack handle GNU_RELRO segments better. r=tglek,a=dbaron

This commit is contained in:
Mike Hommey 2011-01-24 23:11:46 +01:00
Родитель b303489a0c
Коммит c886f4609d
3 изменённых файлов: 31 добавлений и 4 удалений

Просмотреть файл

@ -351,6 +351,14 @@ ElfSection *Elf::getSectionAt(unsigned int offset)
return NULL;
}
ElfSegment *Elf::getSegmentByType(unsigned int type)
{
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
if ((*seg)->getType() == type)
return *seg;
return NULL;
}
ElfDynamic_Section *Elf::getDynSection()
{
for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
@ -563,15 +571,28 @@ unsigned int ElfSegment::getFileSize()
// All sections are SHT_NOBITS
if (i == sections.rend())
return 0;
return ((*i)->getAddr() - sections.front()->getAddr()) + (*i)->getSize();
unsigned int end = (*i)->getAddr() + (*i)->getSize();
// GNU_RELRO segment end is page aligned.
if (type == PT_GNU_RELRO)
end = (end + 4095) & ~4095;
return end - sections.front()->getAddr();
}
unsigned int ElfSegment::getMemSize()
{
if (sections.empty())
return 0;
return (sections.back()->getAddr() - sections.front()->getAddr()) +
(sections.back()->getSize());
unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
// GNU_RELRO segment end is page aligned.
if (type == PT_GNU_RELRO)
end = (end + 4095) & ~4095;
return end - sections.front()->getAddr();
}
ElfSegment *ElfSegment::splitBefore(ElfSection *section)

Просмотреть файл

@ -302,6 +302,8 @@ int do_relocation_section(Elf *elf, unsigned int rel_type)
return -1;
}
ElfSegment *relro = elf->getSegmentByType(PT_GNU_RELRO);
ElfRel_Section<Rel_Type> *section = (ElfRel_Section<Rel_Type> *)dyn->getSectionForType(Rel_Type::d_tag);
assert(section->getType() == Rel_Type::sh_type);
@ -326,7 +328,9 @@ int do_relocation_section(Elf *elf, unsigned int rel_type)
// Don't pack relocations happening in non writable sections.
// Our injected code is likely not to be allowed to write there.
ElfSection *section = elf->getSectionAt(i->r_offset);
if (!(section->getFlags() & SHF_WRITE) || (ELF32_R_TYPE(i->r_info) != rel_type))
if (!(section->getFlags() & SHF_WRITE) || (ELF32_R_TYPE(i->r_info) != rel_type) ||
(relro && (i->r_offset >= relro->getFirstSection()->getAddr()) &&
(i->r_offset < relro->getFirstSection()->getAddr() + relro->getMemSize())))
new_rels.push_back(*i);
else {
// TODO: check that i->r_addend == *i->r_offset

Просмотреть файл

@ -265,6 +265,8 @@ public:
ElfSection *getSectionAt(unsigned int offset);
ElfSegment *getSegmentByType(unsigned int type);
ElfDynamic_Section *getDynSection();
void write(std::ofstream &file);