summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/modelops/fromFile.c5
-rw-r--r--src/modelops/relocate.c8
-rw-r--r--src/modelops/toFile.c60
3 files changed, 68 insertions, 5 deletions
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 <assert.h>
#include <stdlib.h>
+#include <string.h>
#include <libelfu/libelfu.h>
+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