From 5868bb32246367139f0d17a989650964f90a7958 Mon Sep 17 00:00:00 2001 From: norly Date: Sat, 15 Jun 2013 16:27:28 +0100 Subject: Merge symbol tables. (Not fully ELF conformant) Also, remove that nameptr member from symbols. It just *had* to cause trouble. Symbols are simply appended to the target's symbol table, which means that LOCAL symbols are not inserted at the beginning and we are thus ignoring an ELF spec. Might change that in the future, it's good enough for now and it's sure not to break anything with the old symbols. The code currently assumes that the target *has* a symbol table. We'll have to fix that, and also remove undefined and duplicate symbols. --- src/modelops/reladd.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) (limited to 'src/modelops/reladd.c') diff --git a/src/modelops/reladd.c b/src/modelops/reladd.c index 2fdfb48..936c0bd 100644 --- a/src/modelops/reladd.c +++ b/src/modelops/reladd.c @@ -213,16 +213,111 @@ static void* subScnAdd2(ElfuElf *mrel, ElfuScn *ms, void *aux1, void *aux2) } -void elfu_mReladd(ElfuElf *me, ElfuElf *mrel) + +static void insertSymClone(ElfuElf *me, const ElfuScn *oldmsst, const ElfuSym *oldsym) +{ + GElf_Xword newsize; + void *newbuf; + ElfuScn *newscn = NULL; + ElfuSym *newsym; + char *oldsymname; + + assert(me); + assert(oldmsst); + assert(oldsym); + + /* If the old symbol pointed to a section, find its clone in the target */ + if (oldsym->scnptr) { + newscn = elfu_mScnByOldscn(me, oldsym->scnptr); + + /* If we didn't copy the section referenced, we won't + * copy this symbol either */ + if (!newscn) { + return; + } + } + + // TODO: Allocate symtab if none present + assert(me->symtab); + + /* Allocate memory for the cloned symbol */ + newsym = malloc(sizeof(*newsym)); + if (!newsym) { + ELFU_WARN("insertSymClone: malloc() failed for newsym.\n"); + goto ERROR; + } + + oldsymname = ELFU_SYMSTR(oldmsst, oldsym->name); + + /* Expand .strtab, append symbol name, link newsym to it */ + newsize = me->symtab->linkptr->shdr.sh_size + strlen(oldsymname) + 1; + newbuf = realloc(me->symtab->linkptr->data.d_buf, newsize); + if (!newbuf) { + ELFU_WARN("insertSymClone: realloc() failed for strtab.\n"); + goto ERROR; + } + + me->symtab->linkptr->data.d_buf = newbuf; + + newsym->name = me->symtab->linkptr->shdr.sh_size; + + strcpy(newbuf + newsym->name, oldsymname); + + me->symtab->linkptr->data.d_size = newsize; + me->symtab->linkptr->shdr.sh_size = newsize; + + + /* Copy all other fields */ + newsym->scnptr = newscn; + newsym->shndx = oldsym->shndx; /* If scnptr == NULL, this becomes relevant */ + newsym->bind = oldsym->bind; + newsym->other = oldsym->other; + newsym->size = oldsym->size; + newsym->type = oldsym->type; + newsym->value = oldsym->value; + + /* In executables, symbol addresses need to be in memory */ + if (newscn) { + newsym->value += newscn->shdr.sh_addr; + } + + /* Insert symbol */ + CIRCLEQ_INSERT_TAIL(&me->symtab->symtab.syms, newsym, elem); + + return; + + ERROR: + if (newsym) { + free(newsym); + } +} + +static void mergeSymtab(ElfuElf *me, const ElfuElf *mrel) +{ + ElfuSym *sym; + + assert(me); + assert(mrel); + + CIRCLEQ_FOREACH(sym, &mrel->symtab->symtab.syms, elem) { + insertSymClone(me, mrel->symtab, sym); + } +} + + + +void elfu_mReladd(ElfuElf *me, const ElfuElf *mrel) { assert(me); assert(mrel); /* For each section in object file, guess how to insert it */ - elfu_mScnForall(mrel, subScnAdd1, me, NULL); + elfu_mScnForall((ElfuElf*)mrel, subScnAdd1, me, NULL); + + mergeSymtab(me, mrel); /* Do relocations and other stuff */ - elfu_mScnForall(mrel, subScnAdd2, me, NULL); + elfu_mScnForall((ElfuElf*)mrel, subScnAdd2, me, NULL); /* Re-layout to accommodate new contents */ elfu_mLayoutAuto(me); -- cgit v1.2.3