First memory model of an ELF file
authornorly <ny-git@enpas.org>
Sun, 10 Feb 2013 00:36:16 +0000 (00:36 +0000)
committernorly <ny-git@enpas.org>
Mon, 11 Feb 2013 01:39:39 +0000 (01:39 +0000)
include/libelfu/libelfu.h
include/libelfu/model.h [new file with mode: 0644]
include/options.h
src/main.c
src/model/fromFile.c [new file with mode: 0644]
src/options.c

index ac9812b4cb6b4399d7a53a71386e4a213f094e02..7621bc4964d9060c9865ddd715c33b0a10851e01 100644 (file)
@@ -8,6 +8,7 @@
 #include <libelfu/copy.h>
 #include <libelfu/fixup.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 (file)
index 0000000..05f31ca
--- /dev/null
@@ -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
index f39f01e8de9858f0914af2e78ea325aa7ae65bdd..48f6580386f6d468c9883cd461a370fc6f95c662 100644 (file)
@@ -8,6 +8,8 @@ typedef struct {
   int printHeader;
   int printSegments;
   int printSections;
+  int copy;
+  int model;
 } CLIOpts;
 
 
index 4ed00597e6e9629c007d6d5910f0377f940c7c48..e664829c89c7d4a89b286ce7d9209728606001d8 100644 (file)
@@ -5,6 +5,8 @@
 #include <libelf.h>
 #include <gelf.h>
 
+#include <libelfu/libelfu.h>
+
 #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 (file)
index 0000000..f349335
--- /dev/null
@@ -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;
+}
index 014a1f213d32dfc1178f506db6453bafcce108d4..82b12bc1e820240604037ab6807cb6639ab6c59a 100644 (file)
@@ -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;