Loading...
dyld3/shared-cache/DyldSharedCache.cpp dyld-832.7.3 dyld-852
--- dyld/dyld-832.7.3/dyld3/shared-cache/DyldSharedCache.cpp
+++ dyld/dyld-852/dyld3/shared-cache/DyldSharedCache.cpp
@@ -57,6 +57,10 @@
 #if !(BUILDING_LIBDYLD || BUILDING_DYLD)
 #include "JSONWriter.h"
 #include <sstream>
+#endif
+
+#if (BUILDING_LIBDYLD || BUILDING_DYLD)
+VIS_HIDDEN bool gEnableSharedCacheDataConst = false;
 #endif
 
 
@@ -231,8 +235,8 @@
     return mappings[header.mappingCount-1].address + mappings[header.mappingCount-1].size;
 }
 
-void DyldSharedCache::forEachRegion(void (^handler)(const void* content, uint64_t vmAddr, uint64_t size, uint32_t permissions,
-                                                    uint64_t flags)) const
+void DyldSharedCache::forEachRegion(void (^handler)(const void* content, uint64_t vmAddr, uint64_t size,
+                                                    uint32_t initProt, uint32_t maxProt, uint64_t flags)) const
 {
     // <rdar://problem/49875993> sanity check cache header
     if ( strncmp(header.magic, "dyld_v1", 7) != 0 )
@@ -245,13 +249,13 @@
         const dyld_cache_mapping_info* mappings = (dyld_cache_mapping_info*)((char*)this + header.mappingOffset);
         const dyld_cache_mapping_info* mappingsEnd = &mappings[header.mappingCount];
         for (const dyld_cache_mapping_info* m=mappings; m < mappingsEnd; ++m) {
-            handler((char*)this + m->fileOffset, m->address, m->size, m->initProt, 0);
+            handler((char*)this + m->fileOffset, m->address, m->size, m->initProt, m->maxProt, 0);
         }
     } else {
         const dyld_cache_mapping_and_slide_info* mappings = (const dyld_cache_mapping_and_slide_info*)((char*)this + header.mappingWithSlideOffset);
         const dyld_cache_mapping_and_slide_info* mappingsEnd = &mappings[header.mappingCount];
         for (const dyld_cache_mapping_and_slide_info* m=mappings; m < mappingsEnd; ++m) {
-            handler((char*)this + m->fileOffset, m->address, m->size, m->initProt, m->flags);
+            handler((char*)this + m->fileOffset, m->address, m->size, m->initProt, m->maxProt, m->flags);
         }
     }
 }
@@ -460,16 +464,16 @@
     __block std::vector<uint64_t>   regionFileOffsets;
 
     result.reserve(256*1024);
-    forEachRegion(^(const void* content, uint64_t vmAddr, uint64_t size, uint32_t permissions,
-                    uint64_t flags) {
+    forEachRegion(^(const void* content, uint64_t vmAddr, uint64_t size,
+                    uint32_t initProt, uint32_t maxProt, uint64_t flags) {
         regionStartAddresses.push_back(vmAddr);
         regionSizes.push_back(size);
         regionFileOffsets.push_back((uint8_t*)content - (uint8_t*)this);
         char lineBuffer[256];
         const char* prot = "RW";
-        if ( permissions == (VM_PROT_EXECUTE|VM_PROT_READ) )
+        if ( maxProt == (VM_PROT_EXECUTE|VM_PROT_READ) )
             prot = "EX";
-        else if ( permissions == VM_PROT_READ )
+        else if ( maxProt == VM_PROT_READ )
             prot = "RO";
         if ( size > 1024*1024 )
             sprintf(lineBuffer, "mapping  %s %4lluMB 0x%0llX -> 0x%0llX\n", prot, size/(1024*1024), vmAddr, vmAddr+size);
@@ -512,8 +516,8 @@
 {
     __block uint64_t startAddr = 0;
     __block uint64_t endAddr = 0;
-    forEachRegion(^(const void* content, uint64_t vmAddr, uint64_t size, uint32_t permissions,
-                    uint64_t flags) {
+    forEachRegion(^(const void* content, uint64_t vmAddr, uint64_t size,
+                    uint32_t initProt, uint32_t maxProt, uint64_t flags) {
         if ( startAddr == 0 )
             startAddr = vmAddr;
         uint64_t end = vmAddr+size;
@@ -793,6 +797,59 @@
     }
 }
 
+#if (BUILDING_LIBDYLD || BUILDING_DYLD)
+void DyldSharedCache::changeDataConstPermissions(mach_port_t machTask, uint32_t permissions,
+                                                 DataConstLogFunc logFunc) const {
+
+    const dyld_cache_mapping_info* mappings = (dyld_cache_mapping_info*)((char*)this + header.mappingOffset);
+    uintptr_t slide = (uintptr_t)this - (uintptr_t)(mappings[0].address);
+
+    if ( (permissions & VM_PROT_WRITE) != 0 )
+        permissions |= VM_PROT_COPY;
+
+    forEachRegion(^(const void *, uint64_t vmAddr, uint64_t size,
+                    uint32_t initProt, uint32_t maxProt, uint64_t flags) {
+        void* content = (void*)(vmAddr + slide);
+        if ( ( flags & DYLD_CACHE_MAPPING_CONST_DATA) == 0 )
+            return;
+        if ( logFunc != nullptr ) {
+            logFunc("dyld: marking shared cache range 0x%x permissions: 0x%09lX -> 0x%09lX\n",
+                    permissions, (long)content, (long)content + size);
+        }
+        kern_return_t result = vm_protect(machTask, (vm_address_t)content, (vm_size_t)size, false, permissions);
+        if ( result != KERN_SUCCESS ) {
+            if ( logFunc != nullptr )
+                logFunc("dyld: failed to mprotect shared cache due to: %d\n", result);
+        }
+    });
+}
+
+DyldSharedCache::DataConstLazyScopedWriter::DataConstLazyScopedWriter(const DyldSharedCache* cache, mach_port_t machTask, DataConstLogFunc logFunc)
+    : cache(cache), machTask(machTask), logFunc(logFunc) {
+}
+
+DyldSharedCache::DataConstLazyScopedWriter::~DataConstLazyScopedWriter() {
+    if ( wasMadeWritable )
+        cache->changeDataConstPermissions(machTask, VM_PROT_READ, logFunc);
+}
+
+void DyldSharedCache::DataConstLazyScopedWriter::makeWriteable() {
+    if ( wasMadeWritable )
+        return;
+    if ( !gEnableSharedCacheDataConst )
+        return;
+    if ( cache == nullptr )
+        return;
+    wasMadeWritable = true;
+    cache->changeDataConstPermissions(machTask, VM_PROT_READ | VM_PROT_WRITE, logFunc);
+}
+
+DyldSharedCache::DataConstScopedWriter::DataConstScopedWriter(const DyldSharedCache* cache, mach_port_t machTask, DataConstLogFunc logFunc)
+    : writer(cache, machTask, logFunc) {
+    writer.makeWriteable();
+}
+#endif
+
 #if !(BUILDING_LIBDYLD || BUILDING_DYLD)
 // MRM map file generator
 std::string DyldSharedCache::generateJSONMap(const char* disposition) const {