From 3c14755015340e48ae68aa874f672e7c9d289832 Mon Sep 17 00:00:00 2001 From: norly Date: Sat, 15 Jun 2013 13:27:42 +0100 Subject: [PATCH] Flatten symtab to file - gdb works, check breaks. --- Makefile | 1 + include/libelfu/types.h | 5 +++- src/modelops/fromFile.c | 5 +++- src/modelops/relocate.c | 8 +++--- src/modelops/toFile.c | 60 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index fc7c567..6418179 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ default: $(EXE) .PHONY: check check: $(EXE) + $(error the re-layouting has broken make check for now, sorry.) $(EXE) $(EXE) -o testexe @cmp $(EXE) testexe @rm testexe diff --git a/include/libelfu/types.h b/include/libelfu/types.h index 46fbc69..37e25fa 100644 --- a/include/libelfu/types.h +++ b/include/libelfu/types.h @@ -8,7 +8,8 @@ typedef struct ElfuSym { - char *name; + GElf_Word name; + char *nameptr; GElf_Addr value; GElf_Word size; @@ -92,6 +93,8 @@ typedef struct { CIRCLEQ_HEAD(OrphanScnList, ElfuScn) orphanScnList; ElfuScn *shstrtab; + + ElfuScn *symtab; } ElfuElf; #endif diff --git a/src/modelops/fromFile.c b/src/modelops/fromFile.c index 85afe20..c46dd6c 100644 --- a/src/modelops/fromFile.c +++ b/src/modelops/fromFile.c @@ -30,7 +30,8 @@ static void parseSymtab32(ElfuScn *ms, ElfuScn**origScnArr) ElfuSym *sym = malloc(sizeof(*sym)); assert(sym); - sym->name = symstr(ms, cursym->st_name); + sym->name = cursym->st_name; + sym->nameptr = symstr(ms, cursym->st_name); sym->value = cursym->st_value; sym->size = cursym->st_size; sym->bind = ELF32_ST_BIND(cursym->st_info); @@ -256,6 +257,7 @@ ElfuElf* elfu_mFromElf(Elf *e) CIRCLEQ_INIT(&me->phdrList); CIRCLEQ_INIT(&me->orphanScnList); me->shstrtab = NULL; + me->symtab = NULL; me->elfclass = gelf_getclass(e); assert(me->elfclass != ELFCLASSNONE); @@ -368,6 +370,7 @@ ElfuElf* elfu_mFromElf(Elf *e) switch (ms->shdr.sh_type) { case SHT_SYMTAB: + me->symtab = ms; case SHT_DYNSYM: if (me->elfclass == ELFCLASS32) { parseSymtab32(ms, secArray); diff --git a/src/modelops/relocate.c b/src/modelops/relocate.c index 679f57f..0bd8ee8 100644 --- a/src/modelops/relocate.c +++ b/src/modelops/relocate.c @@ -58,11 +58,11 @@ static GElf_Word pltLookupVal(ElfuElf *metarget, char *name) sym = CIRCLEQ_NEXT(sym, elem); } - if (!sym->name) { + if (!sym->nameptr) { continue; } - if (!strcmp(sym->name, name)) { + if (!strcmp(sym->nameptr, name)) { /* If this is the symbol we are looking for, then in an x86 binary * the jump to the dynamic symbol is probably at offset (j * 16) * from the start of the PLT, where j is the PLT entry and 16 is @@ -105,7 +105,7 @@ static GElf_Word symtabLookupVal(ElfuElf *metarget, ElfuScn *msst, GElf_Word ent /* Look the symbol up in .dyn.plt. If it cannot be found there then * .rel.dyn may need to be expanded with a COPY relocation so the * dynamic linker fixes up the (TODO). */ - return pltLookupVal(metarget, sym->name); + return pltLookupVal(metarget, sym->nameptr); } else if (sym->shndx == SHN_ABS) { return sym->value; } else { @@ -121,7 +121,7 @@ static GElf_Word symtabLookupVal(ElfuElf *metarget, ElfuScn *msst, GElf_Word ent ELFU_WARN("symtabLookupVal: Symbol type FILE is not supported, using 0.\n"); return 0; default: - ELFU_WARN("symtabLookupVal: Unknown symbol type %d for %s.\n", sym->type, sym->name); + ELFU_WARN("symtabLookupVal: Unknown symbol type %d for %s.\n", sym->type, sym->nameptr); return 0; } } diff --git a/src/modelops/toFile.c b/src/modelops/toFile.c index da06f4a..66109df 100644 --- a/src/modelops/toFile.c +++ b/src/modelops/toFile.c @@ -1,7 +1,62 @@ +#include #include +#include #include +static void flattenSymtab(ElfuElf *me) +{ + ElfuSym *sym; + size_t numsyms = 0; + + elfu_mLayoutAuto(me); + + CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) { + if (sym->scnptr) { + sym->shndx = elfu_mScnIndex(me, sym->scnptr); + } + + numsyms++; + } + + if (me->elfclass == ELFCLASS32) { + size_t newsize = (numsyms + 1) * sizeof(Elf32_Sym); + size_t i; + + if (me->symtab->data.d_buf) { + free(me->symtab->data.d_buf); + } + me->symtab->data.d_buf = malloc(newsize); + assert(me->symtab->data.d_buf); + + me->symtab->data.d_size = newsize; + me->symtab->shdr.sh_size = newsize; + memset(me->symtab->data.d_buf, 0, newsize); + + i = 1; + CIRCLEQ_FOREACH(sym, &me->symtab->symtab.syms, elem) { + Elf32_Sym *es = ((Elf32_Sym*)me->symtab->data.d_buf) + i; + + es->st_name = sym->name; + es->st_value = sym->value; + es->st_size = sym->size; + es->st_info = ELF32_ST_INFO(sym->bind, sym->type); + es->st_other = sym->other; + es->st_shndx = sym->shndx; + + i++; + } + } else if (me->elfclass == ELFCLASS64) { + // TODO + assert(0); + } else { + // Never reached + assert(0); + } + + elfu_mLayoutAuto(me); +} + static void modelToPhdrs(ElfuElf *me, Elf *e) { @@ -81,6 +136,11 @@ static void* modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2) void elfu_mToElf(ElfuElf *me, Elf *e) { + if (me->symtab) { + flattenSymtab(me); + } + + /* We control the ELF file's layout now. */ /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections, * but we don't want that since we filtered it out in the reading stage -- 2.30.2