static BOOL FinalizeSections(PMEMORYMODULE module) { int i; PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); #ifdef _WIN64 uintptr_t imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000); #else #define imageOffset 0 #endif SECTIONFINALIZEDATA sectionData; sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); sectionData.alignedAddress = ALIGN_DOWN(sectionData.address, module->pageSize); sectionData.size = GetRealSectionSize(module, section); sectionData.characteristics = section->Characteristics; sectionData.last = FALSE; section++; // loop through all sections and change access flags for (i=1; i<module->headers->FileHeader.NumberOfSections; i++, section++) { LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); LPVOID alignedAddress = ALIGN_DOWN(sectionAddress, module->pageSize); DWORD sectionSize = GetRealSectionSize(module, section); // Combine access flags of all sections that share a page // TODO(fancycode): We currently share flags of a trailing large section // with the page of a first small section. This should be optimized. if (sectionData.alignedAddress == alignedAddress || (uintptr_t) sectionData.address + sectionData.size > (uintptr_t) alignedAddress) { // Section shares page with previous if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) { sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE; } else { sectionData.characteristics |= section->Characteristics; } sectionData.size = (DWORD)((((uintptr_t)sectionAddress) + sectionSize) - (uintptr_t) sectionData.address); continue; } if (!FinalizeSection(module, §ionData)) { return FALSE; } sectionData.address = sectionAddress; sectionData.alignedAddress = alignedAddress; sectionData.size = sectionSize; sectionData.characteristics = section->Characteristics; } sectionData.last = TRUE; if (!FinalizeSection(module, §ionData)) { return FALSE; } #ifndef _WIN64 #undef imageOffset #endif return TRUE; }
//============================================================================= // // // //============================================================================= bool CreateSections() { int pick = 0; MarkInternalSubsectors(); while (pick < numsubsectors) { if (ISDONE(pick, processed_subsectors)) { pick++; continue; } subsector_t *subsector = &subsectors[pick]; seg_t *workseg = NULL; vertex_t *startpt = NULL; NewSection(subsector->render_sector); while (1) { if (!ISDONE(subsector-subsectors, processed_subsectors)) { SETDONE(subsector-subsectors, processed_subsectors); section->subsectors.Push(subsector); SectionForSubsector[subsector - subsectors] = int(section - &Sections[0]); } bool result = AddSubSector(subsector, startpt, &workseg); if (!result) { return false; // couldn't create Sections } else if (workseg != NULL) { // crossing into another subsector seg_t *partner = workseg->PartnerSeg; if (workseg->v2 != partner->v1) { DPrintf("Inconsistent subsector references in seg %d. Cannot create Sections.\n", workseg-segs); return false; } subsector = partner->Subsector; startpt = workseg->v1; } else { // loop complete. Check adjoining subsectors for other loops to // be added to this section if (!FindNextSeg(&workseg)) { return false; } else if (workseg == NULL) { // No more subsectors found. This section is complete! FinalizeSection(); break; } else { subsector = workseg->Subsector; // If this is a regular seg, start there, otherwise start // at the subsector's first seg startpt = workseg->sidedef == NULL? NULL : workseg->v1; NewLoop(); } } } } if (!CheckSections()) return false; SetReferences(); Sections.ShrinkToFit(); SectionLoops.ShrinkToFit(); SectionLines.ShrinkToFit(); tesselateSections(); return true; }