+ // make sure after all optimizations, that whole cache file fits into shared region address range
+ {
+ dyldCacheHeader<E>* cacheHeader = (dyldCacheHeader<E>*)inMemoryCache;
+ dyldCacheFileMapping<E>* mappings = (dyldCacheFileMapping<E>*)&inMemoryCache[cacheHeader->mappingOffset()];
+ for (int i=0; i < cacheHeader->mappingCount(); ++i) {
+ uint64_t endAddr = mappings[i].address() + mappings[i].size();
+ if ( endAddr > (sharedRegionStartAddress() + sharedRegionSize()) ) {
+ throwf("update_dyld_shared_cache[%u] for arch=%s, shared cache will not fit in address space: 0x%llX\n",
+ getpid(), fArchGraph->archName(), endAddr);
+ }
+ }
+ }
+
+ // append local symbol info in an unmapped region
+ if ( dontMapLocalSymbols ) {
+ uint32_t spaceAtEnd = allocatedCacheSize - cacheFileSize;
+ uint32_t localSymbolsOffset = pageAlign(cacheFileSize);
+ dyldCacheLocalSymbolsInfo<E>* infoHeader = (dyldCacheLocalSymbolsInfo<E>*)(&inMemoryCache[localSymbolsOffset]);
+ const uint32_t entriesOffset = sizeof(dyldCacheLocalSymbolsInfo<E>);
+ const uint32_t entriesCount = fLocalSymbolInfos.size();
+ const uint32_t nlistOffset = entriesOffset + entriesCount * sizeof(dyldCacheLocalSymbolEntry<E>);
+ const uint32_t nlistCount = fUnmappedLocalSymbols.size();
+ const uint32_t stringsOffset = nlistOffset + nlistCount * sizeof(macho_nlist<P>);
+ const uint32_t stringsSize = fUnmappedLocalsStringPool.size();
+ if ( stringsOffset+stringsSize > spaceAtEnd )
+ throwf("update_dyld_shared_cache[%u] for arch=%s, out of space for local symbols. Have 0x%X, Need 0x%X\n",
+ getpid(), fArchGraph->archName(), spaceAtEnd, stringsOffset+stringsSize);
+ // fill in local symbols info
+ infoHeader->set_nlistOffset(nlistOffset);
+ infoHeader->set_nlistCount(nlistCount);
+ infoHeader->set_stringsOffset(stringsOffset);
+ infoHeader->set_stringsSize(stringsSize);
+ infoHeader->set_entriesOffset(entriesOffset);
+ infoHeader->set_entriesCount(entriesCount);
+ // copy info for each dylib
+ dyldCacheLocalSymbolEntry<E>* entries = (dyldCacheLocalSymbolEntry<E>*)(&inMemoryCache[localSymbolsOffset+entriesOffset]);
+ for (int i=0; i < entriesCount; ++i) {
+ entries[i].set_dylibOffset(fLocalSymbolInfos[i].dylibOffset);
+ entries[i].set_nlistStartIndex(fLocalSymbolInfos[i].nlistStartIndex);
+ entries[i].set_nlistCount(fLocalSymbolInfos[i].nlistCount);
+ }
+ // copy nlists
+ memcpy(&inMemoryCache[localSymbolsOffset+nlistOffset], &fUnmappedLocalSymbols[0], nlistCount*sizeof(macho_nlist<P>));
+ // copy string pool
+ memcpy(&inMemoryCache[localSymbolsOffset+stringsOffset], fUnmappedLocalsStringPool.getBuffer(), stringsSize);
+
+ // update state
+ fUnmappedLocalSymbolsSize = pageAlign(stringsOffset + stringsSize);
+ cacheFileSize = localSymbolsOffset + fUnmappedLocalSymbolsSize;
+
+ // update header to show location of slidePointers
+ dyldCacheHeader<E>* cacheHeader = (dyldCacheHeader<E>*)inMemoryCache;
+ cacheHeader->set_localSymbolsOffset(localSymbolsOffset);
+ cacheHeader->set_localSymbolsSize(stringsOffset+stringsSize);
+ cacheHeader->set_codeSignatureOffset(cacheFileSize);
+ }
+
+ // compute UUID of whole cache
+ uint8_t digest[16];
+ CC_MD5(inMemoryCache, cacheFileSize, digest);
+ // <rdar://problem/6723729> uuids should conform to RFC 4122 UUID version 4 & UUID version 5 formats
+ digest[6] = ( digest[6] & 0x0F ) | ( 3 << 4 );
+ digest[8] = ( digest[8] & 0x3F ) | 0x80;
+ ((dyldCacheHeader<E>*)inMemoryCache)->set_uuid(digest);