summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libelfu/libelfu.h1
-rw-r--r--include/libelfu/model.h50
-rw-r--r--include/options.h1
-rw-r--r--src/main.c14
-rw-r--r--src/model/fromFile.c152
-rw-r--r--src/options.c4
6 files changed, 222 insertions, 0 deletions
diff --git a/include/libelfu/libelfu.h b/include/libelfu/libelfu.h
index 1c40541..28a1e9a 100644
--- a/include/libelfu/libelfu.h
+++ b/include/libelfu/libelfu.h
@@ -6,6 +6,7 @@
#include <libelfu/analysis.h>
#include <libelfu/lookup.h>
+#include <libelfu/model.h>
#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 <sys/queue.h>
+
+#include <elf.h>
+#include <gelf.h>
+
+
+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..ddd44be 100644
--- a/include/options.h
+++ b/include/options.h
@@ -8,6 +8,7 @@ typedef struct {
int printHeader;
int printSegments;
int printSections;
+ int model;
} CLIOpts;
diff --git a/src/main.c b/src/main.c
index 9791feb..87b47ef 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,6 +5,8 @@
#include <libelf.h>
#include <gelf.h>
+#include <libelfu/libelfu.h>
+
#include "elfhandle.h"
#include "options.h"
#include "printing.h"
@@ -57,6 +59,18 @@ int main(int argc, char **argv)
}
+ /* Generate a memory model of the file */
+ if (opts.model) {
+ ElfuElf *me;
+
+ me = elfu_modelFromElf(hIn.e);
+
+ if (me) {
+ printf("Model successfully loaded.\n");
+ }
+ }
+
+
EXIT:
if (hOut.e) {
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 <stdio.h>
+#include <stdlib.h>
+
+#include <libelf.h>
+#include <gelf.h>
+
+#include <libelfu/libelfu.h>
+
+
+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..42637f0 100644
--- a/src/options.c
+++ b/src/options.c
@@ -34,6 +34,7 @@ void parseOptions(CLIOpts *opts, int argc, char **argv)
{"print-header", 0, 0, 10001},
{"print-segments", 0, 0, 10002},
{"print-sections", 0, 0, 10003},
+ {"model", 0, 0, 10004},
{NULL, 0, NULL, 0}
};
@@ -55,6 +56,9 @@ void parseOptions(CLIOpts *opts, int argc, char **argv)
case 10003:
opts->printSections = 1;
break;
+ case 10004:
+ opts->model = 1;
+ break;
case '?':
default:
goto USAGE;