Loading...
common/DyldSharedCache.h dyld-1340 dyld-960
--- dyld/dyld-1340/common/DyldSharedCache.h
+++ dyld/dyld-960/common/DyldSharedCache.h
@@ -41,90 +41,27 @@
 #endif
 
 #include "dyld_cache_format.h"
-#include "Architecture.h"
 #include "CachePatching.h"
 #include "Diagnostics.h"
 #include "MachOAnalyzer.h"
-#include "Header.h"
-
-#if !(BUILDING_LIBDYLD || BUILDING_DYLD)
 #include "JSON.h"
-#endif
-
-typedef dyld3::MachOFile::PointerMetaData  PointerMetaData;
 
 namespace dyld4 {
     class PrebuiltLoader;
     struct PrebuiltLoaderSet;
 }
 
-namespace mach_o {
-    struct FunctionVariants;
-}
-
 namespace objc_opt {
 struct objc_opt_t;
 }
 
-namespace objc
-{
-struct HeaderInfoRO;
-struct HeaderInfoRW;
-class SelectorHashTable;
-class ClassHashTable;
-class ProtocolHashTable;
-}
-
 struct SwiftOptimizationHeader;
-
-struct VIS_HIDDEN ObjCOptimizationHeader
-{
-    uint32_t version;
-    uint32_t flags;
-    uint64_t headerInfoROCacheOffset;
-    uint64_t headerInfoRWCacheOffset;
-    uint64_t selectorHashTableCacheOffset;
-    uint64_t classHashTableCacheOffset;
-    uint64_t protocolHashTableCacheOffset;
-    uint64_t relativeMethodSelectorBaseAddressOffset;
-};
-
-// convenience tuple for tracking file by fs/inode
-struct VIS_HIDDEN FileIdTuple
-{
-                FileIdTuple() { ::bzero(this, sizeof(FileIdTuple)); }
-#if !TARGET_OS_EXCLAVEKIT
-                FileIdTuple(const struct stat&);
-                FileIdTuple(const char* path);
-                FileIdTuple(uint64_t fsidScalar, uint64_t fsobjidScalar);
-    explicit    operator bool() const;
-    bool        operator==(const FileIdTuple& other) const;
-    bool        getPath(char pathBuff[PATH_MAX]) const;
-    uint64_t    inode() const;
-    uint64_t    fsID() const;
-#endif
-
-private:
-    void        init(const struct stat&);
-
-#if !TARGET_OS_EXCLAVEKIT
-    fsid_t      fsid;       // file system
-    fsobj_id_t  fsobjid;    // inode within filesystem
-#endif // !TARGET_OS_EXCLAVEKIT
-};
 
 class VIS_HIDDEN DyldSharedCache
 {
 public:
 
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-    // FIXME: Delete this as its no longer used
-    struct FileAlias
-    {
-        std::string             realPath;
-        std::string             aliasPath;
-    };
-
+#if BUILDING_CACHE_BUILDER
     enum CodeSigningDigestMode
     {
         SHA256only = 0,
@@ -142,10 +79,10 @@
     {
         std::string                                 outputFilePath;
         std::string                                 outputMapFilePath;
-        mach_o::Architecture                        arch;
-        mach_o::Platform                            platform;
+        const dyld3::GradedArchs*                   archs;
+        dyld3::Platform                             platform;
         LocalSymbolsMode                            localSymbolMode;
-        uint64_t                                    cacheConfiguration;
+        bool                                        optimizeStubs;
         bool                                        optimizeDyldDlopens;
         bool                                        optimizeDyldLaunches;
         CodeSigningDigestMode                       codeSigningDigestMode;
@@ -158,7 +95,7 @@
         bool                                        evictLeafDylibsOnOverflow;
         std::unordered_map<std::string, unsigned>   dylibOrdering;
         std::unordered_map<std::string, unsigned>   dirtyDataSegmentOrdering;
-        json::Node                                  objcOptimizations;
+        dyld3::json::Node                           objcOptimizations;
         std::string                                 loggingPrefix;
         // Customer and dev caches share a local symbols file.  Only one will get this set to emit the file
         std::string                                 localSymbolsPath;
@@ -181,75 +118,62 @@
         uint64_t                    inode;                  // only recorded if inodesAreSameAsRuntime
     };
 
+    struct CreateResults
+    {
+        std::string                             errorMessage;
+        std::set<std::string>                   warnings;
+        std::set<const dyld3::MachOAnalyzer*>   evictions;
+    };
+
+
+    struct FileAlias
+    {
+        std::string             realPath;
+        std::string             aliasPath;
+    };
+
+
+    // This function verifies the set of dylibs that will go into the cache are self contained.  That the depend on no dylibs
+    // outset the set.  It will call back the loader function to try to find any mising dylibs.
+    static bool verifySelfContained(std::vector<MappedMachO>& dylibsToCache,
+                                    std::unordered_set<std::string>& badZippered,
+                                    MappedMachO (^loader)(const std::string& runtimePath, Diagnostics& diag), std::vector<std::pair<DyldSharedCache::MappedMachO, std::set<std::string>>>& excluded);
+
+
+    //
+    // This function is single threaded and creates a shared cache. The cache file is created in-memory.
+    //
+    // Inputs:
+    //      options:        various per-platform flags
+    //      dylibsToCache:  a list of dylibs to include in the cache
+    //      otherOsDylibs:  a list of other OS dylibs and bundle which should have load info added to the cache
+    //      osExecutables:  a list of main executables which should have closures created in the cache
+    //
+    // Returns:
+    //    On success:
+    //         cacheContent: start of the allocated cache buffer which must be vm_deallocated after the caller writes out the buffer.
+    //         cacheLength:  size of the allocated cache buffer
+    //         cdHash:       hash of the code directory of the code blob of the created cache
+    //         warnings:     all warning messsages generated during the creation of the cache
+    //
+    //    On failure:
+    //         cacheContent: nullptr
+    //         errorMessage: the string describing why the cache could not be created
+    //         warnings:     all warning messsages generated before the failure
+    //
+    static CreateResults create(const CreateOptions&               options,
+                                const dyld3::closure::FileSystem&  fileSystem,
+                                const std::vector<MappedMachO>&    dylibsToCache,
+                                const std::vector<MappedMachO>&    otherOsDylibs,
+                                const std::vector<MappedMachO>&    osExecutables);
+
+
     //
     // Returns a text "map" file as a big string
     //
     std::string         mapFile() const;
 
-#endif // BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-
-#if !TARGET_OS_EXCLAVEKIT
-    //
-    // When the dyld cache is mapped from files, there is one region that is dynamically constructed
-    //
-    class DynamicRegion
-    {
-    public:
-        static DynamicRegion*   make(uintptr_t prefAddress=0);
-        void                    free();
-
-        void                    setDyldCacheFileID(FileIdTuple);
-        void                    setOSCryptexPath(const char*);
-        void                    setCachePath(const char*);
-        void                    setReadOnly();
-        void                    setSystemWideFlags(__uint128_t);
-        void                    setProcessorFlags(__uint128_t);
-
-        bool                    validMagic() const;
-        uint32_t                version() const;
-
-        // available in version 0
-        bool                    getDyldCacheFileID(FileIdTuple& ids) const;
-
-        // available in version 1
-        const char*             osCryptexPath() const;
-
-        // available in version 2
-        const char*             cachePath() const;
-
-        // available in version 3
-        __uint128_t             getSystemWideFunctionVariantFlags() const;
-        __uint128_t             getProcessorFunctionVariantFlags() const;
-
-        static size_t           size();
-
-    private:
-                        DynamicRegion();
-
-        static constexpr const char* sMagic = "dyld_data    v3";
-
-        // fields in v0
-        char            _magic[16];              // e.g. "dyld_data    v0"
-        FileIdTuple     _dyldCache;              // the inode of the main file for this dyld cache
-
-        // fields added in v1
-        uint32_t        _osCryptexPathOffset;
-
-        // fields added in v2
-        uint32_t        _cachePathOffset;
-
-        // fields added in v3
-        uint64_t        _paddingToAlign;
-        __uint128_t     _systemWideFunctionVariantFlags;  // system wide function-variant flags set in launchd
-        __uint128_t     _processorFunctionVariantFlags;   // arm64 or x86_64 specific function-variant flags
-    };
-
-
-    //
-    // Returns the DynamicRegion of the dyld cache
-    //
-    const DynamicRegion*   dynamicRegion() const;
-#endif // !TARGET_OS_EXCLAVEKIT
+#endif // BUILDING_CACHE_BUILDER
 
 
     //
@@ -261,14 +185,14 @@
     //
     // Returns the platform the cache is for
     //
-    mach_o::Platform    platform() const;
+    dyld3::Platform    platform() const;
 
 
     //
     // Iterates over each dylib in the cache
     //
-    void                forEachImage(void (^handler)(const mach_o::Header* hdr, const char* installName)) const;
-    void                forEachDylib(void (^handler)(const mach_o::Header* hdr, const char* installName, uint32_t imageIndex, uint64_t inode, uint64_t mtime, bool& stop)) const;
+    void                forEachImage(void (^handler)(const mach_header* mh, const char* installName)) const;
+    void                forEachDylib(void (^handler)(const dyld3::MachOAnalyzer* ma, const char* installName, uint32_t imageIndex, uint64_t inode, uint64_t mtime, bool& stop)) const;
 
 
     //
@@ -278,9 +202,16 @@
 
 
     //
+    // Is this path (which we know is in the shared cache), overridable
+    //
+    bool                isOverridablePath(const char* dylibPath) const;
+
+
+    //
     // Path is to a dylib in the cache and this is an optimized cache so that path cannot be overridden
     //
     bool                hasNonOverridablePath(const char* dylibPath) const;
+
 
     //
     // Check if this shared cache file contains local symbols info
@@ -296,10 +227,12 @@
     //
     const bool          hasLocalSymbolsInfoFile() const;
 
-    //
-    // Get string name for a given cache type
-    //
-    static const char*   getCacheTypeName(uint64_t cacheType);
+
+    //
+    // Get code signature mapped address
+    //
+    uint64_t             getCodeSignAddress() const;
+
 
     //
     // Searches cache for dylib with specified mach_header
@@ -316,7 +249,6 @@
     // Get image entry from index
     //
     const mach_header*  getIndexedImageEntry(uint32_t index, uint64_t& mTime, uint64_t& node) const;
-    const mach_header*  getIndexedImageEntry(uint32_t index) const;
 
 
     // iterates over all dylibs and aliases
@@ -325,7 +257,7 @@
     //
     // If path is a dylib in the cache, return is mach_header
     //
-    const mach_o::Header* getImageFromPath(const char* dylibPath) const;
+    const dyld3::MachOFile* getImageFromPath(const char* dylibPath) const;
 
     //
     // Get image path from index
@@ -342,33 +274,14 @@
     //
     void                forEachImageTextSegment(void (^handler)(uint64_t loadAddressUnslid, uint64_t textSegmentSize, const uuid_t dylibUUID, const char* installName, bool& stop)) const;
 
-    //
-    // Returns the dyld_cache_image_text_info[] from the cache header
-    //
-    std::span<const dyld_cache_image_text_info> textImageSegments() const;
-
-    // Get the path from a dyld_cache_image_text_info
-    std::string_view imagePath(const dyld_cache_image_text_info& info) const;
 
     //
     // Iterates over each of the three regions in the cache
     //
     void                forEachRegion(void (^handler)(const void* content, uint64_t vmAddr, uint64_t size,
                                                       uint32_t initProt, uint32_t maxProt, uint64_t flags,
-                                                      uint64_t fileOffset,
                                                       bool& stopRegion)) const;
 
-
-    //
-    // Iterates over each of the TPRO regions in the cache
-    //
-    void                forEachTPRORegion(void (^handler)(const void* content, uint64_t unslidVMAddr, uint64_t vmSize,
-                                                          bool& stopRegion)) const;
-
-    //
-    // Gets a name for the mapping.
-    //
-    static const char*  mappingName(uint32_t maxProt, uint64_t flags);
 
     //
     // Iterates over each of the mappings in the cache and all subCaches
@@ -392,22 +305,7 @@
     uint32_t            numSubCaches() const;
 
     //
-    // Returns index of subCache containing the address
-    //
-    int32_t            getSubCacheIndex(const void* addr) const;
-
-    //
-    // Gets uuid of the subCache
-    //
-    void            getSubCacheUuid(uint8_t index, uint8_t uuid[]) const;
-
-    //
-    // Returns the vmOffset of the subCache
-    //
-    uint64_t  getSubCacheVmOffset(uint8_t index) const;
-
-    //
-    // Returns the address of the first dyld_cache_image_info in the cache
+    // Returns the address of the the first dyld_cache_image_info in the cache
     //
     const dyld_cache_image_info* images() const;
     
@@ -448,9 +346,9 @@
      void                forEachLocalSymbolEntry(void (^handler)(uint64_t dylibCacheVMOffset, uint32_t nlistStartIndex, uint32_t nlistCount, bool& stop)) const;
 
     //
-    // Returns if an address range is in this cache, and if so if in an immutable area
-    //
-    bool                inCache(const void* addr, size_t length, bool& immutable) const;
+    // Returns if an address range is in this cache, and if so if in a read-only area
+    //
+    bool                inCache(const void* addr, size_t length, bool& readOnly) const;
 
     //
     // Returns true if a path is an alternate path (symlink)
@@ -473,11 +371,6 @@
     // returns the vm size required to map cache
     //
     uint64_t            mappedSize() const;
-
-    //
-    // Returns the cache PBLS, if one exists
-    //
-    const dyld4::PrebuiltLoaderSet* dylibsLoaderSet() const;
 
 
     //
@@ -502,22 +395,6 @@
     const dyld4::PrebuiltLoaderSet* findLaunchLoaderSet(const char* executablePath) const;
 
     //
-    // searches cache for PrebuiltLoader for program
-    //
-    const dyld4::PrebuiltLoaderSet* findLaunchLoaderSetWithCDHash(const char* cdHashString) const;
-
-
-    //
-    // Iterates over each of the prewarming data entries
-    //
-    void                forEachPrewarmingEntry(void (^handler)(const void* content, uint64_t unslidVMAddr, uint64_t vmSize)) const;
-
-    //
-    // Iterates over function variant pointers in the dyld cache
-    //
-    void forEachFunctionVariantPatchLocation(void (^handler)(const void* loc, PointerMetaData pmd, const mach_o::FunctionVariants& fvs, const mach_o::Header* dylibHdr, int variantIndex, bool& stop)) const;
-
-    //
     // searches cache for PrebuiltLoader for program by cdHash
     //
     bool hasLaunchLoaderSetWithCDHash(const char* cdHashString) const;
@@ -538,19 +415,14 @@
     const uint8_t* legacyCacheDataRegionBuffer() const;
 
     //
+    // Returns a pointer to the shared cache optimized Objective-C data structures
+    //
+    const objc_opt::objc_opt_t* objcOpt() const;
+
+    //
     // Returns a pointer to the shared cache optimized Objective-C pointer structures
     //
     const void* objcOptPtrs() const;
-
-    bool                            hasOptimizedObjC() const;
-    uint32_t                        objcOptVersion() const;
-    uint32_t                        objcOptFlags() const;
-    const objc::HeaderInfoRO*       objcHeaderInfoRO() const;
-    const objc::HeaderInfoRW*       objcHeaderInfoRW() const;
-    const objc::SelectorHashTable*  objcSelectorHashTable() const;
-    const objc::ClassHashTable*     objcClassHashTable() const;
-    const objc::ProtocolHashTable*  objcProtocolHashTable() const;
-    const void*                     objcRelativeMethodListsBaseAddress() const;
 
 #if !(BUILDING_LIBDYLD || BUILDING_DYLD)
     //
@@ -581,38 +453,24 @@
     //
     bool              addressInText(uint64_t cacheOffset, uint32_t* index) const;
 
-    const void*       patchTable() const;
-
     uint32_t          patchInfoVersion() const;
     uint32_t          patchableExportCount(uint32_t imageIndex) const;
-    void              forEachPatchableExport(uint32_t imageIndex,
-                                             void (^handler)(uint32_t dylibVMOffsetOfImpl, const char* exportName,
-                                                             PatchKind kind)) const;
-#if BUILDING_SHARED_CACHE_UTIL
+    void              forEachPatchableExport(uint32_t imageIndex, void (^handler)(uint32_t dylibVMOffsetOfImpl, const char* exportName)) const;
     void              forEachPatchableUseOfExport(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
                                                   void (^handler)(uint32_t userImageIndex, uint32_t userVMOffset,
-                                                                  dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend,
-                                                                  bool isWeakImport)) const;
-#endif
+                                                                  dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend)) const;
     // Use this when you have a root of at imageIndex, and are trying to patch a cached dylib at userImageIndex
     bool              shouldPatchClientOfImage(uint32_t imageIndex, uint32_t userImageIndex) const;
     void              forEachPatchableUseOfExportInImage(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl, uint32_t userImageIndex,
-                                                         void (^handler)(uint32_t userVMOffset, dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend,
-                                                                         bool isWeakImport)) const;
+                                                         void (^handler)(uint32_t userVMOffset, dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend)) const;
     // Note, use this for weak-defs when you just want all uses of an export, regardless of which dylib they are in.
     void              forEachPatchableUseOfExport(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
                                                   void (^handler)(uint64_t cacheVMOffset,
-                                                                  dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend,
-                                                                  bool isWeakImport)) const;
-    // Used to walk just the GOT uses of a given export.  The above method will walk both regular and GOT uses
-    void              forEachPatchableGOTUseOfExport(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
-                                                     void (^handler)(uint64_t cacheVMOffset,
-                                                                     dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend,
-                                                                     bool isWeakImport)) const;
+                                                                  dyld3::MachOLoaded::PointerMetaData pmd, uint64_t addend)) const;
 
 #if !(BUILDING_LIBDYLD || BUILDING_DYLD)
     // MRM map file generator
-    std::string generateJSONMap(const char* disposition, uuid_t cache_uuid, bool verbose) const;
+    std::string generateJSONMap(const char* disposition) const;
 
     // This generates a JSON representation of deep reverse dependency information in the cache.
     // For each dylib, the output will contain the list of all the other dylibs transitively
@@ -637,15 +495,16 @@
     dyld3::MachOAnalyzer::VMAddrConverter makeVMAddrConverter(bool contentRebased) const;
 #endif
 
-    // Returns true if the given MachO is in the shared cache range.
+    // Returns if the the given MachO is in the shared cache range.
     // Returns false if the cache is null.
     static bool inDyldCache(const DyldSharedCache* cache, const dyld3::MachOFile* mf);
-    static bool inDyldCache(const DyldSharedCache* cache, const mach_o::Header* header);
-
-    // Returns ture if the given path is a subCache filepath.
-    static bool isSubCachePath(const char* leafName);
 
 #if !(BUILDING_LIBDYLD || BUILDING_DYLD)
+    //
+    // Apply rebases for manually mapped shared cache
+    //
+    void applyCacheRebases() const;
+
     // mmap() an shared cache file read/only but laid out like it would be at runtime
     static const DyldSharedCache* mapCacheFile(const char* path,
                                                uint64_t baseCacheUnslidAddress,
@@ -653,19 +512,6 @@
 
     static std::vector<const DyldSharedCache*> mapCacheFiles(const char* path);
 #endif
-
-    //
-    // Fixes up the DATA pages in just this subcache file
-    // Takes a slide, so that some tools can call this to get unslid VM addresses, while
-    // dyld can pass a slide to apply.
-    //
-    mach_o::Error fixupDataPages(intptr_t slideToApply) const;
-    //
-    // Fixes up the DATA pages in this cache and all subcaches
-    // Takes a slide, so that some tools can call this to get unslid VM addresses, while
-    // dyld can pass a slide to apply.
-    //
-    mach_o::Error fixupAllDataPages(intptr_t slideToApply) const;
 
     dyld_cache_header header;
 
@@ -686,48 +532,13 @@
     void findDependentsRecursively(std::unordered_map<std::string, std::set<std::string>> &transitiveDependents, const std::unordered_map<std::string, std::set<std::string>> &reverseDependencyMap, std::set<std::string> & visited, const std::string &loadPath) const;
     void computeTransitiveDependents(std::unordered_map<std::string, std::set<std::string>> & transitiveDependents) const;
 #endif
-
-    //
-    // Returns a pointer to the old shared cache optimized Objective-C data structures
-    //
-    const objc_opt::objc_opt_t* oldObjcOpt() const;
-
-    //
-    // Returns a pointer to the new shared cache optimized Objective-C data structures
-    //
-    const ObjCOptimizationHeader* objcOpts() const;
 };
 
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-
-// Manages checking newly built caches against baseline builds
-struct BaselineCachesChecker
-{
-    BaselineCachesChecker(std::vector<const char*> archs, mach_o::Platform platform);
-
-    // Add a baseline cache map to the checker
-    mach_o::Error addBaselineMap(std::string_view path);
-    mach_o::Error addBaselineMaps(std::string_view dirPath);
-    mach_o::Error addNewMap(std::string_view mapString);
-    void          setFilesFromNewCaches(std::span<const char* const> files);
-
-    const std::set<std::string>& unionBaselineDylibs() { return _unionBaselineDylibs; }
-
-    std::set<std::string> dylibsMissingFromNewCaches() const;
-
-private:
-    // returns if we have a baseline arch for every arch we are building for
-    bool    allBaselineArchsPresent() const;
-
-    std::vector<std::string>                                    _archs;
-    mach_o::Platform                                            _platform;
-    std::set<std::string>                                       _unionBaselineDylibs;
-    std::set<std::string>                                       _dylibsInNewCaches;
-    std::unordered_map<std::string, std::vector<std::string>>   _baselineDylibs;
-    std::unordered_map<std::string, std::set<std::string>>      _newDylibs;
-};
-
-#endif // BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
+
+
+
+
+
 
 
 #endif /* DyldSharedCache_h */