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;
mp->phdr = *phdr;
- CIRCLEQ_INIT(&mp->phdrToScnList);
+ CIRCLEQ_INIT(&mp->childScnList);
+ CIRCLEQ_INIT(&mp->childPhdrList);
return mp;
}
ms->linkptr = NULL;
ms->infoptr = NULL;
+ ms->oldptr = NULL;
+
return ms;
/* General stuff */
- CIRCLEQ_INIT(&me->scnList);
CIRCLEQ_INIT(&me->phdrList);
+ CIRCLEQ_INIT(&me->orphanScnList);
me->shstrtab = NULL;
me->elfclass = gelf_getclass(e);
CIRCLEQ_INSERT_TAIL(&me->phdrList, mp, elem);
}
+ if (numPhdr > 0) {
+ ElfuPhdr *mp;
+
+ /* Find PHDR -> PHDR dependencies (needs sorted sections) */
+ CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
+ ElfuPhdr *mp2;
+
+ if (mp->phdr.p_type != PT_LOAD) {
+ continue;
+ }
+
+ CIRCLEQ_FOREACH(mp2, &me->phdrList, elem) {
+ if (mp2 == mp) {
+ continue;
+ }
+
+ if (mp->phdr.p_vaddr <= mp2->phdr.p_vaddr
+ && OFFS_END(mp2->phdr.p_vaddr, mp2->phdr.p_memsz) <= OFFS_END(mp->phdr.p_vaddr, mp->phdr.p_memsz)) {
+ CIRCLEQ_INSERT_TAIL(&mp->childPhdrList, mp2, elemChildPhdr);
+ }
+ }
+ }
+ }
+
/* Load sections */
assert(!elf_getshdrnum(e, &numShdr));
ElfuPhdr *parent = parentPhdr(me, ms);
if (parent) {
- CIRCLEQ_INSERT_TAIL(&parent->phdrToScnList, ms, elemPhdrToScn);
- }
- }
+ 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);
+ }
- /* Put sections into list of all sections */
- for (i = 0; i < numShdr - 1; i++) {
- CIRCLEQ_INSERT_TAIL(&me->scnList, secArray[i], elem);
+ CIRCLEQ_INSERT_TAIL(&parent->childScnList, ms, elemChildScn);
+ } else {
+ CIRCLEQ_INSERT_TAIL(&me->orphanScnList, ms, elemChildScn);
+ }
}
}