#include <libelfu/libelfu.h>
-static char* symstr(ElfuScn *symtab, size_t off)
+static void parseSymtab(ElfuElf *me, ElfuScn *ms, ElfuScn**origScnArr)
{
- assert(symtab);
- assert(symtab->linkptr);
- assert(symtab->linkptr->data.d_buf);
- assert(off < symtab->linkptr->data.d_size);
-
- return &(((char*)symtab->linkptr->data.d_buf)[off]);
-}
-
-
-static ElfuSymtab* symtabFromScn32(ElfuScn *ms, ElfuScn**origScnArr)
-{
- ElfuSymtab *st;
+ ElfuSym *sym;
size_t i;
assert(ms);
assert(ms->data.d_buf);
assert(origScnArr);
+ /* Parse symbols from their elfclass-specific format */
+ if (me->elfclass == ELFCLASS32) {
+ for (i = 1; (i + 1) * sizeof(Elf32_Sym) <= ms->shdr.sh_size; i++) {
+ Elf32_Sym *cursym = ((Elf32_Sym*)ms->data.d_buf) + i;
+ ElfuSym *newsym = malloc(sizeof(*sym));
+ assert(newsym);
- st = malloc(sizeof(*st));
- if (!st) {
- ELFU_WARN("elfu_mSymtabFromScn32: malloc() failed for st.\n");
- goto ERROR;
- }
+ newsym->name = cursym->st_name;
+ newsym->value = cursym->st_value;
+ newsym->size = cursym->st_size;
+ newsym->bind = ELF32_ST_BIND(cursym->st_info);
+ newsym->type = ELF32_ST_TYPE(cursym->st_info);
+ newsym->other = cursym->st_other;
+ newsym->shndx = cursym->st_shndx;
- CIRCLEQ_INIT(&st->syms);
- for (i = 1; (i + 1) * sizeof(Elf32_Sym) <= ms->shdr.sh_size; i++) {
- Elf32_Sym *cursym = &(((Elf32_Sym*)ms->data.d_buf)[i]);
- ElfuSym *sym = malloc(sizeof(*sym));
- assert(sym);
+ CIRCLEQ_INSERT_TAIL(&ms->symtab.syms, newsym, elem);
+ }
+ } else if (me->elfclass == ELFCLASS64) {
+ for (i = 1; (i + 1) * sizeof(Elf64_Sym) <= ms->shdr.sh_size; i++) {
+ Elf64_Sym *cursym = ((Elf64_Sym*)ms->data.d_buf) + i;
+ ElfuSym *newsym = malloc(sizeof(*sym));
+ assert(newsym);
+
+ newsym->name = cursym->st_name;
+ newsym->value = cursym->st_value;
+ newsym->size = cursym->st_size;
+ newsym->bind = ELF64_ST_BIND(cursym->st_info);
+ newsym->type = ELF64_ST_TYPE(cursym->st_info);
+ newsym->other = cursym->st_other;
+ newsym->shndx = cursym->st_shndx;
+
- sym->name = symstr(ms, cursym->st_name);
- sym->value = cursym->st_value;
- sym->size = cursym->st_size;
- sym->bind = ELF32_ST_BIND(cursym->st_info);
- sym->type = ELF32_ST_TYPE(cursym->st_info);
- sym->other = cursym->st_other;
- switch (cursym->st_shndx) {
+ CIRCLEQ_INSERT_TAIL(&ms->symtab.syms, newsym, elem);
+ }
+ } else {
+ // Unknown elfclass
+ assert(0);
+ }
+
+ /* For each section, find the section it points to if any. */
+ CIRCLEQ_FOREACH(sym, &ms->symtab.syms, elem) {
+ switch (sym->shndx) {
case SHN_UNDEF:
case SHN_ABS:
case SHN_COMMON:
sym->scnptr = NULL;
- sym->shndx = cursym->st_shndx;
break;
default:
- sym->scnptr = origScnArr[cursym->st_shndx - 1];
+ sym->scnptr = origScnArr[sym->shndx - 1];
break;
}
-
-
- CIRCLEQ_INSERT_TAIL(&st->syms, sym, elem);
- }
-
-
- return st;
-
- ERROR:
- if (st) {
- free(st);
}
- return NULL;
}
-static ElfuReltab* reltabFromScn32(ElfuScn *ms)
+static void parseReltab32(ElfuScn *ms)
{
- ElfuReltab *rt;
size_t i;
assert(ms);
assert(ms->data.d_buf);
- rt = malloc(sizeof(*rt));
- if (!rt) {
- ELFU_WARN("elfu_mReltabFromScn32: malloc() failed for rt.\n");
- goto ERROR;
- }
-
- CIRCLEQ_INIT(&rt->rels);
-
-
for (i = 0; (i + 1) * sizeof(Elf32_Rel) <= ms->shdr.sh_size; i++) {
Elf32_Rel *currel = &(((Elf32_Rel*)ms->data.d_buf)[i]);
ElfuRel *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;
- CIRCLEQ_INSERT_TAIL(&rt->rels, rel, elem);
+ CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
}
+}
- return rt;
+static void parseRelatab64(ElfuScn *ms)
+{
+ size_t i;
- ERROR:
- if (rt) {
- free(rt);
+ assert(ms);
+ assert(ms->data.d_buf);
+
+
+ for (i = 0; (i + 1) * sizeof(Elf64_Rela) <= ms->shdr.sh_size; i++) {
+ Elf64_Rela *currel = &(((Elf64_Rela*)ms->data.d_buf)[i]);
+ ElfuRel *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;
+
+ CIRCLEQ_INSERT_TAIL(&ms->reltab.rels, rel, elem);
}
- return NULL;
}
ms->oldptr = NULL;
- ms->symtab = NULL;
- ms->reltab = NULL;
+ CIRCLEQ_INIT(&ms->symtab.syms);
+ CIRCLEQ_INIT(&ms->reltab.rels);
return ms;
CIRCLEQ_INIT(&me->phdrList);
CIRCLEQ_INIT(&me->orphanScnList);
me->shstrtab = NULL;
+ me->symtab = NULL;
me->elfclass = gelf_getclass(e);
assert(me->elfclass != ELFCLASSNONE);
switch (ms->shdr.sh_type) {
case SHT_SYMTAB:
+ me->symtab = ms;
case SHT_DYNSYM:
- if (me->elfclass == ELFCLASS32) {
- ms->symtab = symtabFromScn32(ms, secArray);
- } else if (me->elfclass == ELFCLASS64) {
- // TODO
- }
- assert(ms->symtab);
+ parseSymtab(me, ms, secArray);
break;
}
}
switch (ms->shdr.sh_type) {
case SHT_REL:
if (me->elfclass == ELFCLASS32) {
- ms->reltab = reltabFromScn32(ms);
+ parseReltab32(ms);
} else if (me->elfclass == ELFCLASS64) {
- // TODO
+ // Not used on x86-64
}
- assert(ms->reltab);
break;
case SHT_RELA:
if (me->elfclass == ELFCLASS32) {
// TODO
} else if (me->elfclass == ELFCLASS64) {
- // TODO
+ parseRelatab64(ms);
}
- assert(ms->reltab);
break;
}
}