Add run-time sanity checks
authornorly <ny-git@enpas.org>
Sat, 23 Feb 2013 01:46:32 +0000 (01:46 +0000)
committernorly <ny-git@enpas.org>
Sat, 23 Feb 2013 01:49:43 +0000 (01:49 +0000)
include/libelfu/lookup.h
include/libelfu/model.h
src/lookup/scnSize.c [new file with mode: 0644]
src/main.c
src/model/check.c [new file with mode: 0644]
src/model/count.c
src/model/fromFile.c
src/model/section-name.c [new file with mode: 0644]

index 2cca5df15c162e88fa2e8ad6c250c1c553585b07..250651271a6d04ea5147cf94d6d47e7ed863e386 100644 (file)
@@ -7,8 +7,12 @@
 #include <libelfu/types.h>
 
 char* elfu_sectionName(Elf *e, Elf_Scn *scn);
+
 Elf_Scn* elfu_sectionByName(Elf *e, char *name);
+
 Elf_Scn* elfu_firstSectionInSegment(Elf *e, GElf_Phdr *phdr);
 Elf_Scn* elfu_lastSectionInSegment(Elf *e, GElf_Phdr *phdr);
 
+size_t elfu_scnSizeFile(const GElf_Shdr *shdr);
+
 #endif
index 1b5f6b6d5e8897729e111dedcc47d99edfe6b7c1..588d57a0159d05c0dda9521f3178dba7babb690b 100644 (file)
@@ -37,8 +37,7 @@ typedef struct {
   CIRCLEQ_HEAD(ScnList, ElfuScn) scnList;
   CIRCLEQ_HEAD(PhdrList, ElfuPhdr) phdrList;
 
-  ElfuPhdr *entryBase;
-  GElf_Addr *entryOffs;
+  ElfuScn *shstrtab;
 } ElfuElf;
 
 
@@ -46,6 +45,10 @@ typedef struct {
 size_t elfu_countSections(ElfuElf *me);
 size_t elfu_countPHDRs(ElfuElf *me);
 
+char* elfu_modelScnName(ElfuElf *me, ElfuScn *ms);
+
+int elfu_modelCheck(ElfuElf *me);
+
 ElfuPhdr* elfu_modelFromPhdr(GElf_Phdr *phdr);
 ElfuScn* elfu_modelFromSection(Elf_Scn *scn);
 ElfuElf* elfu_modelFromElf(Elf *e);
diff --git a/src/lookup/scnSize.c b/src/lookup/scnSize.c
new file mode 100644 (file)
index 0000000..2c65ca1
--- /dev/null
@@ -0,0 +1,13 @@
+#include <assert.h>
+#include <sys/types.h>
+#include <gelf.h>
+#include <libelfu/libelfu.h>
+
+
+
+size_t elfu_scnSizeFile(const GElf_Shdr *shdr)
+{
+  assert(shdr);
+
+  return shdr->sh_type == SHT_NOBITS ? 0 : shdr->sh_size;
+}
index 68becadf0beb7319a807b2be510e3af389a35a6b..eaf2709ccac412158cceeea297e083275fbe7352 100644 (file)
@@ -68,6 +68,9 @@ int main(int argc, char **argv)
     if (me) {
       printf("Model successfully loaded.\n");
 
+      elfu_modelCheck(me);
+      printf("Model checked.\n");
+
       elfu_modelToElf(me, hOut.e);
 
       printf("Model converted to ELF, ready to be written.\n");
diff --git a/src/model/check.c b/src/model/check.c
new file mode 100644 (file)
index 0000000..cd45f2d
--- /dev/null
@@ -0,0 +1,104 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <libelfu/libelfu.h>
+
+
+
+static int isOverlapping(size_t off1, size_t sz1, size_t off2, size_t sz2)
+{
+  size_t end1 = off1 + sz1;
+  size_t end2 = off2 + sz2;
+
+  if (off2 >= off1 && off2 < end1) {
+    return 1;
+  } else if (off1 >= off2 && off1 < end2) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+
+static int cmpScnOffs(const void *ms1, const void *ms2)
+{
+  assert(ms1);
+  assert(ms2);
+
+  ElfuScn *s1 = *(ElfuScn**)ms1;
+  ElfuScn *s2 = *(ElfuScn**)ms2;
+
+  assert(s1);
+  assert(s2);
+
+
+  if (s1->shdr.sh_offset < s2->shdr.sh_offset) {
+    return -1;
+  } else if (s1->shdr.sh_offset == s2->shdr.sh_offset) {
+    return 0;
+  } else /* if (s1->shdr.sh_offset > s2->shdr.sh_offset) */ {
+    return 1;
+  }
+}
+
+
+int elfu_modelCheck(ElfuElf *me)
+{
+  ElfuScn *ms;
+  size_t numSecs;
+  ElfuScn **sortedSecs;
+  size_t i;
+
+  /* Sort sections by offset in file */
+  numSecs = elfu_countSections(me);
+  sortedSecs = malloc(numSecs * sizeof(*sortedSecs));
+  if (!sortedSecs) {
+    fprintf(stderr, "elfu_check: Failed to allocate memory.\n");
+  }
+
+  i = 0;
+  CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
+    sortedSecs[i] = ms;
+    i++;
+  }
+  assert(i = numSecs);
+
+  qsort(sortedSecs, numSecs, sizeof(*sortedSecs), cmpScnOffs);
+
+
+  /* Check for overlapping sections */
+  for (i = 0; i < numSecs - 1; i++) {
+    if (sortedSecs[i]->shdr.sh_offset + elfu_scnSizeFile(&sortedSecs[i]->shdr)
+        > sortedSecs[i+1]->shdr.sh_offset) {
+      fprintf(stderr, "elfu_check: Found overlapping sections: %s and %s.\n",
+                      elfu_modelScnName(me, sortedSecs[i]),
+                      elfu_modelScnName(me, sortedSecs[i+1]));
+    }
+  }
+
+
+  /* Check for sections overlapping with EHDR */
+  for (i = 0; i < numSecs; i++) {
+    if (sortedSecs[i]->shdr.sh_offset < me->ehdr.e_ehsize) {
+      fprintf(stderr, "elfu_check: Found section overlapping with EHDR: %s.\n",
+                      elfu_modelScnName(me, sortedSecs[i]));
+    }
+  }
+
+
+  /* Check for sections overlapping with PHDRs */
+  for (i = 0; i < numSecs; i++) {
+    if (isOverlapping(sortedSecs[i]->shdr.sh_offset,
+                      elfu_scnSizeFile(&sortedSecs[i]->shdr),
+                      me->ehdr.e_phoff,
+                      me->ehdr.e_phentsize * me->ehdr.e_phnum)) {
+      fprintf(stderr, "elfu_check: Found section overlapping with PHDRs: %s.\n",
+                      elfu_modelScnName(me, sortedSecs[i]));
+    }
+  }
+
+  free(sortedSecs);
+
+  return 0;
+}
index d42f806c6dba14974cf03e9b12817dc8333188e3..274b9d8f3d36f45d4116f7d2801dda00c0bb6c35 100644 (file)
@@ -1,13 +1,17 @@
+#include <assert.h>
 #include <sys/types.h>
 #include <libelfu/libelfu.h>
 
 
 
+/* NULL section is not counted! */
 size_t elfu_countSections(ElfuElf *me)
 {
   ElfuScn *ms;
   size_t i = 0;
 
+  assert(me);
+
   CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
     i++;
   }
@@ -21,6 +25,8 @@ size_t elfu_countPHDRs(ElfuElf *me)
   ElfuPhdr *mp;
   size_t i = 0;
 
+  assert(me);
+
   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
     i++;
   }
index f349335751900d03f56e48161137784bd5512541..26ce6a7b11a2d7385ff70c7a1fb3f3ca59b4a360 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/types.h>
 
 #include <libelf.h>
 #include <gelf.h>
@@ -72,6 +73,13 @@ ElfuScn* elfu_modelFromSection(Elf_Scn *scn)
 ElfuElf* elfu_modelFromElf(Elf *e)
 {
   ElfuElf *me;
+  Elf_Scn *scn;
+  size_t shstrndx;
+  size_t i, n;
+
+  if (elf_getshdrstrndx(e, &shstrndx) != 0) {
+    shstrndx = 0;
+  }
 
   me = malloc(sizeof(ElfuElf));
   if (!me) {
@@ -80,6 +88,7 @@ ElfuElf* elfu_modelFromElf(Elf *e)
 
   CIRCLEQ_INIT(&me->scnList);
   CIRCLEQ_INIT(&me->phdrList);
+  me->shstrtab = NULL;
 
   /*
    * General stuff
@@ -98,19 +107,22 @@ ElfuElf* elfu_modelFromElf(Elf *e)
   /*
    * Sections
    */
-  Elf_Scn *scn;
-
   scn = elf_getscn(e, 1);
+  i = 1;
   while (scn) {
     ElfuScn *ms = elfu_modelFromSection(scn);
 
     if (ms) {
       CIRCLEQ_INSERT_TAIL(&me->scnList, ms, elem);
+      if (i == shstrndx) {
+        me->shstrtab = ms;
+      }
     } else {
       goto out;
     }
 
     scn = elf_nextscn(e, scn);
+    i++;
   }
 
 
@@ -118,8 +130,6 @@ ElfuElf* elfu_modelFromElf(Elf *e)
   /*
    * Segments
    */
-  size_t i, n;
-
   if (elf_getphdrnum(e, &n)) {
     fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
   }
diff --git a/src/model/section-name.c b/src/model/section-name.c
new file mode 100644 (file)
index 0000000..0e5d903
--- /dev/null
@@ -0,0 +1,27 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include <libelf.h>
+#include <gelf.h>
+
+#include <libelfu/libelfu.h>
+
+
+
+char* elfu_modelScnName(ElfuElf *me, ElfuScn *ms)
+{
+  assert(me);
+  assert(ms);
+
+  if (!me->shstrtab) {
+    return NULL;
+  }
+
+  if (CIRCLEQ_EMPTY(&me->shstrtab->dataList)) {
+    return NULL;
+  }
+
+  /* Don't take multiple data parts into account. */
+  ElfuData *md = me->shstrtab->dataList.cqh_first;
+  return &((char*)md->data.d_buf)[ms->shdr.sh_name];
+}