Loading...
--- dyld/dyld-1335/cache_builder/SubCache.cpp
+++ dyld/dyld-1245.1/cache_builder/SubCache.cpp
@@ -28,7 +28,6 @@
#include "Chunk.h"
#include "CodeSigningTypes.h"
#include "DyldSharedCache.h"
-#include "Header.h"
#include "SubCache.h"
#include "JSONWriter.h"
@@ -38,10 +37,8 @@
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
+using dyld3::GradedArchs;
using dyld3::MachOFile;
-
-using mach_o::Header;
-using mach_o::Platform;
using error::Error;
@@ -416,7 +413,8 @@
return false;
}
-void SubCache::setSuffix(Platform platform, bool forceDevelopmentSubCacheSuffix, size_t subCacheIndex)
+void SubCache::setSuffix(dyld3::Platform platform, bool forceDevelopmentSubCacheSuffix,
+ size_t subCacheIndex)
{
assert(this->isSubCache() || this->isStubsCache());
assert(subCacheIndex > 0);
@@ -426,36 +424,36 @@
const char* readonlySuffix = forceDevelopmentSubCacheSuffix ? ".development.dyldreadonly" : ".dyldreadonly";
const char* subCacheSuffix = forceDevelopmentSubCacheSuffix ? ".development" : "";
- if ( (platform == Platform::macOS) || platform.isSimulator() ) {
- // macOS/sims never has a .development suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex);
- } else if ( platform == Platform::driverKit ) {
+ if ( platform == dyld3::Platform::macOS ) {
+ // macOS never has a .development suffix
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex);
+ } else if ( platform == dyld3::Platform::driverKit ) {
// driverKit never has a .development suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex);
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex);
} else if ( this->isStubsDevelopmentCache() ) {
// Dev stubs always have a suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex) + ".development";
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex) + ".development";
} else if ( this->isStubsCustomerCache() ) {
// Customer stubs never have a suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex);
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex);
} else if ( hasDataRegion(this->regions) ) {
// Data only subcaches have their own suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex) + dataSuffix;
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex) + dataSuffix;
} else if ( hasReadOnlyRegion(this->regions) ) {
// read-only only subcaches have their own suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex) + readonlySuffix;
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex) + readonlySuffix;
} else if ( hasLinkeditRegion(this->regions) ) {
// Linkedit only subcaches have their own suffix
- this->fileSuffix = "." + json::decimal(subCacheIndex) + linkeditSuffix;
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex) + linkeditSuffix;
} else {
- this->fileSuffix = "." + json::decimal(subCacheIndex) + subCacheSuffix;
+ this->fileSuffix = "." + dyld3::json::decimal(subCacheIndex) + subCacheSuffix;
}
}
static std::string getCodeSigningIdentifier(const BuilderOptions& options)
{
std::string cacheIdentifier = "com.apple.dyld.cache.";
- cacheIdentifier += options.arch.name();
+ cacheIdentifier += options.archs.name();
if ( options.dylibsRemovedFromDisk ) {
switch ( options.kind ) {
case CacheKind::development:
@@ -743,14 +741,6 @@
// Note: cdHash is defined as first 20 bytes of hash
memcpy(this->cdHash, fullCdHash, 20);
- if ( layout.agile ) {
- // hash of entire code directory (cdHash) uses same hash as each page
- uint8_t altfullCdHash[CS_HASH_SIZE_SHA256];
- CCDigest(kCCDigestSHA256, (const uint8_t*)cd256, layout.cd256Size, altfullCdHash);
- // Note: cdHash is defined as first 20 bytes of hash
- memcpy(this->agilecdHash, altfullCdHash, 20);
- }
-
// Set the UUID string in the subcache
uuid_unparse_upper(dyldCacheHeader->uuid, this->uuidString);
}
@@ -853,7 +843,7 @@
break;
case Chunk::Kind::dylibDataDirty:
// On arm64e, dataDirty goes in to auth
- if ( cacheDylib.inputHdr->isArch("arm64e") )
+ if ( cacheDylib.inputMF->isArch("arm64e") )
this->addAuthChunk(&segmentInfo);
else
this->addDataChunk(&segmentInfo);
@@ -875,6 +865,8 @@
break;
}
}
+
+ this->addLinkeditFromDylib(cacheDylib);
}
// Linkedit is stored in Chunks in its own array on the dylib. This adds it to the subCache.
@@ -969,8 +961,7 @@
return count;
}
-void SubCache::addCacheHeaderChunk(const BuilderOptions& options, const BuilderConfig& config,
- const std::span<CacheDylib> cacheDylibs)
+void SubCache::addCacheHeaderChunk(const BuilderConfig& config, const std::span<CacheDylib> cacheDylibs)
{
// calculate size of header info and where first dylib's mach_header should start
uint64_t numMappings = this->regions.size();
@@ -983,7 +974,7 @@
startOffset += sizeof(dyld_cache_tpro_mapping_info) * numTPRORegions(config, this, this->subCaches);
}
- if ( this->needsCacheHeaderImageList(options) ) {
+ if ( this->needsCacheHeaderImageList() ) {
startOffset += sizeof(dyld_cache_image_info) * cacheDylibs.size();
startOffset += sizeof(dyld_cache_image_text_info) * cacheDylibs.size();
for ( const CacheDylib& cacheDylib : cacheDylibs ) {
@@ -1065,7 +1056,7 @@
addCodeSignatureChunk(this->codeSignature.get());
}
-void SubCache::addObjCOptsHeaderChunk(const BuilderConfig& config, ObjCOptimizer& objcOptimizer)
+void SubCache::addObjCOptsHeaderChunk(ObjCOptimizer& objcOptimizer)
{
this->objcOptsHeader = std::make_unique<ObjCOptsHeaderChunk>();
this->objcOptsHeader->cacheVMSize = CacheVMSize(objcOptimizer.optsHeaderByteSize);
@@ -1073,7 +1064,7 @@
objcOptimizer.optsHeaderChunk = this->objcOptsHeader.get();
- this->addReadOnlyChunk(config, this->objcOptsHeader.get());
+ this->addLinkeditChunk(this->objcOptsHeader.get());
}
void SubCache::addObjCHeaderInfoReadOnlyChunk(const BuilderConfig& config, ObjCOptimizer& objcOptimizer)
@@ -1188,7 +1179,7 @@
addObjCReadWriteChunk(config, this->objcCanonicalProtocols.get());
}
-void SubCache::addObjCIMPCachesChunk(const BuilderConfig& config, ObjCIMPCachesOptimizer& objcIMPCachesOptimizer)
+void SubCache::addObjCIMPCachesChunk(ObjCIMPCachesOptimizer& objcIMPCachesOptimizer)
{
this->objcIMPCaches = std::make_unique<ObjCIMPCachesChunk>();
this->objcIMPCaches->cacheVMSize = CacheVMSize(objcIMPCachesOptimizer.impCachesTotalByteSize);
@@ -1196,7 +1187,7 @@
objcIMPCachesOptimizer.impCachesChunk = this->objcIMPCaches.get();
- this->addReadOnlyChunk(config, this->objcIMPCaches.get());
+ this->addLinkeditChunk(this->objcIMPCaches.get());
}
void SubCache::addObjCCategoriesChunk(const BuilderConfig& config,
@@ -1225,26 +1216,16 @@
void SubCache::addPatchTableChunk(PatchTableOptimizer& patchTableOptimizer)
{
- // We can't compute the size yet so just make an empty chunk
+ // We can't compute the size yet. We need to know how many fixups we have
+ // And yet we have an estimate, so we'll use it
this->patchTable = std::make_unique<PatchTableChunk>();
- this->patchTable->cacheVMSize = CacheVMSize(0ULL);
- this->patchTable->subCacheFileSize = CacheFileSize(0ULL);
+ this->patchTable->cacheVMSize = CacheVMSize(patchTableOptimizer.patchTableTotalByteSize);
+ this->patchTable->subCacheFileSize = CacheFileSize(patchTableOptimizer.patchTableTotalByteSize);
patchTableOptimizer.patchTableChunk = this->patchTable.get();
this->addLinkeditChunk(this->patchTable.get());
-}
-
-void SubCache::addFunctionVariantsChunk(FunctionVariantsOptimizer& optimizer)
-{
- this->functionVariants = std::make_unique<FunctionVariantsPatchTableChunk>();
- this->functionVariants->cacheVMSize = CacheVMSize(optimizer.fvInfoTotalByteSize);
- this->functionVariants->subCacheFileSize = CacheFileSize(optimizer.fvInfoTotalByteSize);
-
- optimizer.chunk = this->functionVariants.get();
-
- this->addLinkeditChunk(this->functionVariants.get());
}
void SubCache::addCacheDylibsLoaderChunk(PrebuiltLoaderBuilder& builder)
@@ -1286,21 +1267,7 @@
this->addLinkeditChunk(this->executablesTrie.get());
}
-void SubCache::addPrewarmingDataChunk(const BuilderConfig& config, PrewarmingOptimizer& opt)
-{
- if ( opt.prewarmingByteSize == 0 )
- return;
-
- this->prewarmingChunk = std::make_unique<PrewarmingChunk>(Chunk::Kind::prewarmingData);
- this->prewarmingChunk->cacheVMSize = CacheVMSize(opt.prewarmingByteSize);
- this->prewarmingChunk->subCacheFileSize = CacheFileSize(opt.prewarmingByteSize);
-
- opt.prewarmingChunk = this->prewarmingChunk.get();
-
- this->addReadOnlyChunk(config, this->prewarmingChunk.get());
-}
-
-void SubCache::addSwiftOptsHeaderChunk(const BuilderConfig& config, SwiftOptimizer& opt)
+void SubCache::addSwiftOptsHeaderChunk(SwiftProtocolConformanceOptimizer& opt)
{
this->swiftOptsHeader = std::make_unique<SwiftOptsHeaderChunk>();
this->swiftOptsHeader->cacheVMSize = CacheVMSize(opt.optsHeaderByteSize);
@@ -1308,10 +1275,10 @@
opt.optsHeaderChunk = this->swiftOptsHeader.get();
- this->addReadOnlyChunk(config, this->swiftOptsHeader.get());
-}
-
-void SubCache::addSwiftTypeHashTableChunk(const BuilderConfig& config, SwiftOptimizer& opt)
+ this->addLinkeditChunk(this->swiftOptsHeader.get());
+}
+
+void SubCache::addSwiftTypeHashTableChunk(SwiftProtocolConformanceOptimizer& opt)
{
this->swiftTypeHashTable = std::make_unique<SwiftProtocolConformancesHashTableChunk>();
this->swiftTypeHashTable->cacheVMSize = CacheVMSize(opt.typeConformancesHashTableSize);
@@ -1319,10 +1286,10 @@
opt.typeConformancesHashTable = this->swiftTypeHashTable.get();
- this->addReadOnlyChunk(config, this->swiftTypeHashTable.get());
-}
-
-void SubCache::addSwiftMetadataHashTableChunk(const BuilderConfig& config, SwiftOptimizer& opt)
+ this->addLinkeditChunk(this->swiftTypeHashTable.get());
+}
+
+void SubCache::addSwiftMetadataHashTableChunk(SwiftProtocolConformanceOptimizer& opt)
{
this->swiftMetadataHashTable = std::make_unique<SwiftProtocolConformancesHashTableChunk>();
this->swiftMetadataHashTable->cacheVMSize = CacheVMSize(opt.metadataConformancesHashTableSize);
@@ -1330,10 +1297,10 @@
opt.metadataConformancesHashTable = this->swiftMetadataHashTable.get();
- this->addReadOnlyChunk(config, this->swiftMetadataHashTable.get());
-}
-
-void SubCache::addSwiftForeignHashTableChunk(const BuilderConfig& config, SwiftOptimizer& opt)
+ this->addLinkeditChunk(this->swiftMetadataHashTable.get());
+}
+
+void SubCache::addSwiftForeignHashTableChunk(SwiftProtocolConformanceOptimizer& opt)
{
this->swiftForeignTypeHashTable = std::make_unique<SwiftProtocolConformancesHashTableChunk>();
this->swiftForeignTypeHashTable->cacheVMSize = CacheVMSize(opt.foreignTypeConformancesHashTableSize);
@@ -1341,10 +1308,10 @@
opt.foreignTypeConformancesHashTable = this->swiftForeignTypeHashTable.get();
- this->addReadOnlyChunk(config, this->swiftForeignTypeHashTable.get());
-}
-
-void SubCache::addSwiftPrespecializedMetadataPointerTableChunks(const BuilderConfig& config, SwiftOptimizer& opt)
+ this->addLinkeditChunk(this->swiftForeignTypeHashTable.get());
+}
+
+void SubCache::addSwiftPrespecializedMetadataPointerTableChunks(SwiftProtocolConformanceOptimizer& opt)
{
for ( PointerHashTableOptimizerInfo& tableInfo : opt.prespecializedMetadataHashTables ) {
PointerHashTableChunk* chunk = this->pointerHashTables.emplace_back(std::make_unique<PointerHashTableChunk>()).get();
@@ -1352,7 +1319,7 @@
chunk->subCacheFileSize = CacheFileSize(tableInfo.size);
tableInfo.chunk = chunk;
- this->addReadOnlyChunk(config, chunk);
+ this->addLinkeditChunk(chunk);
}
}
@@ -1549,16 +1516,15 @@
}
void SubCache::writeCacheHeader(const BuilderOptions& options, const BuilderConfig& config,
- const std::span<CacheDylib> cacheDylibs,
- uint32_t osVersion, uint32_t altPlatform, uint32_t altOsVersion)
+ const std::span<CacheDylib> cacheDylibs)
{
Chunk& cacheHeaderChunk = *this->cacheHeader.get();
dyld_cache_header* dyldCacheHeader = (dyld_cache_header*)cacheHeaderChunk.subCacheBuffer;
// "dyld_v1" + spaces + archName(), with enough spaces to pad to 15 bytes
std::string magic = "dyld_v1";
- magic.append(15 - magic.length() - strlen(options.arch.name()), ' ');
- magic.append(options.arch.name());
+ magic.append(15 - magic.length() - strlen(options.archs.name()), ' ');
+ magic.append(options.archs.name());
assert(magic.length() == 15);
// Num of mappings depends on cache layout.
@@ -1604,14 +1570,12 @@
dyldCacheHeader->progClosuresSize = 0; // no longer used
dyldCacheHeader->progClosuresTrieAddr = 0; // no longer used
dyldCacheHeader->progClosuresTrieSize = 0; // no longer used
- dyldCacheHeader->platform = options.platform.value();
+ dyldCacheHeader->platform = (uint8_t)options.platform;
dyldCacheHeader->formatVersion = 0; //dyld3::closure::kFormatVersion;
dyldCacheHeader->dylibsExpectedOnDisk = !options.dylibsRemovedFromDisk;
dyldCacheHeader->simulator = options.isSimulator();
dyldCacheHeader->locallyBuiltCache = options.isLocallyBuiltCache;
dyldCacheHeader->builtFromChainedFixups = false; // no longer used
- dyldCacheHeader->newFormatTLVs = true;
- dyldCacheHeader->padding = 0;
dyldCacheHeader->sharedRegionStart = this->subCacheVMAddress.rawValue();
dyldCacheHeader->sharedRegionSize = 0;
dyldCacheHeader->maxSlide = 0; // overwritten later in build if the cache supports ASLR
@@ -1629,9 +1593,9 @@
dyldCacheHeader->programsPBLSetPoolSize = 0; // set later only on the main cache file
dyldCacheHeader->programTrieAddr = 0; // set later only on the main cache file
dyldCacheHeader->programTrieSize = 0; // set later only on the main cache file
- dyldCacheHeader->osVersion = osVersion;
- dyldCacheHeader->altPlatform = altPlatform;
- dyldCacheHeader->altOsVersion = altOsVersion;
+ dyldCacheHeader->osVersion = 0; // set later only on the main cache file
+ dyldCacheHeader->altPlatform = 0; // set later only on the main cache file
+ dyldCacheHeader->altOsVersion = 0; // set later only on the main cache file
dyldCacheHeader->swiftOptsOffset = 0; // set later only on the main cache file
dyldCacheHeader->swiftOptsSize = 0; // set later only on the main cache file
dyldCacheHeader->subCacheArrayOffset = 0;
@@ -1650,8 +1614,6 @@
dyldCacheHeader->dynamicDataMaxSize = 0; // set later only on the main cache file
dyldCacheHeader->tproMappingsOffset = 0; // set later only on the main cache file
dyldCacheHeader->tproMappingsCount = 0; // set later only on the main cache file
- dyldCacheHeader->prewarmingDataOffset = 0; // set later only on the main cache file
- dyldCacheHeader->prewarmingDataSize = 0; // set later only on the main cache file
// Fill in old mappings
// And new mappings which also have slide info
@@ -1663,15 +1625,14 @@
void SubCache::addMainCacheHeaderInfo(const BuilderOptions& options, const BuilderConfig& config,
const std::span<CacheDylib> cacheDylibs,
CacheVMSize totalVMSize, uint64_t maxSlide,
+ uint32_t osVersion, uint32_t altPlatform, uint32_t altOsVersion,
CacheVMAddress dyldInCacheUnslidAddr,
CacheVMAddress dyldInCacheEntryUnslidAddr,
const DylibTrieOptimizer& dylibTrieOptimizer,
const ObjCOptimizer& objcOptimizer,
- const SwiftOptimizer& swiftOpt,
+ const SwiftProtocolConformanceOptimizer& swiftProtocolConformanceOpt,
const PatchTableOptimizer& patchTableOptimizer,
- const FunctionVariantsOptimizer& functionVariantOptimizer,
- const PrebuiltLoaderBuilder& prebuiltLoaderBuilder,
- const PrewarmingOptimizer& prewarmingOptimizer)
+ const PrebuiltLoaderBuilder& prebuiltLoaderBuilder)
{
const CacheVMAddress cacheBaseAddress = config.layout.cacheBaseAddress;
@@ -1684,13 +1645,13 @@
dyldCacheHeader->dylibsTrieAddr = dylibTrieOptimizer.dylibsTrieChunk->cacheVMAddress.rawValue();
dyldCacheHeader->dylibsTrieSize = dylibTrieOptimizer.dylibsTrieChunk->subCacheFileSize.rawValue();
- // Disable objc optimizations from EK shared cache
- bool emitObjcOpts = !options.platform.isExclaveKit();
- if ( !objcOptimizer.objcDylibs.empty() && emitObjcOpts ) {
+ if ( !objcOptimizer.objcDylibs.empty() ) {
dyldCacheHeader->objcOptsOffset = (objcOptimizer.optsHeaderChunk->cacheVMAddress - cacheBaseAddress).rawValue();
dyldCacheHeader->objcOptsSize = objcOptimizer.optsHeaderChunk->subCacheFileSize.rawValue();
-
- const auto& opt = swiftOpt;
+ }
+
+ if ( !objcOptimizer.objcDylibs.empty() ) {
+ const auto& opt = swiftProtocolConformanceOpt;
dyldCacheHeader->swiftOptsOffset = (opt.optsHeaderChunk->cacheVMAddress - cacheBaseAddress).rawValue();
dyldCacheHeader->swiftOptsSize = opt.optsHeaderChunk->subCacheFileSize.rawValue();
}
@@ -1707,15 +1668,16 @@
dyldCacheHeader->dyldInCacheMH = dyldInCacheUnslidAddr.rawValue();
dyldCacheHeader->dyldInCacheEntry = dyldInCacheEntryUnslidAddr.rawValue();
+ dyldCacheHeader->osVersion = osVersion;
+ dyldCacheHeader->altPlatform = altPlatform;
+ dyldCacheHeader->altOsVersion = altOsVersion;
+
// record max slide now that final size is established
dyldCacheHeader->maxSlide = maxSlide;
// TODO: Build the atlas
dyldCacheHeader->cacheAtlasOffset = 0; // set later only on the main cache file
dyldCacheHeader->cacheAtlasSize = 0; // set later only on the main cache file
-
- dyldCacheHeader->functionVariantInfoAddr = functionVariantOptimizer.chunk->cacheVMAddress.rawValue();
- dyldCacheHeader->functionVariantInfoSize = functionVariantOptimizer.fvInfoTotalByteSize;
// The main cache has offsets to all the caches
if ( !this->subCaches.empty() ) {
@@ -1755,11 +1717,6 @@
++index;
});
}
-
- if ( prewarmingOptimizer.prewarmingChunk != nullptr ) {
- dyldCacheHeader->prewarmingDataOffset = (prewarmingOptimizer.prewarmingChunk->cacheVMAddress - cacheBaseAddress).rawValue();
- dyldCacheHeader->prewarmingDataSize = prewarmingOptimizer.prewarmingChunk->subCacheFileSize.rawValue();
- }
}
void SubCache::addSymbolsCacheHeaderInfo(const UnmappedSymbolsOptimizer& optimizer)
@@ -1786,7 +1743,7 @@
const BuilderConfig& config,
const std::span<CacheDylib> cacheDylibs)
{
- if ( !this->needsCacheHeaderImageList(options) )
+ if ( !this->needsCacheHeaderImageList() )
return;
Chunk& cacheHeaderChunk = *this->cacheHeader.get();
@@ -1812,7 +1769,7 @@
// write text image array and image names pool at same time
for ( const CacheDylib& cacheDylib : cacheDylibs ) {
- cacheDylib.inputHdr->getUuid(textImages->uuid);
+ cacheDylib.inputMF->getUuid(textImages->uuid);
textImages->loadAddress = cacheDylib.cacheLoadAddress.rawValue();
textImages->textSegmentSize = (uint32_t)cacheDylib.segments.front().cacheVMSize.rawValue();
textImages->pathOffset = stringOffset;
@@ -1920,17 +1877,16 @@
return this->kind == Kind::stubsCustomer;
}
-bool SubCache::needsCacheHeaderImageList(const BuilderOptions& options) const
+bool SubCache::needsCacheHeaderImageList() const
{
// Symbols and stubs files don't need an image list
+ // We'd like to not add the image list to subcaches, only the main cache, but Rosetta needs
+ // the image list on subCaches.
switch ( this->kind ) {
case Kind::mainDevelopment:
case Kind::mainCustomer:
+ case Kind::subUniversal:
return true;
- case Kind::subUniversal:
- // We'd like to not add the image list to subcaches, only the main cache, but Rosetta needs
- // the image list on subCaches.
- return options.arch.sameCpu(mach_o::Architecture::x86_64);
case Kind::stubsDevelopment:
case Kind::stubsCustomer:
case Kind::symbols: