Bug 716295 part 1 - Fail more gracefully when .dynamic section can't be grown. r=nfroyd

This commit is contained in:
Mike Hommey 2012-08-09 16:34:24 +02:00
parent ab23ebf01d
commit 62ef24ad74
3 changed files with 16 additions and 22 deletions

View File

@ -642,34 +642,25 @@ ElfSection *ElfDynamic_Section::getSectionForType(unsigned int tag)
return value ? value->getSection() : NULL;
}
void ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
{
unsigned int i;
for (i = 0; (i < shdr.sh_size / shdr.sh_entsize) && (dyns[i].tag != DT_NULL); i++)
unsigned int shnum = shdr.sh_size / shdr.sh_entsize;
for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++)
if (dyns[i].tag == tag) {
delete dyns[i].value;
dyns[i].value = val;
return;
return true;
}
// This should never happen, as the last entry is always tagged DT_NULL
assert(i < shdr.sh_size / shdr.sh_entsize);
// If we get here, this means we didn't match for the given tag
// Most of the time, there are a few DT_NULL entries, that we can
// use to add our value, but if we are on the last entry, we can't.
if (i >= shnum - 1)
return false;
dyns[i].tag = tag;
dyns[i++].value = val;
// If we were on the last entry, we need to grow the section.
// Most of the time, though, there are a few DT_NULL entries.
if (i < shdr.sh_size / shdr.sh_entsize)
return;
Elf_DynValue value;
value.tag = DT_NULL;
value.value = NULL;
dyns.push_back(value);
// Resize the section accordingly
shdr.sh_size += shdr.sh_entsize;
if (getNext() != NULL)
getNext()->markDirty();
dyns[i].value = val;
return true;
}
ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)

View File

@ -450,7 +450,10 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
section->rels.assign(new_rels.begin(), new_rels.end());
section->shrink(new_rels.size() * section->getEntSize());
ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
dyn->setValueForType(DT_INIT, init);
if (!dyn->setValueForType(DT_INIT, init)) {
fprintf(stderr, "Can't grow .dynamic section to set DT_INIT. Skipping\n");
return -1;
}
// TODO: adjust the value according to the remaining number of relative relocations
if (dyn->getValueForType(Rel_Type::d_tag_count))
dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0));

View File

@ -505,7 +505,7 @@ public:
ElfValue *getValueForType(unsigned int tag);
ElfSection *getSectionForType(unsigned int tag);
void setValueForType(unsigned int tag, ElfValue *val);
bool setValueForType(unsigned int tag, ElfValue *val);
private:
std::vector<Elf_DynValue> dyns;
};