Basic x86-64 support, not very usable in practice
[centaur.git] / src / elfops / check.c
index c7ebc7d5ebfc92eec645b5b03f91137421aae26a..e184b268493f83460f09178d1ecf40247327db17 100644 (file)
@@ -1,7 +1,5 @@
 #include <assert.h>
 #include <stdlib.h>
-#include <libelf/libelf.h>
-#include <libelf/gelf.h>
 #include <libelfu/libelfu.h>
 
 int elfu_eCheck(Elf *e)
@@ -26,6 +24,11 @@ int elfu_eCheck(Elf *e)
     goto ERROR;
   }
 
+  if (ehdr.e_machine != EM_386 && ehdr.e_machine != EM_X86_64) {
+    ELFU_WARN("Sorry, only x86-32 and x86-64 ELF files are supported at the moment.\n");
+    goto ERROR;
+  }
+
   if (elf_getphdrnum(e, &numPhdr)) {
     ELFU_WARNELF("elf_getphdrnum");
     goto ERROR;
@@ -126,14 +129,14 @@ int elfu_eCheck(Elf *e)
       }
 
       /* Section should not overlap with PHDRs. */
-      if (OVERLAPPING(shdrs[i].sh_offset, elfu_gScnSizeFile(&shdrs[i]),
+      if (OVERLAPPING(shdrs[i].sh_offset, SCNFILESIZE(&shdrs[i]),
                       ehdr.e_phoff, numPhdr * ehdr.e_phentsize)) {
         ELFU_WARN("elfu_eCheck: Section %d overlaps with PHDR.\n", i);
         goto ERROR;
       }
 
       /* Section should not overlap with SHDRs. */
-      if (OVERLAPPING(shdrs[i].sh_offset, elfu_gScnSizeFile(&shdrs[i]),
+      if (OVERLAPPING(shdrs[i].sh_offset, SCNFILESIZE(&shdrs[i]),
                       ehdr.e_shoff, numShdr * ehdr.e_shentsize)) {
         ELFU_WARN("elfu_eCheck: Section %d overlaps with SHDRs.\n", i);
         goto ERROR;
@@ -154,12 +157,31 @@ int elfu_eCheck(Elf *e)
         }
 
         /* Sections must not overlap in file. */
-        if (OVERLAPPING(shdrs[i].sh_offset, elfu_gScnSizeFile(&shdrs[i]),
-                        shdrs[j].sh_offset, elfu_gScnSizeFile(&shdrs[j]))) {
+        if (OVERLAPPING(shdrs[i].sh_offset, SCNFILESIZE(&shdrs[i]),
+                        shdrs[j].sh_offset, SCNFILESIZE(&shdrs[j]))) {
           ELFU_WARN("elfu_eCheck: Sections %d and %d overlap in file.\n", i, j);
           goto ERROR;
         }
       }
+
+      /* Section addr/offset should match parent PHDR.
+       * Find parent PHDR: */
+      for (j = 0; j < numPhdr; j++) {
+        if (PHDR_CONTAINS_SCN_IN_MEMORY(&phdrs[j], &shdrs[i])) {
+          GElf_Off shoff = phdrs[j].p_offset + (shdrs[i].sh_addr - phdrs[j].p_vaddr);
+
+          if (shdrs[i].sh_offset != shoff
+              || !PHDR_CONTAINS_SCN_IN_FILE(&phdrs[j], &shdrs[i])) {
+            ELFU_WARN("elfu_eCheck: Memory/file offsets/sizes are not congruent for SHDR %d, PHDR %d.\n", i, j);
+            goto ERROR;
+          }
+        }
+      }
+
+      /* sh_link members should not point to sections out of range. */
+      if (shdrs[i].sh_link >= numShdr) {
+        ELFU_WARN("elfu_eCheck: Bogus sh_link in SHDR %d.\n", i);
+      }
     }
   }