More rigorous sh_addr and sh_offset checking
authornorly <ny-git@enpas.org>
Thu, 30 May 2013 17:13:59 +0000 (18:13 +0100)
committernorly <ny-git@enpas.org>
Thu, 30 May 2013 17:13:59 +0000 (18:13 +0100)
src/elfops/check.c
src/model/fromFile.c

index daf6542698fb8171dc681ff570b484ac4c10f713..be8704bb45d5bd4d499d0eeeff50aa162639a4c6 100644 (file)
@@ -165,7 +165,10 @@ int elfu_eCheck(Elf *e)
        * Find parent PHDR: */
       for (j = 0; j < numPhdr; j++) {
         if (PHDR_CONTAINS_SCN_IN_MEMORY(&phdrs[j], &shdrs[i])) {
-          if (!PHDR_CONTAINS_SCN_IN_FILE(&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;
           }
index ee0536de26a630c876d3ec65f86464c12549ef7c..7b8bfd31d756fc87a2e85cda36d1874d8f7abcec 100644 (file)
@@ -42,14 +42,21 @@ static ElfuPhdr* parentPhdr(ElfuElf *me, ElfuScn *ms)
       continue;
     }
 
-    if (ms->shdr.sh_addr >= mp->phdr.p_vaddr
-        && OFFS_END(ms->shdr.sh_addr, ms->shdr.sh_size) <= OFFS_END(mp->phdr.p_vaddr, mp->phdr.p_memsz)) {
+    if (PHDR_CONTAINS_SCN_IN_MEMORY(&mp->phdr, &ms->shdr)) {
       return mp;
-    } else if (ms->shdr.sh_offset >= mp->phdr.p_offset
-               && OFFS_END(ms->shdr.sh_offset, SCNFILESIZE(&ms->shdr)) <= OFFS_END(mp->phdr.p_offset, mp->phdr.p_filesz)
-               && OFFS_END(ms->shdr.sh_offset, ms->shdr.sh_size) <= OFFS_END(mp->phdr.p_offset, mp->phdr.p_memsz)) {
+    }
+
+    /* Give sections a second chance if they do not have any sh_addr
+     * at all. */
+    /* Actually we don't, because it's ambiguous.
+     * Re-enable for experiments with strangely-formatted files.
+    if (ms->shdr.sh_addr == 0
+        && PHDR_CONTAINS_SCN_IN_FILE(&mp->phdr, &ms->shdr)
+        && OFFS_END(ms->shdr.sh_offset, ms->shdr.sh_size)
+            <= OFFS_END(mp->phdr.p_offset, mp->phdr.p_memsz)) {
       return mp;
     }
+    */
   }
 
   return NULL;
@@ -287,6 +294,15 @@ ElfuElf* elfu_mFromElf(Elf *e)
       ElfuPhdr *parent = parentPhdr(me, ms);
 
       if (parent) {
+        GElf_Off shaddr = parent->phdr.p_vaddr +
+                         (ms->shdr.sh_offset - parent->phdr.p_offset);
+
+        if (ms->shdr.sh_addr == 0) {
+          ms->shdr.sh_addr = shaddr;
+        } else {
+          assert(ms->shdr.sh_addr == shaddr);
+        }
+
         CIRCLEQ_INSERT_TAIL(&parent->childScnList, ms, elemChildScn);
       } else {
         CIRCLEQ_INSERT_TAIL(&me->orphanScnList, ms, elemChildScn);