Bug 628232 part 1 - Use the init symbol from elfhack injected code as an entry point instead of hardcoding 0. r=tglek,a=sdwilsh

This commit is contained in:
Mike Hommey 2011-01-28 09:22:58 +01:00
parent a59a2243d8
commit a46608b3ad

View File

@ -123,22 +123,45 @@ public:
if (elf->getMachine() != parent.getMachine())
throw std::runtime_error("architecture of object for injected code doesn't match");
ElfSymtab_Section *symtab = NULL;
// Get all executable sections from the injected code object.
// Most of the time, there will only be one for the init function,
// but on e.g. x86, there is a separate section for
// __i686.get_pc_thunk.$reg
for (ElfSection *text = elf->getSection(1); text != NULL;
text = text->getNext()) {
if ((text->getType() == SHT_PROGBITS) &&
(text->getFlags() & SHF_EXECINSTR)) {
code.push_back(text);
// Find the symbol table at the same time.
for (ElfSection *section = elf->getSection(1); section != NULL;
section = section->getNext()) {
if ((section->getType() == SHT_PROGBITS) &&
(section->getFlags() & SHF_EXECINSTR)) {
code.push_back(section);
// We need to align this section depending on the greater
// alignment required by code sections.
if (shdr.sh_addralign < text->getAddrAlign())
shdr.sh_addralign = text->getAddrAlign();
if (shdr.sh_addralign < section->getAddrAlign())
shdr.sh_addralign = section->getAddrAlign();
} else if (section->getType() == SHT_SYMTAB) {
symtab = (ElfSymtab_Section *) section;
}
}
assert(code.size() != 0);
if (symtab == NULL)
throw std::runtime_error("Couldn't find a symbol table for the injected code");
// Find the init symbol
entry_point = -1;
int shndx = 0;
ElfStrtab_Section *strtab = (ElfStrtab_Section *)symtab->getLink();
for (std::vector<Elf_Sym>::iterator sym = symtab->syms.begin();
sym != symtab->syms.end(); sym++) {
const char *name = strtab->getStr(sym->st_name);
if (strcmp(name, "init") == 0) {
entry_point = sym->st_value;
shndx = sym->st_shndx;
break;
}
}
if (entry_point == -1)
throw std::runtime_error("Couldn't find an 'init' symbol in the injected code");
// Adjust code sections offsets according to their size
std::vector<ElfSection *>::iterator c = code.begin();
@ -155,6 +178,8 @@ public:
for (c = code.begin(); c != code.end(); c++) {
memcpy(buf, (*c)->getData(), (*c)->getSize());
buf += (*c)->getSize();
if ((*c)->getIndex() < shndx)
entry_point += (*c)->getSize();
}
name = elfhack_text;
}
@ -188,6 +213,9 @@ public:
return true;
}
unsigned int getEntryPoint() {
return entry_point;
}
private:
void apply_pc32_relocation(ElfSection *the_code, char *base, Elf_Rel *r, unsigned int addr)
{
@ -291,6 +319,7 @@ private:
Elf *elf, &parent;
std::vector<ElfSection *> code;
ElfSection *init;
int entry_point;
};
template <typename Rel_Type>
@ -353,7 +382,7 @@ int do_relocation_section(Elf *elf, 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, 0);
ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
dyn->setValueForType(DT_INIT, init);
// TODO: adjust the value according to the remaining number of relative relocations
if (dyn->getValueForType(Rel_Type::d_tag_count))