Loading...
--- dyld/dyld-1235.2/cache_builder/mrm_shared_cache_builder.cpp
+++ dyld/dyld-1330/cache_builder/mrm_shared_cache_builder.cpp
@@ -23,6 +23,7 @@
*/
#include "mrm_shared_cache_builder.h"
+#include "Architecture.h"
#include "Defines.h"
#include "BuilderFileSystem.h"
#include "NewSharedCacheBuilder.h"
@@ -52,19 +53,22 @@
static const uint64_t kMaxBuildVersion = 3; //The maximum version BuildOptions struct we can support
static const uint32_t MajorVersion = 1;
-static const uint32_t MinorVersion = 6;
+static const uint32_t MinorVersion = 8;
struct BuildInstance {
std::unique_ptr<cache_builder::BuilderOptions> options;
std::vector<cache_builder::FileAlias> aliases;
std::vector<cache_builder::FileAlias> intermediateAliases;
std::string mainCacheFilePath;
+ std::string atlasPath;
std::vector<const char*> errors;
std::vector<const char*> warnings;
std::vector<std::string> errorStrings; // Owns the data for the errors
std::vector<std::string> warningStrings; // Owns the data for the warnings
std::vector<CacheBuffer> cacheBuffers;
- std::vector<std::string> cachePaths; // Owns the data for the cache paths
+ std::vector<std::string> cachePaths; // Owns the data for the cache paths
+ std::vector<std::string> cacheAgileHashPaths; // Owns the data for the cache paths for agile signatures
+ std::vector<std::byte> atlas;
std::string loggingPrefix;
std::string jsonMap;
std::string mainCacheUUID;
@@ -74,6 +78,7 @@
std::string macOSMap; // For compatibility with update_dyld_shared_cache's .map file
std::string macOSMapPath; // Owns the string for the path
std::string cdHashType; // Owns the data for the cdHashType
+ std::string agileHashType; // Owns the data for the other cdHashType (if using agile signatures)
};
struct BuildFileResult {
@@ -114,6 +119,7 @@
std::string swiftGenericMetadataFileData;
void* objcOptimizationsFileData;
size_t objcOptimizationsFileLength;
+ std::string prewarmingMetadataFileData;
// An array of builders and their options as we may have more than one builder for a given device variant.
std::vector<BuildInstance> builders;
@@ -126,24 +132,14 @@
// We keep this in a vector to own the data.
std::vector<FileResult*> fileResults;
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
// The builder dylib passes back buffers
std::vector<FileResult_v1> fileResultStorage_v1;
-#else
- // The builder executable gets file descriptors
- std::vector<FileResult_v2> fileResultStorage_v2;
-#endif
// Buffers which were malloc()ed and need free()d
std::vector<FileBuffer> buffersToFree;
// Buffers which were vm_allocate()d, and need vm_deallocate()d
std::vector<FileBuffer> buffersToDeallocate;
-
-#if !SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
- // Buffers which were open()ed and mmap()ed
- std::vector<MappedBuffer> buffersToUnmap;
-#endif
// The results from all of the builders
// We keep this in a vector to own the data.
@@ -153,6 +149,10 @@
// The files to remove. These are in every copy of the caches we built
std::vector<const char*> filesToRemove;
+
+ // 1 JSON string per cache we built, with stats
+ std::vector<const char*> stats;
+ std::vector<std::string> statsStorage;
std::vector<const char*> errors;
std::vector<std::string> errorStorage;
@@ -178,7 +178,7 @@
va_list list;
va_start(list, format);
Diagnostics diag;
- diag.error(format, list);
+ diag.error(format, va_list_wrap(list));
va_end(list);
errorStorage.push_back(diag.errorMessage());
@@ -190,7 +190,7 @@
va_list list;
va_start(list, format);
Diagnostics diag;
- diag.error(format, list);
+ diag.error(format, va_list_wrap(list));
va_end(list);
warningsStorage.push_back(diag.errorMessage());
@@ -299,6 +299,42 @@
builder->swiftGenericMetadataFileData = std::string((char*)data, size);
success = true;
return;
+ case OptimizationFile: {
+ // TODO: Remove DylibOrderFile..SwiftGenericMetadataFile once image assembly
+ // passes this for all files from the OrderFiles project
+ CString leafName = CString(path).leafName();
+ if ( leafName == "dylib-order.txt" ) {
+ builder->dylibOrderFileData = std::string((char*)data, size);
+ success = true;
+ return;
+ }
+ if ( leafName == "dirty-data-segments-order.txt" ) {
+ builder->dirtyDataOrderFileData = std::string((char*)data, size);
+ success = true;
+ return;
+ }
+ if ( leafName == "shared-cache-objc-optimizations.json" ) {
+ builder->objcOptimizationsFileData = data;
+ builder->objcOptimizationsFileLength = size;
+ success = true;
+ return;
+ }
+ if ( leafName == "swift-generic-metadata.json" ) {
+ builder->swiftGenericMetadataFileData = std::string((char*)data, size);
+ success = true;
+ return;
+ }
+ if ( leafName == "prewarming-metadata.json" ) {
+ builder->prewarmingMetadataFileData = std::string((char*)data, size);
+ success = true;
+ return;
+ }
+ // Skip this file as image assembly will probably just give us all files in a given
+ // directory and that might include new/unrelated content
+ builder->warning("unknown optimization file path: %s", path);
+ success = true;
+ return;
+ }
default:
builder->error("unknown file flags value");
break;
@@ -355,7 +391,7 @@
}
static cache_builder::LocalSymbolsMode platformExcludeLocalSymbols(Platform platform) {
- if ( dyld3::MachOFile::isSimulatorPlatform((dyld3::Platform)platform) )
+ if ( mach_o::Platform((uint32_t)platform).isSimulator() )
return cache_builder::LocalSymbolsMode::keep;
if ( (platform == Platform::macOS) || (platform == Platform::iOSMac) )
return cache_builder::LocalSymbolsMode::keep;
@@ -425,12 +461,32 @@
return v3->printStats;
}
+static bool debugIMPCaches(const BuildOptions_v1* options) {
+ // Old builds just don't print this verbose output
+ if ( options->version < 3 ) {
+ return false;
+ }
+
+ const BuildOptions_v3* v3 = (const BuildOptions_v3*)options;
+ return v3->verboseIMPCaches;
+}
+
+static bool debugCacheLayout(const BuildOptions_v1* options) {
+ // Old builds just don't print this verbose output
+ if ( options->version < 3 ) {
+ return false;
+ }
+
+ const BuildOptions_v3* v3 = (const BuildOptions_v3*)options;
+ return v3->verboseCacheLayout;
+}
+
// This is a JSON file containing the list of classes for which
// we should try to build IMP caches.
-static dyld3::json::Node parseObjcOptimizationsFile(Diagnostics& diags, const void* data, size_t length) {
+static json::Node parseObjcOptimizationsFile(Diagnostics& diags, const void* data, size_t length) {
if ( data == nullptr )
- return dyld3::json::Node();
- return dyld3::json::readJSON(diags, data, length);
+ return json::Node();
+ return json::readJSON(diags, data, length, false /* useJSON5 */);
}
static cache_builder::CacheKind getCacheKind(const BuildOptions_v1* options)
@@ -438,11 +494,11 @@
// Work out what kind of cache we are building. macOS/driverKit/exclaveKit are always development
if ( (options->platform == macOS)
|| (options->platform == driverKit)
- || dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)options->platform) )
+ || mach_o::Platform(options->platform).isExclaveKit() )
return cache_builder::CacheKind::development;
// Sims are always development
- if ( dyld3::MachOFile::isSimulatorPlatform((dyld3::Platform)options->platform) )
+ if ( mach_o::Platform(options->platform).isSimulator() )
return cache_builder::CacheKind::development;
// iOS is always universal. If building for InternalMinDevelopment, we'll build universal
@@ -500,6 +556,14 @@
return true;
}
+static std::string cacheFileName(const char* arch, bool isSimulator) {
+ if ( isSimulator ) {
+ return std::string("dyld_sim_shared_cache_") + arch;
+ } else {
+ return std::string("dyld_shared_cache_") + arch;
+ }
+}
+
static bool createBuilders(struct MRMSharedCacheBuilder* builder)
{
if (builder->state != MRMSharedCacheBuilder::AcceptingFiles) {
@@ -534,7 +598,7 @@
const char *loggingSuffix = "";
if ( builder->options->platform == Platform::driverKit )
loggingSuffix = ".driverKit";
- if ( dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)builder->options->platform) )
+ if ( mach_o::Platform(builder->options->platform).isExclaveKit() )
loggingSuffix = ".exclaveKit";
std::string loggingPrefix = "";
@@ -543,20 +607,22 @@
loggingPrefix += std::string(".") + builder->options->archs[i];
loggingPrefix += loggingSuffix;
+ std::string mainCacheFileName;
std::string runtimePath;
- if ( dyld3::MachOFile::isSimulatorPlatform((dyld3::Platform)builder->options->platform) ) {
+ if ( mach_o::Platform(builder->options->platform).isSimulator() ) {
// Sim caches are written exactly where instructed, without adding any directory structure
- runtimePath = runtimePath + "dyld_sim_shared_cache_" + builder->options->archs[i];
+ mainCacheFileName = cacheFileName(builder->options->archs[i], true);
+ runtimePath = mainCacheFileName;
} else {
+ mainCacheFileName = cacheFileName(builder->options->archs[i], false);
if ( builder->options->platform == Platform::macOS )
- runtimePath = MACOSX_MRM_DYLD_SHARED_CACHE_DIR;
+ runtimePath = MACOSX_MRM_DYLD_SHARED_CACHE_DIR + mainCacheFileName;
else if ( builder->options->platform == Platform::driverKit )
- runtimePath = DRIVERKIT_DYLD_SHARED_CACHE_DIR;
- else if ( dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)builder->options->platform) )
- runtimePath = EXCLAVEKIT_DYLD_SHARED_CACHE_DIR;
+ runtimePath = DRIVERKIT_DYLD_SHARED_CACHE_DIR + mainCacheFileName;
+ else if ( mach_o::Platform(builder->options->platform).isExclaveKit() )
+ runtimePath = EXCLAVEKIT_DYLD_SHARED_CACHE_DIR + mainCacheFileName;
else
- runtimePath = IPHONE_DYLD_SHARED_CACHE_DIR;
- runtimePath = runtimePath + "dyld_shared_cache_" + builder->options->archs[i];
+ runtimePath = IPHONE_DYLD_SHARED_CACHE_DIR + mainCacheFileName;
}
bool dylibsRemovedFromDisk = filesRemovedFromDisk(builder->options);
@@ -574,12 +640,17 @@
forceDevelopmentSubCacheSuffix = true;
auto options = std::make_unique<cache_builder::BuilderOptions>(builder->options->archs[i],
- (dyld3::Platform)builder->options->platform,
+ builder->options->platform,
dylibsRemovedFromDisk, isLocallyBuiltCache,
- cacheKind, forceDevelopmentSubCacheSuffix);
-
+ cacheKind, forceDevelopmentSubCacheSuffix,
+ builder->options->updateName,
+ builder->options->deviceName);
+
+ options->mainCacheFileName = mainCacheFileName;
options->logPrefix = loggingPrefix;
options->debug = builder->options->verboseDiagnostics;
+ options->debugIMPCaches = debugIMPCaches(builder->options);
+ options->debugCacheLayout = debugCacheLayout(builder->options);
options->timePasses = options->debug ? true : timePasses(builder->options);
options->stats = options->debug ? true : printStats(builder->options);
options->dylibOrdering = parseOrderFile(builder->dylibOrderFileData);
@@ -588,12 +659,14 @@
builder->objcOptimizationsFileLength);
options->localSymbolsMode = excludeLocalSymbols(builder->options);
options->swiftGenericMetadataFile = builder->swiftGenericMetadataFileData;
+ options->prewarmingOptimizations = builder->prewarmingMetadataFileData;
BuildInstance buildInstance;
buildInstance.options = std::move(options);
buildInstance.aliases = aliases;
buildInstance.intermediateAliases = intermediateAliases;
buildInstance.mainCacheFilePath = runtimePath;
+ buildInstance.atlasPath = runtimePath + ".atlas";
builder->builders.push_back(std::move(buildInstance));
}
@@ -610,6 +683,10 @@
std::unordered_set<std::string> evictedDylibsSet;
__block std::unique_ptr<SharedCacheBuilder> cacheBuilder;
Error error;
+
+ // Note down when we start so we can emit it in stats().
+ // This is outside the loop to include potential time in eviction and rebuilds
+ uint64_t startTimeNanos = clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
while ( true ) {
cacheBuilder = std::make_unique<SharedCacheBuilder>(*buildInstance.options.get(), builder->fileSystem);
@@ -628,6 +705,7 @@
case FileFlags::DirtyDataOrderFile:
case FileFlags::ObjCOptimizationsFile:
case FileFlags::SwiftGenericMetadataFile:
+ case FileFlags::OptimizationFile:
builder->error("Order files should not be in the file system");
return;
}
@@ -641,7 +719,7 @@
error = cacheBuilder->build();
// Get result buffers, even if there's an error. That way we'll free them
- cacheBuilder->getResults(buildInstance.cacheBuffers);
+ cacheBuilder->getResults(buildInstance.cacheBuffers, buildInstance.atlas);
if ( !error.hasError() )
break;
@@ -685,18 +763,8 @@
// Track all buffers to be freed/unmapped (see allocateSubCacheBuffers() for allocation)
for ( const CacheBuffer& buffer : buildInstance.cacheBuffers ) {
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
// In MRM, we vm_allocated
builder->buffersToDeallocate.emplace_back((FileBuffer){ buffer.bufferData, buffer.bufferSize });
-#else
- // In the local builder, we mmap()ed
- builder->buffersToUnmap.emplace_back((MappedBuffer) {
- buffer.bufferData,
- buffer.bufferSize,
- buffer.fd,
- buffer.tempPath
- });
-#endif
}
if ( error.hasError() ) {
@@ -747,8 +815,8 @@
return true;
});
- if ( (buildInstance.options->platform == dyld3::Platform::macOS)
- || dyld3::MachOFile::isSimulatorPlatform(buildInstance.options->platform) ) {
+ if ( (buildInstance.options->platform == Platform::macOS)
+ || buildInstance.options->platform.isSimulator() ) {
// For compatibility with update_dyld_shared_cache/update_dyld_sim_shared_cache, put a .map file next to the shared cache
buildInstance.macOSMap = cacheBuilder->getMapFileBuffer();
buildInstance.macOSMapPath = buildInstance.mainCacheFilePath + ".map";
@@ -790,6 +858,7 @@
break;
case DyldSharedCache::Agile:
buildInstance.cdHashType = "sha1";
+ buildInstance.agileHashType = "sha256";
break;
}
@@ -800,7 +869,16 @@
cacheBuilder->forEachCacheSymlink(^(const std::string_view &path) {
builder->dylibsInCaches[std::string(path)].insert(&buildInstance);
});
- }
+
+ // Track cache stats
+ builder->statsStorage.push_back(cacheBuilder->stats(startTimeNanos));
+ }
+ }
+
+ // Make the stats vector from the storage
+ if ( !builder->statsStorage.empty() ) {
+ for ( std::string& str : builder->statsStorage )
+ builder->stats.push_back(str.data());
}
}
@@ -853,81 +931,78 @@
if (!buildInstance.errors.empty())
continue;
- for ( const CacheBuffer& buffer : buildInstance.cacheBuffers )
+ for ( const CacheBuffer& buffer : buildInstance.cacheBuffers ) {
buildInstance.cachePaths.push_back(buildInstance.mainCacheFilePath + buffer.cacheFileSuffix);
+ if ( !buildInstance.agileHashType.empty() ) {
+ buildInstance.cacheAgileHashPaths.push_back(buildInstance.cachePaths.back() + ".cdhash");
+ }
+ }
uint32_t cacheIndex = 0;
for ( const CacheBuffer& cacheBuffer : buildInstance.cacheBuffers ) {
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
- FileResult_v1 cacheFileResult;
- cacheFileResult.version = 1;
- cacheFileResult.path = buildInstance.cachePaths[cacheIndex].c_str();
- cacheFileResult.behavior = AddFile;
- cacheFileResult.data = cacheBuffer.bufferData;
- cacheFileResult.size = cacheBuffer.bufferSize;
- cacheFileResult.hashArch = buildInstance.options->archs.name();
- cacheFileResult.hashType = buildInstance.cdHashType.c_str();
- cacheFileResult.hash = cacheBuffer.cdHash.c_str();
-
- builder->fileResultStorage_v1.emplace_back(cacheFileResult);
-#else
- FileResult_v2 cacheFileResult;
- cacheFileResult.version = 2;
- cacheFileResult.path = buildInstance.cachePaths[cacheIndex].c_str();
- cacheFileResult.behavior = AddFile;
- cacheFileResult.data = cacheBuffer.bufferData;
- cacheFileResult.size = cacheBuffer.bufferSize;
- cacheFileResult.hashArch = buildInstance.options->archs.name();
- cacheFileResult.hashType = buildInstance.cdHashType.c_str();
- cacheFileResult.hash = cacheBuffer.cdHash.c_str();
- cacheFileResult.fd = cacheBuffer.fd;
- cacheFileResult.tempFilePath = cacheBuffer.tempPath.c_str();
-
- builder->fileResultStorage_v2.emplace_back(cacheFileResult);
-#endif
+ {
+ FileResult_v1 cacheFileResult;
+ cacheFileResult.version = 1;
+ cacheFileResult.path = buildInstance.cachePaths[cacheIndex].c_str();
+ cacheFileResult.behavior = AddFile;
+ cacheFileResult.data = cacheBuffer.bufferData;
+ cacheFileResult.size = cacheBuffer.bufferSize;
+ cacheFileResult.hashArch = buildInstance.options->arch.name();
+ cacheFileResult.hashType = buildInstance.cdHashType.c_str();
+ cacheFileResult.hash = cacheBuffer.cdHash.c_str();
+
+ builder->fileResultStorage_v1.emplace_back(cacheFileResult);
+ }
+
+ // Generate a dummy file for the agile cdHash if we have it, this gets it in to the trust cache
+ if ( !buildInstance.agileHashType.empty() ) {
+ FileResult_v1 cacheFileResult;
+ cacheFileResult.version = 1;
+ cacheFileResult.path = buildInstance.cacheAgileHashPaths[cacheIndex].c_str();
+ cacheFileResult.behavior = AddFile;
+ cacheFileResult.data = (const uint8_t*)"cdhash";
+ cacheFileResult.size = strlen("cdhash");
+ cacheFileResult.hashArch = buildInstance.options->arch.name();
+ cacheFileResult.hashType = buildInstance.agileHashType.c_str();
+ cacheFileResult.hash = cacheBuffer.agilecdHash.c_str();
+
+ builder->fileResultStorage_v1.emplace_back(cacheFileResult);
+ }
++cacheIndex;
}
+
+ FileResult_v1 arlasFileResult;
+ arlasFileResult.version = 1;
+ arlasFileResult.path = buildInstance.atlasPath.c_str();
+ arlasFileResult.behavior = AddFile;
+ arlasFileResult.data = (const uint8_t*)&buildInstance.atlas[0];
+ arlasFileResult.size = buildInstance.atlas.size();
+ arlasFileResult.hashArch = buildInstance.options->arch.name();
+ arlasFileResult.hashType = buildInstance.cdHashType.c_str();
+ arlasFileResult.hash = buildInstance.cacheBuffers.front().cdHash.c_str();;
+
+ builder->fileResultStorage_v1.emplace_back(arlasFileResult);
// Add a file result for the .map file
// FIXME: We only emit a single map file right now.
if ( !buildInstance.macOSMap.empty() ) {
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
FileResult_v1 cacheFileResult;
cacheFileResult.version = 1;
cacheFileResult.path = buildInstance.macOSMapPath.c_str();
cacheFileResult.behavior = AddFile;
cacheFileResult.data = (const uint8_t*)buildInstance.macOSMap.data();
cacheFileResult.size = buildInstance.macOSMap.size();
- cacheFileResult.hashArch = buildInstance.options->archs.name();
+ cacheFileResult.hashArch = buildInstance.options->arch.name();
cacheFileResult.hashType = buildInstance.cdHashType.c_str();
cacheFileResult.hash = buildInstance.cacheBuffers.front().cdHash.c_str();;
builder->fileResultStorage_v1.emplace_back(cacheFileResult);
-#else
- FileResult_v2 cacheFileResult;
- cacheFileResult.version = 2;
- cacheFileResult.path = buildInstance.macOSMapPath.c_str();
- cacheFileResult.behavior = AddFile;
- cacheFileResult.data = (const uint8_t*)buildInstance.macOSMap.data();
- cacheFileResult.size = buildInstance.macOSMap.size();
- cacheFileResult.hashArch = buildInstance.options->archs.name();
- cacheFileResult.hashType = buildInstance.cdHashType.c_str();
- cacheFileResult.hash = buildInstance.cacheBuffers.front().cdHash.c_str();
- cacheFileResult.fd = 0;
- cacheFileResult.tempFilePath = nullptr;
-
- builder->fileResultStorage_v2.emplace_back(cacheFileResult);
-#endif
}
}
}
static void calculateDylibsToDelete(struct MRMSharedCacheBuilder* builder)
{
- // Keep ExclaveKit binaries on disk, remove that exception later (rdar://112851136)
- if ( dyld3::MachOFile::isExclaveKitPlatform((dyld3::Platform)builder->options->platform) )
- return;
-
// Add entries to tell us to remove all of the dylibs from disk which are in every cache.
const size_t numCaches = builder->builders.size();
for (const auto& dylibAndCount : builder->dylibsInCaches) {
@@ -978,10 +1053,11 @@
// so removing it from disk won't hurt
Diagnostics loaderDiag;
const bool isOSBinary = false;
- const dyld3::GradedArchs& archs = buildInstance.options->archs;
- dyld3::Platform platform = buildInstance.options->platform;
+ const mach_o::GradedArchitectures& archs = buildInstance.options->gradedArchs;
+ mach_o::Platform platform = buildInstance.options->platform;
+ uint64_t sliceOffset = 0;
uint64_t sliceSize = 0;
- if ( const auto* mf = dyld3::MachOFile::compatibleSlice(loaderDiag, sliceSize, buffer, bufferSize,
+ if ( const auto* mf = dyld3::MachOFile::compatibleSlice(loaderDiag, sliceOffset, sliceSize, buffer, bufferSize,
pathToRemove, platform,
isOSBinary, archs) ) {
// This arch was compatible, so the dylib was rejected from this cache for some other reason, eg,
@@ -993,11 +1069,11 @@
}
// Check iOSMac, just in case we couldn't load the slice on macOS
- if ( (platform == dyld3::Platform::macOS) && loaderDiag.hasError() ) {
+ if ( (platform == mach_o::Platform::macOS) && loaderDiag.hasError() ) {
loaderDiag.clearError();
- if ( const auto* mf = dyld3::MachOFile::compatibleSlice(loaderDiag, sliceSize, buffer, bufferSize,
- pathToRemove, dyld3::Platform::iOSMac,
+ if ( const auto* mf = dyld3::MachOFile::compatibleSlice(loaderDiag, sliceOffset, sliceSize, buffer, bufferSize,
+ pathToRemove, mach_o::Platform::macCatalyst,
isOSBinary, archs) ) {
// This arch was compatible, so the dylib was rejected from this cache for some other reason, eg,
// cache overflow. We need to keep it on-disk
@@ -1033,14 +1109,28 @@
if ( pvs.platform.empty() )
return;
- // HACK: Pretend zippered are macOS, so that the database doesn't have to care about zippering
- mach_o::Platform platform;
- if ( (pvs.platform == mach_o::Platform::zippered) || (pvs.platform == mach_o::Platform::macCatalyst) )
- platform = mach_o::Platform::macOS;
- else
- platform = pvs.platform;
-
- archPlatforms[mh->archName()].push_back(platform);
+ archPlatforms[mh->archName()].push_back(pvs.platform);
+ });
+ if ( parseErr ) {
+ builder->error("Cannot build symbols cache because: %s", parseErr.message());
+ }
+ }
+ });
+ } else if ( mach_o::Platform(builder->options->platform).isExclaveKit() ) {
+ // Note Image Assembly might not know which archs/platforms to build as a single DylibCache could
+ // have different archs for different platforms, like userland vs driverKit vs exclaves.
+ builder->fileSystem.forEachFileInfo(^(const char* path, const void* buffer, size_t bufferSize,
+ FileFlags fileFlags, uint64_t inode, uint64_t modTime,
+ const char* projectName) {
+ if ( !strcmp(path, "/System/ExclaveKit/usr/lib/libSystem.dylib") ) {
+ const std::span<uint8_t> bufferSpan = { (uint8_t*)buffer, bufferSize };
+ mach_o::Error parseErr = mach_o::forEachHeader(bufferSpan, path,
+ ^(const mach_o::Header* mh, size_t sliceHeader, bool &stop) {
+ mach_o::PlatformAndVersions pvs = mh->platformAndVersions();
+ if ( pvs.platform.empty() )
+ return;
+
+ archPlatforms[mh->archName()].push_back(pvs.platform);
});
if ( parseErr ) {
builder->error("Cannot build symbols cache because: %s", parseErr.message());
@@ -1056,7 +1146,8 @@
if ( !strcmp(path, "/usr/lib/libSystem.dylib")
|| !strcmp(path, "/usr/lib/libSystem.B.dylib")
|| !strcmp(path, "/System/DriverKit/usr/lib/libSystem.dylib")
- || !strcmp(path, "/System/DriverKit/usr/lib/libSystem.B.dylib") ) {
+ || !strcmp(path, "/System/DriverKit/usr/lib/libSystem.B.dylib")
+ || !strcmp(path, "/System/ExclaveKit/usr/lib/libSystem.dylib") ) {
const std::span<uint8_t> bufferSpan = { (uint8_t*)buffer, bufferSize };
mach_o::Error parseErr = mach_o::forEachHeader(bufferSpan, path,
^(const mach_o::Header* mh, size_t sliceHeader, bool &stop) {
@@ -1104,6 +1195,7 @@
case FileFlags::DirtyDataOrderFile:
case FileFlags::ObjCOptimizationsFile:
case FileFlags::SwiftGenericMetadataFile:
+ case FileFlags::OptimizationFile:
builder->error("Order files should not be in the file system");
return;
}
@@ -1153,10 +1245,11 @@
const char* resultPath = MACOSX_MRM_DYLD_SHARED_CACHE_DIR "dyld_symbols.db";;
if ( builder->options->platform == driverKit )
resultPath = DRIVERKIT_DYLD_SHARED_CACHE_DIR "dyld_symbols.db";
-
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
+ else if ( mach_o::Platform(builder->options->platform).isExclaveKit() )
+ resultPath = EXCLAVEKIT_DYLD_SHARED_CACHE_DIR "dyld_symbols.db";
+
FileResult_v1 cacheFileResult;
- cacheFileResult.version = 2;
+ cacheFileResult.version = 1;
cacheFileResult.path = resultPath;
cacheFileResult.behavior = AddFile;
cacheFileResult.data = buffer;
@@ -1167,22 +1260,6 @@
builder->fileResultStorage_v1.emplace_back(cacheFileResult);
builder->fileResults.push_back((FileResult*)&builder->fileResultStorage_v1.back());
-#else
- FileResult_v2 cacheFileResult;
- cacheFileResult.version = 2;
- cacheFileResult.path = resultPath;
- cacheFileResult.behavior = AddFile;
- cacheFileResult.data = buffer;
- cacheFileResult.size = bufferSize;
- cacheFileResult.hashArch = "x86_64";
- cacheFileResult.hashType = "sha256";
- cacheFileResult.hash = "";
- cacheFileResult.fd = 0;
- cacheFileResult.tempFilePath = nullptr;
-
- builder->fileResultStorage_v2.emplace_back(cacheFileResult);
- builder->fileResults.push_back((FileResult*)&builder->fileResultStorage_v2.back());
-#endif
builder->buffersToFree.emplace_back((FileBuffer) { (void*)buffer, bufferSize });
@@ -1208,13 +1285,8 @@
calculateDylibsToDelete(builder);
// Copy from the storage to the vector we can return to the API.
-#if SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
for (auto &fileResult : builder->fileResultStorage_v1)
builder->fileResults.push_back((FileResult*)&fileResult);
-#else
- for (auto &fileResult : builder->fileResultStorage_v2)
- builder->fileResults.push_back((FileResult*)&fileResult);
-#endif
for (auto &cacheResult : builder->cacheResultStorage)
builder->cacheResults.push_back(&cacheResult);
@@ -1258,6 +1330,15 @@
return builder->filesToRemove.data();
}
+const char* const* getCacheStats(const struct MRMSharedCacheBuilder* builder, uint64_t* resultCount) {
+ if ( builder->stats.empty() ) {
+ *resultCount = 0;
+ return nullptr;
+ }
+ *resultCount = builder->stats.size();
+ return builder->stats.data();
+}
+
void destroySharedCacheBuilder(struct MRMSharedCacheBuilder* builder) {
for ( FileBuffer& buffer : builder->buffersToFree ) {
@@ -1268,16 +1349,15 @@
vm_deallocate(mach_task_self(), (vm_address_t)buffer.buffer, buffer.size);
}
-#if !SUPPORT_CACHE_BUILDER_MEMORY_BUFFERS
- for ( MappedBuffer& buffer : builder->buffersToUnmap ) {
- ::munmap(buffer.buffer, buffer.size);
- ::close(buffer.fd);
-
- // The builder tool will link this temp path to the new location, if needed. We then
- // remove the old path with this unlink().
- ::unlink(buffer.tempPath.c_str());
- }
-#endif
-
delete builder;
}
+
+
+// rdar://146678211 (slc_builder.dylib is using libcpp_verbose_abort() which does not exist on builder)
+// This can be removed when IA builders update to a host whose libc++.dylib has the symbol __ZNSt3__122__libcpp_verbose_abortEPKcz
+__attribute__((__noreturn__, visibility("hidden")))
+void _libcpp_verbose_abort(const char* msg, ...) __asm("__ZNSt3__122__libcpp_verbose_abortEPKcz");
+void _libcpp_verbose_abort(const char* msg, ...)
+{
+ abort();
+}