From 80e4f848d96000030cf1494d3ca64e86b0fdca11 Mon Sep 17 00:00:00 2001 From: norly Date: Sun, 10 Feb 2013 00:36:16 +0000 Subject: [PATCH] First memory model of an ELF file --- include/libelfu/libelfu.h | 1 + include/libelfu/model.h | 50 +++++++++++++ include/options.h | 2 + src/main.c | 23 +++++- src/model/fromFile.c | 152 ++++++++++++++++++++++++++++++++++++++ src/options.c | 8 ++ 6 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 include/libelfu/model.h create mode 100644 src/model/fromFile.c diff --git a/include/libelfu/libelfu.h b/include/libelfu/libelfu.h index ac9812b..7621bc4 100644 --- a/include/libelfu/libelfu.h +++ b/include/libelfu/libelfu.h @@ -8,6 +8,7 @@ #include #include #include +#include #endif diff --git a/include/libelfu/model.h b/include/libelfu/model.h new file mode 100644 index 0000000..05f31ca --- /dev/null +++ b/include/libelfu/model.h @@ -0,0 +1,50 @@ +#ifndef __LIBELFU_MODEL_H__ +#define __LIBELFU_MODEL_H__ + +#include + +#include +#include + + +typedef struct ElfuData { + Elf_Data data; + + CIRCLEQ_ENTRY(ElfuData) elem; +} ElfuData; + + +typedef struct ElfuScn { + GElf_Shdr shdr; + + CIRCLEQ_HEAD(DataList, ElfuData) dataList; + + CIRCLEQ_ENTRY(ElfuScn) elem; +} ElfuScn; + + +typedef struct ElfuPhdr { + GElf_Phdr phdr; + + CIRCLEQ_ENTRY(ElfuPhdr) elem; +} ElfuPhdr; + + +typedef struct { + int elfclass; + GElf_Ehdr ehdr; + + CIRCLEQ_HEAD(ScnList, ElfuScn) scnList; + CIRCLEQ_HEAD(PhdrList, ElfuPhdr) phdrList; + + ElfuPhdr *entryBase; + GElf_Addr *entryOffs; +} ElfuElf; + + + +ElfuPhdr* elfu_modelFromPhdr(GElf_Phdr *phdr); +ElfuScn* elfu_modelFromSection(Elf_Scn *scn); +ElfuElf* elfu_modelFromElf(Elf *e); + +#endif diff --git a/include/options.h b/include/options.h index f39f01e..48f6580 100644 --- a/include/options.h +++ b/include/options.h @@ -8,6 +8,8 @@ typedef struct { int printHeader; int printSegments; int printSections; + int copy; + int model; } CLIOpts; diff --git a/src/main.c b/src/main.c index 4ed0059..e664829 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,8 @@ #include #include +#include + #include "elfhandle.h" #include "options.h" #include "printing.h" @@ -57,8 +59,25 @@ int main(int argc, char **argv) } /* Copy the input ELF to the output file */ - if (opts.fnOutput) { - elfu_copyElf(hOut.e, hIn.e); + if (!opts.fnOutput) { + if (opts.copy) { + fprintf(stderr, "Error: Missing output file name for requested operation.\n"); + } + } else { + if (opts.copy) { + elfu_copyElf(hOut.e, hIn.e); + } + } + + /* Generate a memory model of the file */ + if (opts.model) { + ElfuElf *me; + + me = elfu_modelFromElf(hIn.e); + + if (me) { + printf("Model successfully loaded.\n"); + } } diff --git a/src/model/fromFile.c b/src/model/fromFile.c new file mode 100644 index 0000000..f349335 --- /dev/null +++ b/src/model/fromFile.c @@ -0,0 +1,152 @@ +#include +#include + +#include +#include + +#include + + +ElfuPhdr* elfu_modelFromPhdr(GElf_Phdr *phdr) +{ + ElfuPhdr *mp; + + mp = malloc(sizeof(ElfuPhdr)); + if (!mp) { + return NULL; + } + + mp->phdr = *phdr; + + return mp; +} + + +ElfuScn* elfu_modelFromSection(Elf_Scn *scn) +{ + ElfuScn *ms; + Elf_Data *data; + + ms = malloc(sizeof(ElfuScn)); + if (!ms) { + return NULL; + } + + CIRCLEQ_INIT(&ms->dataList); + + + if (gelf_getshdr(scn, &ms->shdr) != &ms->shdr) { + fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1)); + goto out; + } + + + + /* Copy each data part in source segment */ + data = elf_rawdata(scn, NULL); + while (data) { + ElfuData *md; + + md = malloc(sizeof(ElfuData)); + if (!md) { + goto out; + } + + md->data = *data; + + CIRCLEQ_INSERT_TAIL(&ms->dataList, md, elem); + + data = elf_rawdata(scn, data); + } + + return ms; + + out: + // FIXME + return NULL; +} + + + + +ElfuElf* elfu_modelFromElf(Elf *e) +{ + ElfuElf *me; + + me = malloc(sizeof(ElfuElf)); + if (!me) { + return NULL; + } + + CIRCLEQ_INIT(&me->scnList); + CIRCLEQ_INIT(&me->phdrList); + + /* + * General stuff + */ + me->elfclass = gelf_getclass(e); + if (me->elfclass == ELFCLASSNONE) { + fprintf(stderr, "getclass() failed: %s\n", elf_errmsg(-1)); + } + + if (!gelf_getehdr(e, &me->ehdr)) { + fprintf(stderr, "gelf_getehdr() failed: %s\n", elf_errmsg(-1)); + goto out; + } + + + /* + * Sections + */ + Elf_Scn *scn; + + scn = elf_getscn(e, 1); + while (scn) { + ElfuScn *ms = elfu_modelFromSection(scn); + + if (ms) { + CIRCLEQ_INSERT_TAIL(&me->scnList, ms, elem); + } else { + goto out; + } + + scn = elf_nextscn(e, scn); + } + + + + /* + * Segments + */ + size_t i, n; + + if (elf_getphdrnum(e, &n)) { + fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1)); + } + + for (i = 0; i < n; i++) { + GElf_Phdr phdr; + ElfuPhdr *mp; + + if (gelf_getphdr(e, i, &phdr) != &phdr) { + fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1)); + break; + } + + mp = elfu_modelFromPhdr(&phdr); + + if (mp) { + CIRCLEQ_INSERT_TAIL(&me->phdrList, mp, elem); + } else { + goto out; + } + } + + + + return me; + + out: + // FIXME + return NULL; +} diff --git a/src/options.c b/src/options.c index 014a1f2..82b12bc 100644 --- a/src/options.c +++ b/src/options.c @@ -34,6 +34,8 @@ void parseOptions(CLIOpts *opts, int argc, char **argv) {"print-header", 0, 0, 10001}, {"print-segments", 0, 0, 10002}, {"print-sections", 0, 0, 10003}, + {"copy", 0, 0, 10004}, + {"model", 0, 0, 10005}, {NULL, 0, NULL, 0} }; @@ -55,6 +57,12 @@ void parseOptions(CLIOpts *opts, int argc, char **argv) case 10003: opts->printSections = 1; break; + case 10004: + opts->copy = 1; + break; + case 10005: + opts->model = 1; + break; case '?': default: goto USAGE; -- 2.30.2