Loading...
cache-builder/AppCacheBuilder.cpp dyld-1042.1 dyld-1241.17
--- dyld/dyld-1042.1/cache-builder/AppCacheBuilder.cpp
+++ dyld/dyld-1241.17/cache-builder/AppCacheBuilder.cpp
@@ -159,6 +159,10 @@
     // readOnlyTextRegion
     callback(readOnlyTextRegion);
 
+    // -sectcreate
+    for (const Region& region : customDataRegions)
+        callback(region);
+
     // readExecuteRegion
     if ( readExecuteRegion.sizeInUse != 0 )
         callback(readExecuteRegion);
@@ -175,6 +179,14 @@
     if ( dataConstRegion.sizeInUse != 0 )
         callback(dataConstRegion);
 
+    // lateConstRegion
+    if ( lateConstRegion.sizeInUse != 0 )
+        callback(lateConstRegion);
+
+    // dataSptmRegion
+    if ( dataSptmRegion.sizeInUse != 0 )
+        callback(dataSptmRegion);
+
     // branchGOTsRegion
     if ( branchGOTsRegion.bufferSize != 0 )
         callback(branchGOTsRegion);
@@ -186,10 +198,6 @@
     // hibernateRegion
     if ( hibernateRegion.sizeInUse != 0 )
         callback(hibernateRegion);
-
-    // -sectcreate
-    for (const Region& region : customDataRegions)
-        callback(region);
 
     // prelinkInfoRegion
     if ( prelinkInfoDict != nullptr )
@@ -287,6 +295,17 @@
     return totalTargets;
 }
 
+bool AppCacheBuilder::hasSancovGateSection() const
+{
+    for ( const AppCacheDylibInfo& dylib : sortedDylibs ) {
+        const dyld3::MachOAnalyzer* ma = dylib.input->mappedFile.mh;
+        if ( ma->hasSection("__DATA", "__sancov_gate") )
+            return true;
+    }
+
+    return false;
+}
+
 bool AppCacheBuilder::removeStubs()
 {
     // Only eliminate stubs in the base kernel collection.  We could eliminate stubs
@@ -295,6 +314,9 @@
         return false;
 
     if ( _options.archs != &dyld3::GradedArchs::arm64e )
+        return false;
+
+    if ( hasSancovGateSection() )
         return false;
 
     return true;
@@ -398,7 +420,8 @@
                     return;
                 if ( (strcmp(segInfo.segName, "__DATA_CONST") == 0)
                     || (strcmp(segInfo.segName, "__PPLDATA_CONST") == 0)
-                    || (strcmp(segInfo.segName, "__LASTDATA_CONST") == 0) )
+                    || (strcmp(segInfo.segName, "__LASTDATA_CONST") == 0)
+                    || (strcmp(segInfo.segName, "__LATE_CONST") == 0) )
                     return;
                 if ( strcmp(segInfo.segName, "__LINKEDIT") == 0 )
                     return;
@@ -603,7 +626,9 @@
                     return;
                 if ( (strcmp(segInfo.segName, "__DATA_CONST") != 0)
                     && (strcmp(segInfo.segName, "__PPLDATA_CONST") != 0)
-                    && (strcmp(segInfo.segName, "__LASTDATA_CONST") != 0)  )
+                    && (strcmp(segInfo.segName, "__LASTDATA_CONST") != 0) )
+                    return;
+                if ( strcmp(segInfo.segName, "__LATE_CONST") == 0 )
                     return;
                 // kxld packs __DATA_CONST so we will do
                 uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
@@ -635,6 +660,96 @@
         dataConstRegion.name        = "__DATA_CONST";
     }
 
+    // __LATE_CONST segments
+    {
+        __block uint64_t offsetInRegion = 0;
+        for (DylibInfo& dylib : sortedDylibs) {
+            if (!dylib.input->mappedFile.mh->hasSplitSeg())
+                continue;
+
+            __block uint64_t textSegVmAddr = 0;
+            dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+                if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+                    textSegVmAddr = segInfo.vmAddr;
+                if ( (segInfo.protections & VM_PROT_EXECUTE) != 0 )
+                    return;
+                if ( (strcmp(segInfo.segName, "__LATE_CONST") != 0) )
+                    return;
+                // pack __LATE_CONST
+                uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+                offsetInRegion = align(offsetInRegion, segInfo.p2align);
+                offsetInRegion = align(offsetInRegion, minAlignmentP2);
+                size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
+                uint64_t dstCacheSegmentSize = align(segInfo.sizeOfSections, minAlignmentP2);
+                SegmentMappingInfo loc;
+                loc.srcSegment             = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+                loc.segName                = segInfo.segName;
+                loc.dstSegment             = nullptr;
+                loc.dstCacheUnslidAddress  = offsetInRegion; // This will be updated later once we've assigned addresses
+                loc.dstCacheFileOffset     = (uint32_t)offsetInRegion;
+                loc.dstCacheSegmentSize    = (uint32_t)dstCacheSegmentSize;
+                loc.dstCacheFileSize       = (uint32_t)copySize;
+                loc.copySegmentSize        = (uint32_t)copySize;
+                loc.srcSegmentIndex        = segInfo.segIndex;
+                loc.parentRegion           = &lateConstRegion;
+                dylib.cacheLocation[segInfo.segIndex] = loc;
+                offsetInRegion += loc.dstCacheSegmentSize;
+            });
+        }
+
+        // align r/o region end
+        lateConstRegion.bufferSize  = align(offsetInRegion, 14);
+        lateConstRegion.sizeInUse   = lateConstRegion.bufferSize;
+        lateConstRegion.initProt    = VM_PROT_READ;
+        lateConstRegion.maxProt     = VM_PROT_READ;
+        lateConstRegion.name        = "__LATE_CONST";
+    }
+
+    // __DATA_SPTM segments
+    {
+        __block uint64_t offsetInRegion = 0;
+        for (DylibInfo& dylib : sortedDylibs) {
+            if (!dylib.input->mappedFile.mh->hasSplitSeg())
+                continue;
+
+            __block uint64_t textSegVmAddr = 0;
+            dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+                if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+                    textSegVmAddr = segInfo.vmAddr;
+                if ( (segInfo.protections & VM_PROT_EXECUTE) != 0 )
+                    return;
+                if ( (strcmp(segInfo.segName, "__DATA_SPTM") != 0) )
+                    return;
+                uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+                offsetInRegion = align(offsetInRegion, segInfo.p2align);
+                offsetInRegion = align(offsetInRegion, minAlignmentP2);
+                size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
+                uint64_t dstCacheSegmentSize = align(segInfo.sizeOfSections, minAlignmentP2);
+                SegmentMappingInfo loc;
+                loc.srcSegment             = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+                loc.segName                = segInfo.segName;
+                loc.dstSegment             = nullptr;
+                loc.dstCacheUnslidAddress  = offsetInRegion; // This will be updated later once we've assigned addresses
+                loc.dstCacheFileOffset     = (uint32_t)offsetInRegion;
+                loc.dstCacheSegmentSize    = (uint32_t)dstCacheSegmentSize;
+                loc.dstCacheFileSize       = (uint32_t)copySize;
+                loc.copySegmentSize        = (uint32_t)copySize;
+                loc.srcSegmentIndex        = segInfo.segIndex;
+                loc.parentRegion           = &dataSptmRegion;
+                dylib.cacheLocation[segInfo.segIndex] = loc;
+                offsetInRegion += loc.dstCacheSegmentSize;
+            });
+        }
+
+        // align r/o region end
+        dataSptmRegion.bufferSize  = align(offsetInRegion, 14);
+        dataSptmRegion.sizeInUse   = dataSptmRegion.bufferSize;
+        dataSptmRegion.initProt    = VM_PROT_READ;
+        dataSptmRegion.maxProt     = VM_PROT_READ;
+        dataSptmRegion.name        = "__DATA_SPTM";
+    }
+
+
     // Branch GOTs
     if ( branchTargetsFromKexts != 0 ) {
         // 8-bytes per GOT
@@ -660,7 +775,8 @@
                     return;
                 if ( (strcmp(segInfo.segName, "__DATA_CONST") == 0)
                     || (strcmp(segInfo.segName, "__PPLDATA_CONST") == 0)
-                    || (strcmp(segInfo.segName, "__LASTDATA_CONST") == 0) )
+                    || (strcmp(segInfo.segName, "__LASTDATA_CONST") == 0)
+                    || (strcmp(segInfo.segName, "__LATE_CONST") == 0) )
                     return;
                 if ( segInfo.protections != (VM_PROT_READ | VM_PROT_WRITE) )
                     return;
@@ -1105,6 +1221,10 @@
         uint64_t numBytesForPageStarts = 0;
         if ( dataConstRegion.sizeInUse != 0 )
             numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(dataConstRegion.bufferSize));
+        if ( lateConstRegion.sizeInUse != 0 )
+            numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(lateConstRegion.bufferSize));
+        if ( dataSptmRegion.sizeInUse != 0 )
+            numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(dataSptmRegion.bufferSize));
         if ( branchGOTsRegion.bufferSize != 0 )
             numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(branchGOTsRegion.bufferSize));
         if ( readWriteRegion.sizeInUse != 0 )
@@ -4209,6 +4329,10 @@
 
         if ( dataConstRegion.sizeInUse != 0 )
             addSegmentStarts(dataConstRegion);
+        if ( lateConstRegion.sizeInUse != 0 )
+            addSegmentStarts(lateConstRegion);
+        if ( dataSptmRegion.sizeInUse != 0 )
+            addSegmentStarts(dataSptmRegion);
         if ( branchGOTsRegion.sizeInUse != 0 )
             addSegmentStarts(branchGOTsRegion);
         if ( readWriteRegion.sizeInUse != 0 )
@@ -4299,36 +4423,6 @@
         sectionsToAddToRegions[&readOnlyTextRegion] = 1;
     }
 
-    // __DATA_CONST
-    if ( dataConstRegion.sizeInUse != 0 ) {
-        vmOrder.emplace_back(&dataConstRegion, 14, 14);
-        fileOrder.emplace_back(&dataConstRegion, 14, 14);
-    }
-
-    // Split seg __TEXT_EXEC
-    if ( readExecuteRegion.sizeInUse != 0 ) {
-        vmOrder.emplace_back(&readExecuteRegion, 14, 14);
-        fileOrder.emplace_back(&readExecuteRegion, 14, 14);
-    }
-
-    // __BRANCH_STUBS
-    if ( branchStubsRegion.bufferSize != 0 ) {
-        vmOrder.emplace_back(&branchStubsRegion, 14, 14);
-        fileOrder.emplace_back(&branchStubsRegion, 14, 14);
-    }
-
-    // __TEXT_BOOT_EXEC
-    if ( textBootExecRegion.sizeInUse != 0 ) {
-        vmOrder.emplace_back(&textBootExecRegion, 14, 14);
-        fileOrder.emplace_back(&textBootExecRegion, 14, 14);
-    }
-
-    // __BRANCH_GOTS
-    if ( branchGOTsRegion.bufferSize != 0 ) {
-        vmOrder.emplace_back(&branchGOTsRegion, 14, 14);
-        fileOrder.emplace_back(&branchGOTsRegion, 14, 14);
-    }
-
     // -sectcreate
     // Align to 16k before we lay out all contiguous regions
     if ( !customSegments.empty() ) {
@@ -4354,6 +4448,48 @@
         // Align the last region after
         vmOrder.back().alignmentAfter = 14;
         fileOrder.back().alignmentAfter = 14;
+    }
+
+    // __DATA_CONST
+    if ( dataConstRegion.sizeInUse != 0 ) {
+        vmOrder.emplace_back(&dataConstRegion, 14, 14);
+        fileOrder.emplace_back(&dataConstRegion, 14, 14);
+    }
+
+    // __LATE_CONST
+    if ( lateConstRegion.sizeInUse != 0 ) {
+        vmOrder.emplace_back(&lateConstRegion, 14, 14);
+        fileOrder.emplace_back(&lateConstRegion, 14, 14);
+    }
+
+    // __DATA_SPTM
+    if ( dataSptmRegion.sizeInUse != 0 ) {
+        vmOrder.emplace_back(&dataSptmRegion, 14, 14);
+        fileOrder.emplace_back(&dataSptmRegion, 14, 14);
+    }
+
+    // Split seg __TEXT_EXEC
+    if ( readExecuteRegion.sizeInUse != 0 ) {
+        vmOrder.emplace_back(&readExecuteRegion, 14, 14);
+        fileOrder.emplace_back(&readExecuteRegion, 14, 14);
+    }
+
+    // __BRANCH_STUBS
+    if ( branchStubsRegion.bufferSize != 0 ) {
+        vmOrder.emplace_back(&branchStubsRegion, 14, 14);
+        fileOrder.emplace_back(&branchStubsRegion, 14, 14);
+    }
+
+    // __TEXT_BOOT_EXEC
+    if ( textBootExecRegion.sizeInUse != 0 ) {
+        vmOrder.emplace_back(&textBootExecRegion, 14, 14);
+        fileOrder.emplace_back(&textBootExecRegion, 14, 14);
+    }
+
+    // __BRANCH_GOTS
+    if ( branchGOTsRegion.bufferSize != 0 ) {
+        vmOrder.emplace_back(&branchGOTsRegion, 14, 14);
+        fileOrder.emplace_back(&branchGOTsRegion, 14, 14);
     }
 
     // __PRELINK_INFO
@@ -5193,6 +5329,20 @@
                 firstDataRegion = &dataConstRegion;
             if ( (lastDataRegion == nullptr) || (dataConstRegion.buffer > lastDataRegion->buffer) )
                 lastDataRegion = &dataConstRegion;
+        }
+
+        if ( lateConstRegion.sizeInUse != 0 ) {
+            if ( firstDataRegion == nullptr )
+                firstDataRegion = &lateConstRegion;
+            if ( (lastDataRegion == nullptr) || (lateConstRegion.buffer > lastDataRegion->buffer) )
+                lastDataRegion = &lateConstRegion;
+        }
+
+        if ( dataSptmRegion.sizeInUse != 0 ) {
+            if ( firstDataRegion == nullptr )
+                firstDataRegion = &dataSptmRegion;
+            if ( (lastDataRegion == nullptr) || (dataSptmRegion.buffer > lastDataRegion->buffer) )
+                lastDataRegion = &dataSptmRegion;
         }
 
         if ( branchGOTsRegion.bufferSize != 0 ) {