summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/elfops/check.c5
-rw-r--r--src/model/fromFile.c26
2 files changed, 25 insertions, 6 deletions
diff --git a/src/elfops/check.c b/src/elfops/check.c
index daf6542..be8704b 100644
--- a/src/elfops/check.c
+++ b/src/elfops/check.c
@@ -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;
}
diff --git a/src/model/fromFile.c b/src/model/fromFile.c
index ee0536d..7b8bfd3 100644
--- a/src/model/fromFile.c
+++ b/src/model/fromFile.c
@@ -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);