summaryrefslogtreecommitdiff
path: root/src/modelops/fromFile.c
diff options
context:
space:
mode:
authornorly <ny-git@enpas.org>2013-06-15 21:42:53 +0100
committernorly <ny-git@enpas.org>2013-06-15 22:02:26 +0100
commit825613b8e4f141a82d2b8be22d7fba68fed5ef96 (patch)
tree8ade4e195c1a77a3814c44109c4f5cc9e1a5ced7 /src/modelops/fromFile.c
parent5868bb32246367139f0d17a989650964f90a7958 (diff)
Basic x86-64 support, not very usable in practice
Turns out that x86-64 aligns LOAD segments to 0x200000 bytes. Given that the mapping starts at 0x400000, there is not much room to expand... so there will be a need to add additional LOAD headers.
Diffstat (limited to 'src/modelops/fromFile.c')
-rw-r--r--src/modelops/fromFile.c100
1 files changed, 74 insertions, 26 deletions
diff --git a/src/modelops/fromFile.c b/src/modelops/fromFile.c
index 28ecb85..bc089bf 100644
--- a/src/modelops/fromFile.c
+++ b/src/modelops/fromFile.c
@@ -5,41 +5,69 @@
#include <libelfu/libelfu.h>
-static void parseSymtab32(ElfuScn *ms, ElfuScn**origScnArr)
+static void parseSymtab(ElfuElf *me, ElfuScn *ms, ElfuScn**origScnArr)
{
+ 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);
- 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);
+ 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;
- sym->name = 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;
- sym->shndx = cursym->st_shndx;
- switch (cursym->st_shndx) {
+
+ 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;
+
+
+
+ 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;
break;
default:
- sym->scnptr = origScnArr[cursym->st_shndx - 1];
+ sym->scnptr = origScnArr[sym->shndx - 1];
break;
}
-
-
- CIRCLEQ_INSERT_TAIL(&ms->symtab.syms, sym, elem);
}
}
@@ -60,10 +88,8 @@ static void parseReltab32(ElfuScn *ms)
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;
@@ -72,6 +98,32 @@ static void parseReltab32(ElfuScn *ms)
}
+static void parseRelatab64(ElfuScn *ms)
+{
+ size_t i;
+
+ 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);
+ }
+}
+
+
static int cmpScnOffs(const void *ms1, const void *ms2)
{
assert(ms1);
@@ -360,11 +412,7 @@ ElfuElf* elfu_mFromElf(Elf *e)
case SHT_SYMTAB:
me->symtab = ms;
case SHT_DYNSYM:
- if (me->elfclass == ELFCLASS32) {
- parseSymtab32(ms, secArray);
- } else if (me->elfclass == ELFCLASS64) {
- // TODO
- }
+ parseSymtab(me, ms, secArray);
break;
}
}
@@ -379,14 +427,14 @@ ElfuElf* elfu_mFromElf(Elf *e)
if (me->elfclass == ELFCLASS32) {
parseReltab32(ms);
} else if (me->elfclass == ELFCLASS64) {
- // TODO
+ // Not used on x86-64
}
break;
case SHT_RELA:
if (me->elfclass == ELFCLASS32) {
// TODO
} else if (me->elfclass == ELFCLASS64) {
- // TODO
+ parseRelatab64(ms);
}
break;
}