summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornorly <ny-git@enpas.org>2013-02-23 01:46:32 +0000
committernorly <ny-git@enpas.org>2013-02-23 01:49:43 +0000
commit58b6f8de8862c9ccba763d3607afb5495727e4d6 (patch)
treeca23423174e1238cebc4f77ab3602bf0b8e4864e
parent7b04e102bb2ad0189f66d4878fe92d6fa22a1990 (diff)
Add run-time sanity checks
-rw-r--r--include/libelfu/lookup.h4
-rw-r--r--include/libelfu/model.h7
-rw-r--r--src/lookup/scnSize.c13
-rw-r--r--src/main.c3
-rw-r--r--src/model/check.c104
-rw-r--r--src/model/count.c6
-rw-r--r--src/model/fromFile.c18
-rw-r--r--src/model/section-name.c27
8 files changed, 176 insertions, 6 deletions
diff --git a/include/libelfu/lookup.h b/include/libelfu/lookup.h
index 2cca5df..2506512 100644
--- a/include/libelfu/lookup.h
+++ b/include/libelfu/lookup.h
@@ -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
diff --git a/include/libelfu/model.h b/include/libelfu/model.h
index 1b5f6b6..588d57a 100644
--- a/include/libelfu/model.h
+++ b/include/libelfu/model.h
@@ -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
index 0000000..2c65ca1
--- /dev/null
+++ b/src/lookup/scnSize.c
@@ -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;
+}
diff --git a/src/main.c b/src/main.c
index 68becad..eaf2709 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
index 0000000..cd45f2d
--- /dev/null
+++ b/src/model/check.c
@@ -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;
+}
diff --git a/src/model/count.c b/src/model/count.c
index d42f806..274b9d8 100644
--- a/src/model/count.c
+++ b/src/model/count.c
@@ -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++;
}
diff --git a/src/model/fromFile.c b/src/model/fromFile.c
index f349335..26ce6a7 100644
--- a/src/model/fromFile.c
+++ b/src/model/fromFile.c
@@ -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
index 0000000..0e5d903
--- /dev/null
+++ b/src/model/section-name.c
@@ -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];
+}