Loading...
common/MachOFile.cpp dyld-1066.8 dyld-1162
--- dyld/dyld-1066.8/common/MachOFile.cpp
+++ dyld/dyld-1162/common/MachOFile.cpp
@@ -24,23 +24,36 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
+#include <strings.h>
 #include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/fcntl.h>
-#include <unistd.h>
 #include <TargetConditionals.h>
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_host.h>
+#include "Defines.h"
+#if TARGET_OS_EXCLAVEKIT
+  #define OSSwapBigToHostInt32 __builtin_bswap32
+  #define OSSwapBigToHostInt64 __builtin_bswap64
+  #define htonl                __builtin_bswap32
+#else
+  #include <sys/stat.h>
+  #include <sys/types.h>
+  #include <sys/errno.h>
+  #include <sys/fcntl.h>
+  #include <unistd.h>
+  #include <mach/host_info.h>
+  #include <mach/mach.h>
+  #include <mach/mach_host.h>
+#if SUPPORT_CLASSIC_RELOCS
+  #include <mach-o/reloc.h>
+  #include <mach-o/x86_64/reloc.h>
+#endif
 extern "C" {
   #include <corecrypto/ccdigest.h>
   #include <corecrypto/ccsha1.h>
   #include <corecrypto/ccsha2.h>
 }
-#include <mach-o/reloc.h>
-#include <mach-o/x86_64/reloc.h>
+#endif
+
+#include "Defines.h"
+
 #include <mach-o/nlist.h>
 
 #include "Array.h"
@@ -48,13 +61,13 @@
 #include "SupportedArchs.h"
 #include "CodeSigningTypes.h"
 
-#if BUILDING_DYLD || BUILDING_LIBDYLD
-    // define away restrict until rdar://60166935 is fixed
-    #define restrict
+#if (BUILDING_DYLD || BUILDING_LIBDYLD) && !TARGET_OS_EXCLAVEKIT
     #include <subsystem.h>
 #endif
 
 namespace dyld3 {
+
+#if !TARGET_OS_EXCLAVEKIT
 
 ////////////////////////////  posix wrappers ////////////////////////////////////////
 
@@ -101,6 +114,7 @@
 
     return result;
 }
+#endif // !TARGET_OS_EXCLAVEKIT
 
 
 ////////////////////////////  FatFile ////////////////////////////////////////
@@ -480,16 +494,18 @@
 };
 
 const MachOFile::PlatformInfo MachOFile::_s_platformInfos[] = {
-    { "macOS",       Platform::macOS,             LC_VERSION_MIN_MACOSX   },
-    { "iOS",         Platform::iOS,               LC_VERSION_MIN_IPHONEOS },
-    { "tvOS",        Platform::tvOS,              LC_VERSION_MIN_TVOS     },
-    { "watchOS",     Platform::watchOS,           LC_VERSION_MIN_WATCHOS  },
-    { "bridgeOS",    Platform::bridgeOS,          LC_BUILD_VERSION        },
-    { "MacCatalyst", Platform::iOSMac,            LC_BUILD_VERSION        },
-    { "iOS-sim",     Platform::iOS_simulator,     LC_BUILD_VERSION        },
-    { "tvOS-sim",    Platform::tvOS_simulator,    LC_BUILD_VERSION        },
-    { "watchOS-sim", Platform::watchOS_simulator, LC_BUILD_VERSION        },
-    { "driverKit",   Platform::driverKit,         LC_BUILD_VERSION        },
+    { "macOS",              Platform::macOS,                LC_VERSION_MIN_MACOSX   },
+    { "iOS",                Platform::iOS,                  LC_VERSION_MIN_IPHONEOS },
+    { "tvOS",               Platform::tvOS,                 LC_VERSION_MIN_TVOS     },
+    { "watchOS",            Platform::watchOS,              LC_VERSION_MIN_WATCHOS  },
+    { "bridgeOS",           Platform::bridgeOS,             LC_BUILD_VERSION        },
+    { "MacCatalyst",        Platform::iOSMac,               LC_BUILD_VERSION        },
+    { "iOS-sim",            Platform::iOS_simulator,        LC_BUILD_VERSION        },
+    { "tvOS-sim",           Platform::tvOS_simulator,       LC_BUILD_VERSION        },
+    { "watchOS-sim",        Platform::watchOS_simulator,    LC_BUILD_VERSION        },
+    { "driverKit",          Platform::driverKit,            LC_BUILD_VERSION        },
+    { "xrOS",               Platform::xrOS,                 LC_BUILD_VERSION        },
+    { "xrOS-sim",           Platform::xrOS_simulator,       LC_BUILD_VERSION        },
 };
 
 
@@ -640,7 +656,7 @@
     return false;
 }
 
-bool MachOFile::loadableIntoProcess(Platform processPlatform, const char* path) const
+bool MachOFile::loadableIntoProcess(Platform processPlatform, const char* path, bool internalInstall) const
 {
     if ( this->builtForPlatform(processPlatform) )
         return true;
@@ -683,7 +699,6 @@
     // macOS dylibs can be loaded into iOSMac processes
     if ( (iOSonMac) && this->builtForPlatform(Platform::macOS, true) )
         return true;
-
 
     return false;
 }
@@ -775,6 +790,26 @@
 #endif
 }
 
+bool MachOFile::isExclaveKitPlatform(Platform platform, Platform* basePlatform)
+{
+    switch ( platform ) {
+        case Platform::macOSExclaveKit:
+            if ( basePlatform )
+                *basePlatform = Platform::macOS;
+            return true;
+        case Platform::iOSExclaveKit:
+            if ( basePlatform )
+                *basePlatform = Platform::iOS;
+            return true;
+        case Platform::tvOSExclaveKit:
+            if ( basePlatform )
+                *basePlatform = Platform::tvOS;
+            return true;
+       default:
+            return false;
+    }
+}
+
 bool MachOFile::isSimulatorPlatform(Platform platform, Platform* basePlatform)
 {
     switch ( platform ) {
@@ -1122,6 +1157,14 @@
         }
     });
     return result;
+}
+
+bool MachOFile::hasConstObjCSection() const
+{
+    return hasSection("__DATA_CONST", "__objc_selrefs")
+        || hasSection("__DATA_CONST", "__objc_classrefs")
+        || hasSection("__DATA_CONST", "__objc_protorefs")
+        || hasSection("__DATA_CONST", "__objc_superrefs");
 }
 
 bool MachOFile::hasSection(const char* segName, const char* sectName) const
@@ -1223,6 +1266,10 @@
     if ( (count == 0) && !stopped ) {
         // The dylibs that make up libSystem can link with nothing
         // except for dylibs in libSystem.dylib which are ok to link with nothing (they are on bottom)
+#if TARGET_OS_EXCLAVEKIT
+        if ( !this->isDylib() || (strncmp(this->installName(), "/System/ExclaveKit/usr/lib/system/", 34) != 0) )
+            callback("/System/ExclaveKit/usr/lib/libSystem.dylib", false, false, false, 0x00010000, 0x00010000, stopped);
+#else
         if ( this->builtForPlatform(Platform::driverKit, true) ) {
             if ( !this->isDylib() || (strncmp(this->installName(), "/System/DriverKit/usr/lib/system/", 33) != 0) )
                 callback("/System/DriverKit/usr/lib/libSystem.B.dylib", false, false, false, 0x00010000, 0x00010000, stopped);
@@ -1231,8 +1278,9 @@
             if ( !this->isDylib() || (strncmp(this->installName(), "/usr/lib/system/", 16) != 0) )
                 callback("/usr/lib/libSystem.B.dylib", false, false, false, 0x00010000, 0x00010000, stopped);
         }
-    }
-#endif
+#endif // TARGET_OS_EXCLAVEKIT
+    }
+#endif // !BUILDING_SHARED_CACHE_UTIL && !BUILDING_DYLDINFO && !BUILDING_UNIT_TESTS
     diag.assertNoError();   // any malformations in the file should have been caught by earlier validate() call
 }
 
@@ -1247,9 +1295,7 @@
             if ( (strncmp(keyEqualsValue, "DYLD_", 5) == 0) ) {
                 const char* equals = strchr(keyEqualsValue, '=');
                 if ( equals != NULL ) {
-                    if ( strncmp(&equals[-5], "_PATH", 5) == 0 ) {
-                        callback(keyEqualsValue, stop);
-                    }
+                    callback(keyEqualsValue, stop);
                 }
             }
         }
@@ -1633,7 +1679,9 @@
             || (strncmp(dylibName, "/System/Cryptexes/OS/usr/lib/", 29) == 0)
             || (strncmp(dylibName, "/System/Cryptexes/OS/System/Library/", 36) == 0)
             || (strncmp(dylibName, "/System/Cryptexes/OS/System/iOSSupport/usr/lib/", 47) == 0)
-            || (strncmp(dylibName, "/System/Cryptexes/OS/System/iOSSupport/System/Library/", 54) == 0));
+            || (strncmp(dylibName, "/System/Cryptexes/OS/System/iOSSupport/System/Library/", 54) == 0)
+            || (strncmp(dylibName, "/System/ExclaveKit/usr/lib/", 27) == 0)
+            || (strncmp(dylibName, "/System/ExclaveKit/System/Library/", 34) == 0));
 }
 
 static bool startsWith(const char* buffer, const char* valueToFind) {
@@ -1682,37 +1730,16 @@
     return false;
 }
 
-// HACK: Remove this function.  Its only here until we can handle cache overflow
-static bool platformExcludesSharedCache_sim(const char* installName) {
-    if ( startsWith(installName, "/System/Library/PrivateFrameworks/iWorkImport.framework/") )
-        return true;
-    if ( startsWith(installName, "/System/Library/PrivateFrameworks/News") )
-        return true;
-    if ( strcmp(installName, "/System/Library/PrivateFrameworks/StocksUI.framework/StocksUI") == 0 )
-        return true;
-    if ( strcmp(installName, "/System/Library/PrivateFrameworks/NewsUI.framework/NewsUI") == 0 )
-        return true;
-    if ( strcmp(installName, "/System/Library/PrivateFrameworks/CompassUI.framework/CompassUI") == 0 )
-        return true;
-    if ( strcmp(installName, "/System/Library/PrivateFrameworks/WeatherUI.framework/WeatherUI") == 0 )
-        return true;
-    if ( strcmp(installName, "/System/Library/PrivateFrameworks/NewsUI2.framework/NewsUI2") == 0 )
-        return true;
-    return false;
-}
-
 // Returns true if the current platform requires that this install name be excluded from the shared cache
 // Note that this overrides any exclusion from anywhere else.
 static bool platformExcludesSharedCache(Platform platform, const char* installName) {
-    if ( MachOFile::isSimulatorPlatform(platform) )
-        return platformExcludesSharedCache_sim(installName);
     if ( (platform == dyld3::Platform::macOS) || (platform == dyld3::Platform::iOSMac) )
         return platformExcludesSharedCache_macOS(installName);
     // Everything else is based on iOS so just use that value
     return platformExcludesSharedCache_iOS(installName);
 }
 
-bool MachOFile::canBePlacedInDyldCache(const char* path, void (^failureReason)(const char*)) const
+bool MachOFile::canBePlacedInDyldCache(const char* path, void (^failureReason)(const char* format, ...)) const
 {
     if ( !isSharedCacheEligiblePath(path) ) {
         // Dont spam the user with an error about paths when we know these are never eligible.
@@ -1803,18 +1830,19 @@
     }
 
     // dylib can only depend on other dylibs in the shared cache
-    __block bool allDepPathsAreGood = true;
+    __block const char* badDep = nullptr;
     forEachDependentDylib(^(const char* loadPath, bool isWeak, bool isReExport, bool isUpward, uint32_t compatVersion, uint32_t curVersion, bool& stop) {
         // Skip weak links.  They are allowed to be missing
         if ( isWeak )
             return;
         if ( !isSharedCacheEligiblePath(loadPath) ) {
-            allDepPathsAreGood = false;
+            badDep = loadPath;
             stop = true;
         }
     });
-    if ( !allDepPathsAreGood ) {
-        failureReason("Depends on dylibs ineligable for dyld cache");
+    if ( badDep != nullptr ) {
+        failureReason("Depends on dylibs ineligible for dyld cache '%s'.  (cache dylibs must start /usr/lib or /System/Library or similar)",
+                      badDep);
         return false;
     }
 
@@ -2023,6 +2051,33 @@
                 return;
         }
 
+        // Check that shared cache dylibs don't use undefined lookup
+        {
+            __block bool bindsOk = true;
+
+            auto checkBind = ^(int libOrdinal, bool& stop) {
+                if ( libOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP ) {
+                    failureReason("has dynamic_lookup binds");
+                    bindsOk = false;
+                    stop = true;
+                }
+            };
+
+            if (hasChainedFixups()) {
+                fixups.forEachChainedFixupTarget(diag, ^(int libOrdinal, const char* symbolName, uint64_t addend, bool weakImport, bool& stop) {
+                    checkBind(libOrdinal, stop);
+                });
+            } else {
+                auto handler = ^(const mach_o::Fixups::BindTargetInfo &info, bool &stop) {
+                    checkBind(info.libOrdinal, stop);
+                };
+                fixups.forEachBindTarget_Opcodes(diag, true, handler, handler);
+            }
+
+            if ( !bindsOk )
+                return;
+        }
+
         passedLinkeditChecks = true;
     });
 
@@ -2188,7 +2243,9 @@
 
     return true;
 }
-
+#endif // BUILDING_APP_CACHE_UTIL
+
+#if BUILDING_APP_CACHE_UTIL || BUILDING_DYLDINFO
 bool MachOFile::usesClassicRelocationsInKernelCollection() const {
     // The xnu x86_64 static executable needs to do the i386->x86_64 transition
     // so will be emitted with classic relocations
@@ -2197,7 +2254,7 @@
     }
     return false;
 }
-#endif
+#endif // BUILDING_APP_CACHE_UTIL || BUILDING_DYLDINFO
 
 #if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
 static bool platformExcludesPrebuiltClosure_macOS(const char* path) {
@@ -2447,6 +2504,12 @@
                         chainEnd = true;
                     else
                         chain = (ChainedFixupPointerOnDisk*)((uint8_t*)chain + chainContent.arm64e.rebase.next*stride);
+                    break;
+                case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE:
+                    if ( chainContent.cache64e.regular.next == 0 )
+                        chainEnd = true;
+                    else
+                        chain = (ChainedFixupPointerOnDisk*)((uint8_t*)chain + chainContent.cache64e.regular.next*stride);
                     break;
                 case DYLD_CHAINED_PTR_64:
                 case DYLD_CHAINED_PTR_64_OFFSET:
@@ -2649,12 +2712,12 @@
     buffer[0] = '\0';
     archs.forEachArch(isOSBinary, ^(const char* archName) {
         if ( buffer[0] != '\0' )
-            strcat(buffer, "' or '");
-        strcat(buffer, archName);
-    });
-}
-
-const MachOFile* MachOFile::compatibleSlice(Diagnostics& diag, const void* fileContent, size_t contentSize, const char* path, Platform platform, bool isOSBinary, const GradedArchs& archs)
+            strlcat(buffer, "' or '", 256);
+        strlcat(buffer, archName, 256);
+    });
+}
+
+const MachOFile* MachOFile::compatibleSlice(Diagnostics& diag, const void* fileContent, size_t contentSize, const char* path, Platform platform, bool isOSBinary, const GradedArchs& archs, bool internalInstall)
 {
     const MachOFile* mf = nullptr;
     if ( const dyld3::FatFile* ff = dyld3::FatFile::isFatFile(fileContent) ) {
@@ -2690,7 +2753,7 @@
         return nullptr;
     }
 
-    if ( !mf->loadableIntoProcess(platform, path) ) {
+    if ( !mf->loadableIntoProcess(platform, path, internalInstall) ) {
         __block Platform havePlatform = Platform::unknown;
         mf->forEachSupportedPlatform(^(Platform aPlat, uint32_t minOS, uint32_t sdk) {
             havePlatform = aPlat;
@@ -3009,7 +3072,7 @@
 
     // The aux KC may have __DATA first, in which case we always want to vm_copy to the right place
     bool hasOutOfOrderSegments = false;
-#if BUILDING_APP_CACHE_UTIL
+#if BUILDING_APP_CACHE_UTIL || BUILDING_DYLDINFO
     uint64_t textSegVMAddr = preferredLoadAddress();
     hasOutOfOrderSegments = textSegVMAddr != lowestVmAddr;
 #endif
@@ -3081,7 +3144,7 @@
     return true;
 }
 
-
+#if !TARGET_OS_EXCLAVEKIT
 // Note, this has to match the kernel
 static const uint32_t hashPriorities[] = {
     CS_HASHTYPE_SHA1,
@@ -3238,6 +3301,7 @@
         }
     });
 }
+#endif // !TARGET_OS_EXCLAVEKIT
 
 // These are mangled symbols for all the variants of operator new and delete
 // which a main executable can define (non-weak) and override the
@@ -3250,7 +3314,8 @@
     "__ZnwmSt11align_val_t", "__ZnwmSt11align_val_tRKSt9nothrow_t",
     "__ZnamSt11align_val_t", "__ZnamSt11align_val_tRKSt9nothrow_t",
     "__ZdlPvSt11align_val_t", "__ZdlPvSt11align_val_tRKSt9nothrow_t", "__ZdlPvmSt11align_val_t",
-    "__ZdaPvSt11align_val_t", "__ZdaPvSt11align_val_tRKSt9nothrow_t", "__ZdaPvmSt11align_val_t"
+    "__ZdaPvSt11align_val_t", "__ZdaPvSt11align_val_tRKSt9nothrow_t", "__ZdaPvmSt11align_val_t",
+    "__ZnwmSt19__type_descriptor_t", "__ZnamSt19__type_descriptor_t"
 };
 
 void MachOFile::forEachTreatAsWeakDef(void (^handler)(const char* symbolName))
@@ -3289,6 +3354,17 @@
             }
             else if ( fixupLoc->arm64e.bind.bind == 0 ) {
                 this->high8             = fixupLoc->arm64e.rebase.high8;
+            }
+            break;
+        case DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE:
+            this->authenticated = fixupLoc->cache64e.auth.auth;
+            if ( this->authenticated ) {
+                this->key               = fixupLoc->cache64e.auth.keyIsData ? 2 : 0; // true -> DA (2), false -> IA (0)
+                this->usesAddrDiversity = fixupLoc->cache64e.auth.addrDiv;
+                this->diversity         = fixupLoc->cache64e.auth.diversity;
+            }
+            else {
+                this->high8 = fixupLoc->cache64e.regular.high8;
             }
             break;
         case DYLD_CHAINED_PTR_64:
@@ -3970,7 +4046,7 @@
                 }
                 else if ( sect->addr+sect->size > seg->vmaddr+seg->vmsize ) {
                     bool ignoreError = !enforceFormat(Malformed::sectionsAddrRangeWithinSegment);
-#if BUILDING_APP_CACHE_UTIL
+#if BUILDING_APP_CACHE_UTIL || BUILDING_DYLDINFO
                     if ( (seg->vmsize == 0) && !strcmp(seg->segname, "__CTF") )
                         ignoreError = true;
 #endif