From 13b621d944766f19db762c0fd79e359e824a5f83 Mon Sep 17 00:00:00 2001 From: norly Date: Thu, 27 Jun 2013 03:20:54 +0100 Subject: [PATCH] Allocate .symtab during Reladd if none present --- include/libelfu/modelops.h | 2 ++ src/libelfu/model/section.c | 24 +++++++++++++++++++ src/libelfu/model/symtab.c | 45 +++++++++++++++++++++++++++++++++++ src/libelfu/modelops/reladd.c | 44 +++++++--------------------------- 4 files changed, 79 insertions(+), 36 deletions(-) diff --git a/include/libelfu/modelops.h b/include/libelfu/modelops.h index e9ea9ee..538e97a 100644 --- a/include/libelfu/modelops.h +++ b/include/libelfu/modelops.h @@ -15,6 +15,7 @@ ElfuSym* elfu_mSymtabIndexToSym(ElfuScn *msst, GElf_Word entry); GElf_Addr elfu_mSymtabLookupAddrByName(ElfuElf *me, ElfuScn *msst, char *name); void elfu_mSymtabFlatten(ElfuElf *me); + void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me); typedef void* (PhdrHandlerFunc)(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2); @@ -39,6 +40,7 @@ typedef void* (SectionHandlerFunc)(ElfuElf *me, ElfuScn *ms, void *aux1, void *a ElfuScn* elfu_mScnByOldscn(ElfuElf *me, ElfuScn *oldscn); char* elfu_mScnName(ElfuElf *me, ElfuScn *ms); ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count); + int elfu_mScnAppendData(ElfuScn *ms, void *buf, size_t len); ElfuScn* elfu_mScnAlloc(); void elfu_mScnDestroy(ElfuScn* ms); diff --git a/src/libelfu/model/section.c b/src/libelfu/model/section.c index 9ef6fd8..74fbc3a 100644 --- a/src/libelfu/model/section.c +++ b/src/libelfu/model/section.c @@ -198,6 +198,30 @@ ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count) +int elfu_mScnAppendData(ElfuScn *ms, void *buf, size_t len) +{ + char *newbuf; + + assert(ms); + assert(ms->shdr.sh_type != SHT_NOBITS); + assert(ms->databuf); + + newbuf = realloc(ms->databuf, ms->shdr.sh_size + len); + if (!newbuf) { + ELFU_WARN("elfu_mScnAppendData: malloc() failed for newbuf.\n"); + return -1; + } + + ms->databuf = newbuf; + memcpy(newbuf + ms->shdr.sh_size, buf, len); + ms->shdr.sh_size += len; + assert(ms->shdr.sh_size == ms->shdr.sh_size); + + return 0; +} + + + /* * Allocation, destruction */ diff --git a/src/libelfu/model/symtab.c b/src/libelfu/model/symtab.c index 0cf107b..439c4d3 100644 --- a/src/libelfu/model/symtab.c +++ b/src/libelfu/model/symtab.c @@ -198,3 +198,48 @@ void elfu_mSymtabFlatten(ElfuElf *me) elfu_mLayoutAuto(me); } + + + +void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me) +{ + assert(me); + + if (!me->symtab) { + ElfuScn *symtab; + ElfuScn *strtab; + + symtab = elfu_mScnAlloc(); + assert(symtab); + strtab = elfu_mScnAlloc(); + assert(strtab); + + symtab->linkptr = strtab; + symtab->shdr.sh_entsize = me->elfclass == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym); + symtab->shdr.sh_addralign = 4; + strtab->shdr.sh_addralign = 1; + symtab->shdr.sh_type = SHT_SYMTAB; + strtab->shdr.sh_type = SHT_STRTAB; + + strtab->databuf = malloc(1); + assert(strtab->databuf); + strtab->databuf[0] = 0; + + CIRCLEQ_INSERT_TAIL(&me->orphanScnList, symtab, elemChildScn); + CIRCLEQ_INSERT_TAIL(&me->orphanScnList, strtab, elemChildScn); + + me->symtab = symtab; + + if (me->shstrtab) { + symtab->shdr.sh_name = me->shstrtab->shdr.sh_size; + if (elfu_mScnAppendData(me->shstrtab, ".symtab", 8)) { + symtab->shdr.sh_name = 0; + } + + strtab->shdr.sh_name = me->shstrtab->shdr.sh_size; + if (elfu_mScnAppendData(me->shstrtab, ".strtab", 8)) { + strtab->shdr.sh_name = 0; + } + } + } +} diff --git a/src/libelfu/modelops/reladd.c b/src/libelfu/modelops/reladd.c index fc0adc3..1980c76 100644 --- a/src/libelfu/modelops/reladd.c +++ b/src/libelfu/modelops/reladd.c @@ -36,28 +36,6 @@ static ElfuScn* cloneScn(ElfuScn *ms) } -static int appendData(ElfuScn *ms, void *buf, size_t len) -{ - char *newbuf; - - assert(ms); - assert(ms->shdr.sh_type != SHT_NOBITS); - assert(ms->databuf); - - newbuf = realloc(ms->databuf, ms->shdr.sh_size + len); - if (!newbuf) { - ELFU_WARN("appendData: malloc() failed for newbuf.\n"); - return 1; - } - - ms->databuf = newbuf; - memcpy(newbuf + ms->shdr.sh_size, buf, len); - ms->shdr.sh_size += len; - assert(ms->shdr.sh_size == ms->shdr.sh_size); - - return 0; -} - static ElfuScn* insertSection(ElfuElf *me, ElfuElf *mrel, ElfuScn *oldscn) { @@ -128,7 +106,6 @@ static ElfuScn* insertSection(ElfuElf *me, ElfuElf *mrel, ElfuScn *oldscn) /* Inject name */ if (me->shstrtab) { - char *newname; size_t newnamelen; newnamelen = strlen("reladd") + 1; @@ -136,21 +113,15 @@ static ElfuScn* insertSection(ElfuElf *me, ElfuElf *mrel, ElfuScn *oldscn) newnamelen += strlen(elfu_mScnName(mrel, oldscn)); } - newname = malloc(newnamelen); + char newname[newnamelen]; + strcpy(newname, "reladd"); strcat(newname, elfu_mScnName(mrel, oldscn)); - if (!newname) { - ELFU_WARN("insertSection: malloc() failed for newname. Leaving section name empty.\n"); - newscn->shdr.sh_name = 0; - } else { - size_t offset = me->shstrtab->shdr.sh_size; - - if (!appendData(me->shstrtab, newname, newnamelen)) { - newscn->shdr.sh_name = offset; - } + newscn->shdr.sh_name = me->shstrtab->shdr.sh_size; - free(newname); + if (elfu_mScnAppendData(me->shstrtab, newname, newnamelen)) { + newscn->shdr.sh_name = 0; } } @@ -262,8 +233,9 @@ static void insertSymClone(ElfuElf *me, const ElfuScn *oldmsst, const ElfuSym *o } } - // TODO: Allocate symtab if none present - assert(me->symtab); + /* If we don't have a symbol table, create one so we have somewhere to + * write our new symbols to. */ + elfu_mSymtabAddGlobalDymtabIfNotPresent(me); /* Allocate memory for the cloned symbol */ newsym = malloc(sizeof(*newsym)); -- 2.30.2