}
-static void parseReltab32(ElfuScn *ms)
+static void parseReltab(ElfuElf *me, ElfuScn *ms)
{
size_t i;
assert(ms);
assert(ms->databuf);
+ if (me->elfclass == ELFCLASS32) {
+ for (i = 0; (i + 1) * sizeof(Elf32_Rel) <= ms->shdr.sh_size; i++) {
+ Elf32_Rel *currel = &(((Elf32_Rel*)ms->databuf)[i]);
+ ElfuRel *rel;
+
+ rel = malloc(sizeof(*rel));
+ assert(rel);
- for (i = 0; (i + 1) * sizeof(Elf32_Rel) <= ms->shdr.sh_size; i++) {
- Elf32_Rel *currel = &(((Elf32_Rel*)ms->databuf)[i]);
- ElfuRel *rel;
+ rel->offset = currel->r_offset;
+ rel->sym = ELF32_R_SYM(currel->r_info);
+ rel->type = ELF32_R_TYPE(currel->r_info);
+ rel->addendUsed = 0;
+ rel->addend = 0;
+
+ CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
+ }
+ } else if (me->elfclass == ELFCLASS64) {
+ for (i = 0; (i + 1) * sizeof(Elf64_Rel) <= ms->shdr.sh_size; i++) {
+ Elf64_Rel *currel = &(((Elf64_Rel*)ms->databuf)[i]);
+ ElfuRel *rel;
- rel = malloc(sizeof(*rel));
- assert(rel);
+ rel = malloc(sizeof(*rel));
+ assert(rel);
- rel->offset = currel->r_offset;
- rel->sym = ELF32_R_SYM(currel->r_info);
- rel->type = ELF32_R_TYPE(currel->r_info);
- rel->addendUsed = 0;
- rel->addend = 0;
+ rel->offset = currel->r_offset;
+ rel->sym = ELF64_R_SYM(currel->r_info);
+ rel->type = ELF64_R_TYPE(currel->r_info);
+ rel->addendUsed = 0;
+ rel->addend = 0;
- CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
+ CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
+ }
+ } else {
+ /* Unknown elfclass */
+ assert(0);
}
}
-static void parseRelatab64(ElfuScn *ms)
+static void parseRelatab(ElfuElf *me, ElfuScn *ms)
{
size_t i;
assert(ms);
assert(ms->databuf);
+ if (me->elfclass == ELFCLASS32) {
+ for (i = 0; (i + 1) * sizeof(Elf32_Rela) <= ms->shdr.sh_size; i++) {
+ Elf32_Rela *currel = &(((Elf32_Rela*)ms->databuf)[i]);
+ ElfuRel *rel;
+
+ rel = malloc(sizeof(*rel));
+ assert(rel);
+
+ rel->offset = currel->r_offset;
+ rel->sym = ELF32_R_SYM(currel->r_info);
+ rel->type = ELF32_R_TYPE(currel->r_info);
+ rel->addendUsed = 1;
+ rel->addend = currel->r_addend;
- for (i = 0; (i + 1) * sizeof(Elf64_Rela) <= ms->shdr.sh_size; i++) {
- Elf64_Rela *currel = &(((Elf64_Rela*)ms->databuf)[i]);
- ElfuRel *rel;
+ CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
+ }
+ } else if (me->elfclass == ELFCLASS64) {
+ for (i = 0; (i + 1) * sizeof(Elf64_Rela) <= ms->shdr.sh_size; i++) {
+ Elf64_Rela *currel = &(((Elf64_Rela*)ms->databuf)[i]);
+ ElfuRel *rel;
- rel = malloc(sizeof(*rel));
- assert(rel);
+ rel = malloc(sizeof(*rel));
+ assert(rel);
- rel->offset = currel->r_offset;
- rel->sym = ELF64_R_SYM(currel->r_info);
- rel->type = ELF64_R_TYPE(currel->r_info);
- rel->addendUsed = 1;
- rel->addend = currel->r_addend;
+ rel->offset = currel->r_offset;
+ rel->sym = ELF64_R_SYM(currel->r_info);
+ rel->type = ELF64_R_TYPE(currel->r_info);
+ rel->addendUsed = 1;
+ rel->addend = currel->r_addend;
- CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
+ CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
+ }
+ } else {
+ /* Unknown elfclass */
+ assert(0);
}
}
if (PHDR_CONTAINS_SCN_IN_MEMORY(&mp->phdr, &ms->shdr)) {
return mp;
}
-
- /* Give sections a second chance if they do not have any sh_addr
- * at all. */
- /* Actually we don't, because it's ambiguous.
- * Re-enable for experiments with strangely-formatted files.
- if (ms->shdr.sh_addr == 0
- && PHDR_CONTAINS_SCN_IN_FILE(&mp->phdr, &ms->shdr)
- && OFFS_END(ms->shdr.sh_offset, ms->shdr.sh_size)
- <= OFFS_END(mp->phdr.p_offset, mp->phdr.p_memsz)) {
- return mp;
- }
- */
}
return NULL;
data = elf_rawdata(scn, NULL);
assert(data);
- /* elf_rawdata() always returns ELF_T_BYTE */
- assert(data->d_type == ELF_T_BYTE);
-
while (data) {
if (data->d_off + data->d_size > ms->shdr.sh_size) {
ELFU_WARN("modelFromSection: libelf delivered a bogus data blob. Skipping\n");
ElfuElf* elfu_mFromElf(Elf *e)
{
- ElfuElf *me;
+ ElfuElf *me = NULL;
size_t shstrndx;
size_t i, numPhdr, numShdr;
ElfuScn **secArray = NULL;
goto ERROR;
}
- me = malloc(sizeof(ElfuElf));
+ me = elfu_mElfAlloc();
if (!me) {
- ELFU_WARN("elfu_mFromElf: malloc() failed for ElfuElf.\n");
goto ERROR;
}
-
- /* General stuff */
- CIRCLEQ_INIT(&me->phdrList);
- CIRCLEQ_INIT(&me->orphanScnList);
- me->shstrtab = NULL;
- me->symtab = NULL;
-
me->elfclass = gelf_getclass(e);
assert(me->elfclass != ELFCLASSNONE);
assert(gelf_getehdr(e, &me->ehdr) == &me->ehdr);
if (mp->phdr.p_vaddr <= mp2->phdr.p_vaddr
&& OFFS_END(mp2->phdr.p_vaddr, mp2->phdr.p_memsz) <= OFFS_END(mp->phdr.p_vaddr, mp->phdr.p_memsz)) {
+ /* Remove from the main list so only LOADs remain there */
+ CIRCLEQ_REMOVE(&me->phdrList, mp2, elem);
CIRCLEQ_INSERT_TAIL(&mp->childPhdrList, mp2, elemChildPhdr);
}
}
}
- /* Parse relocations */
+ /* Parse relocations (needs sections in original order) */
for (i = 0; i < numShdr - 1; i++) {
ElfuScn *ms = secArray[i];
switch (ms->shdr.sh_type) {
case SHT_REL:
- if (me->elfclass == ELFCLASS32) {
- parseReltab32(ms);
- } else if (me->elfclass == ELFCLASS64) {
- /* Not used on x86-64 */
- assert(0);
- }
+ parseReltab(me, ms);
break;
case SHT_RELA:
- if (me->elfclass == ELFCLASS32) {
- /* Not used on x86-32 */
- assert(0);
- } else if (me->elfclass == ELFCLASS64) {
- parseRelatab64(ms);
- }
+ parseRelatab(me, ms);
break;
}
}
if (ms->shdr.sh_addr == 0) {
ms->shdr.sh_addr = shaddr;
} else {
- assert(ms->shdr.sh_addr == shaddr);
+ if (ms->shdr.sh_type != SHT_NOBITS) {
+ assert(ms->shdr.sh_addr == shaddr);
+ } else if (ms->shdr.sh_addr > shaddr) {
+ parent->phdr.p_filesz = MAX(parent->phdr.p_filesz,
+ ms->shdr.sh_addr - parent->phdr.p_vaddr);
+ }
}
CIRCLEQ_INSERT_TAIL(&parent->childScnList, ms, elemChildScn);
}
}
-
+ if (secArray) {
+ free(secArray);
+ }
return me;
free(secArray);
}
if (me) {
- // TODO: Free data structures
+ elfu_mElfDestroy(me);
}
ELFU_WARN("elfu_mFromElf: Failed to load file.\n");