]> git.saurik.com Git - apple/dyld.git/commitdiff
dyld-551.3.tar.gz macos-10134 macos-10135 v551.3
authorApple <opensource@apple.com>
Wed, 15 Aug 2018 19:10:21 +0000 (19:10 +0000)
committerApple <opensource@apple.com>
Wed, 15 Aug 2018 19:10:21 +0000 (19:10 +0000)
26 files changed:
dyld3/AllImages.cpp
dyld3/AllImages.h
dyld3/LaunchCacheReader.cpp
dyld3/Loading.cpp
dyld3/MachOParser.cpp
dyld3/SharedCacheRuntime.cpp
dyld3/libclosured-stub.cpp
dyld3/libdyldEntryVector.cpp
dyld3/shared-cache/BuilderUtils.mm
dyld3/shared-cache/CacheBuilder.cpp
dyld3/shared-cache/CacheBuilder.h
dyld3/shared-cache/DyldSharedCache.cpp
dyld3/shared-cache/DyldSharedCache.h
dyld3/shared-cache/ImageProxy.cpp
dyld3/shared-cache/Manifest.mm
dyld3/shared-cache/OptimizerLinkedit.cpp
dyld3/shared-cache/update_dyld_shared_cache.cpp
src/ImageLoaderMachO.cpp
src/ImageLoaderMachOCompressed.cpp
src/dyld.cpp
src/dyldAPIs.cpp
src/dyldNew.cpp
src/dyld_process_info_notify.cpp
testing/test-cases/dyld_process_info_unload.dtest/main.c
testing/test-cases/flat-namespace-absolute-symbol.dtest/foo.s [new file with mode: 0644]
testing/test-cases/flat-namespace-absolute-symbol.dtest/main.c [new file with mode: 0644]

index 6d64e363d6f111389cbcfab21ad91294757dffcf..a410456994d70997448a6c071688f9f50adb1c5a 100644 (file)
@@ -455,6 +455,12 @@ void AllImages::init(const BinaryClosure* closure, const void* dyldCacheLoadAddr
     _dyldCacheAddress   = dyldCacheLoadAddress;
     _dyldCachePath      = dyldCachePath;
 
+    if ( _dyldCacheAddress ) {
+        const DyldSharedCache* cache = (DyldSharedCache*)_dyldCacheAddress;
+        const dyld_cache_mapping_info* const fileMappings = (dyld_cache_mapping_info*)((uint64_t)_dyldCacheAddress + cache->header.mappingOffset);
+        _dyldCacheSlide     = (uint64_t)dyldCacheLoadAddress - fileMappings[0].address;
+    }
+
     // Make temporary old image array, so libSystem initializers can be debugged
     uint32_t count = (uint32_t)initialImages.count();
     dyld_image_info oldDyldInfo[count];
@@ -585,9 +591,13 @@ void AllImages::addImages(const launch_cache::DynArray<loader::ImageInfo>& newIm
     for (uint32_t j=0; j < existingNotifierCount; ++j) {
         NotifyFunc func = existingNotifierArray[j];
         for (uint32_t i=0; i < count; ++i) {
-            MachOParser parser(newImages[i].loadAddress);
             log_notifications("dyld: add notifier %p called with mh=%p\n", func, newImages[i].loadAddress);
-            func(newImages[i].loadAddress, parser.getSlide());
+            if (newImages[i].justUsedFromDyldCache) {
+                func(newImages[i].loadAddress, _dyldCacheSlide);
+            } else {
+                MachOParser parser(newImages[i].loadAddress);
+                func(newImages[i].loadAddress, parser.getSlide());
+            }
         }
     }
 
index 1f644bcf7277b95f9d520697250b3725c424b6db..47d06552dbec9fb130f09ba07ff6a764ac31a495 100644 (file)
@@ -146,6 +146,7 @@ private:
     const BinaryClosure*                    _mainClosure         = nullptr;
     const void*                             _dyldCacheAddress    = nullptr;
     const char*                             _dyldCachePath       = nullptr;
+    uint64_t                                _dyldCacheSlide      = 0;
     StartImageArray*                        _initialImages       = nullptr;
     const char*                             _mainExeOverridePath = nullptr;
     _dyld_objc_notify_mapped                _objcNotifyMapped    = nullptr;
index 06c73e15c10878dc88aa274ef962cadc606b0e8d..5b99e750a3bb3e46b81cf18a597a6648019a7044 100644 (file)
@@ -196,7 +196,15 @@ uintptr_t TargetSymbolValue::resolveTarget(Diagnostics& diag, const ImageGroup&
                             });
                             return (*foundMH != nullptr);
                         }) ) {
-                        result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                        switch (foundInfo.kind) {
+                            case MachOParser::FoundSymbol::Kind::headerOffset:
+                            case MachOParser::FoundSymbol::Kind::resolverOffset:
+                                result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                                break;
+                            case MachOParser::FoundSymbol::Kind::absolute:
+                                result = (uintptr_t)foundInfo.value;
+                                break;
+                        }
                         images.setAsNeverUnload(idx);
                         found  = true;
                         stop   = true;
@@ -216,7 +224,15 @@ uintptr_t TargetSymbolValue::resolveTarget(Diagnostics& diag, const ImageGroup&
                         dyld3::MachOParser parser(mh);
                         dyld3::MachOParser::FoundSymbol foundInfo;
                         if ( parser.findExportedSymbol(findSymbolDiag, symbolName, nullptr, foundInfo, nullptr) ) {
-                            result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                            switch (foundInfo.kind) {
+                                case MachOParser::FoundSymbol::Kind::headerOffset:
+                                case MachOParser::FoundSymbol::Kind::resolverOffset:
+                                    result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                                    break;
+                                case MachOParser::FoundSymbol::Kind::absolute:
+                                    result = (uintptr_t)foundInfo.value;
+                                    break;
+                            }
                             found  = true;
                             stop   = true;
                         }
@@ -232,7 +248,15 @@ uintptr_t TargetSymbolValue::resolveTarget(Diagnostics& diag, const ImageGroup&
                         dyld3::MachOParser parser(mh);
                         dyld3::MachOParser::FoundSymbol foundInfo;
                         if ( parser.findExportedSymbol(findSymbolDiag, symbolName, nullptr, foundInfo, nullptr) ) {
-                            result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                            switch (foundInfo.kind) {
+                                case MachOParser::FoundSymbol::Kind::headerOffset:
+                                case MachOParser::FoundSymbol::Kind::resolverOffset:
+                                    result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                                    break;
+                                case MachOParser::FoundSymbol::Kind::absolute:
+                                    result = (uintptr_t)foundInfo.value;
+                                    break;
+                            }
                             found  = true;
                             images.setAsNeverUnload(idx);
                             stop   = true;
@@ -249,7 +273,15 @@ uintptr_t TargetSymbolValue::resolveTarget(Diagnostics& diag, const ImageGroup&
                         dyld3::MachOParser parser(mh);
                         dyld3::MachOParser::FoundSymbol foundInfo;
                         if ( parser.findExportedSymbol(findSymbolDiag, symbolName, nullptr, foundInfo, reExportFollower) ) {
-                            result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                            switch (foundInfo.kind) {
+                                case MachOParser::FoundSymbol::Kind::headerOffset:
+                                case MachOParser::FoundSymbol::Kind::resolverOffset:
+                                    result = ((uintptr_t)(foundInfo.foundInDylib) + (uintptr_t)foundInfo.value);
+                                    break;
+                                case MachOParser::FoundSymbol::Kind::absolute:
+                                    result = (uintptr_t)foundInfo.value;
+                                    break;
+                            }
                             found  = true;
                             stop = true;
                         }
index 50785b504fdcf902f86f89a7db1defe82075b068..d34431a8e6f36bfcb8625c85bd713020b9e52379 100644 (file)
@@ -91,16 +91,20 @@ static bool sandboxBlockedStat(const char* path)
     return sandboxBlocked(path, "file-read-metadata");
 }
 
-#if TARGET_OS_WATCH
+#if TARGET_OS_WATCH || TARGET_OS_BRIDGE
 static uint64_t pageAlign(uint64_t value)
 {
-       return (value + 4095) & (-4096);
+  #if __arm64__
+    return (value + 0x3FFF) & (-0x4000);
+  #else
+       return (value + 0xFFF) & (-0x1000);
+  #endif
 }
 #endif
 
 static void updateSliceOffset(uint64_t& sliceOffset, uint64_t codeSignEndOffset, size_t fileLen)
 {
-#if TARGET_OS_WATCH
+#if TARGET_OS_WATCH || TARGET_OS_BRIDGE
     if ( sliceOffset != 0 ) {
         if ( pageAlign(codeSignEndOffset) == pageAlign(fileLen) ) {
             // cache builder saw fat file, but file is now thin
index 27bf3bad8e359542004320adf5b712993c3f9e19..92366f01bb4350588901c1ca31947d6971fa5bcd 100644 (file)
@@ -205,11 +205,9 @@ MachOParser::MachOParser(const mach_header* mh, bool dyldCacheIsRaw)
         // asssume out-of-process mach_header not in a dyld cache are raw mapped files
         _data |= 1;
     }
-    else {
-        // out-of-process mach_header in a dyld cache are not raw, but cache may be raw
-        if ( dyldCacheIsRaw )
-            _data |= 2;
-    }
+    // out-of-process mach_header in a dyld cache are not raw, but cache may be raw
+    if ( dyldCacheIsRaw )
+        _data |= 2;
 #endif
 }
 
index d1c821b3f75031daa2e9e4fbb94ff155a2c1e252..993ed54cbde78b831ea7f73f6565bb6aa0281b2b 100644 (file)
@@ -266,10 +266,13 @@ static bool preflightCacheFile(const SharedCacheOptions& options, SharedCacheLoa
         ::close(fd);
         return false;
     }
+    if ( (cache->header.mappingCount != 3) || (cache->header.mappingOffset > 0x120) ) {
+        results->errorMessage = "shared cache file mappings are invalid";
+        ::close(fd);
+        return false;
+    }
     const dyld_cache_mapping_info* const fileMappings = (dyld_cache_mapping_info*)&firstPage[cache->header.mappingOffset];
-    if ( (cache->header.mappingCount != 3)
-      || (cache->header.mappingOffset > 0x120)
-      || (fileMappings[0].fileOffset != 0)
+    if (  (fileMappings[0].fileOffset != 0)
       || ((fileMappings[0].address + fileMappings[0].size) > fileMappings[1].address)
       || ((fileMappings[1].address + fileMappings[1].size) > fileMappings[2].address)
       || ((fileMappings[0].fileOffset + fileMappings[0].size) != fileMappings[1].fileOffset)
index 90820e4e73cceea6ebf16b3c4945f425097464dc..f7e654cff450824011b211c19ebde594d36bfa92 100644 (file)
@@ -1,7 +1,7 @@
 
 namespace dyld3 {
 
-struct ClosureBuffer { int x; };
+struct ClosureBuffer { };
 
 ClosureBuffer closured_CreateImageGroup(const ClosureBuffer& input)
 {
index 9735df2478b7e3ce38c1221688bf6fe0cab29405..42cedaa1eea36caa18f83c523401afd087318024 100644 (file)
@@ -29,6 +29,7 @@
 #include "Logging.h"
 #include "PathOverrides.h"
 #include "LaunchCacheFormat.h"
+#include "start_glue.h"
 
 extern "C" void start();
 
@@ -123,6 +124,8 @@ static void entry_setChildForkFunction(void (*func)() )
     sChildForkFunction = func;
 }
 
+typedef void (*StartFunc)();
+
 const LibDyldEntryVector entryVectorForDyld = {
     LibDyldEntryVector::kCurrentVectorVersion,
     launch_cache::binary_format::kFormatVersion,
@@ -131,7 +134,7 @@ const LibDyldEntryVector entryVectorForDyld = {
     &entry_setOldAllImageInfo,
     &entry_setInitialImageList,
     &entry_runInitialzersBottomUp,
-    &start,
+    (StartFunc)address_of_start,
     &entry_setChildForkFunction,
     &entry_setLogFunction,
 };
index ef2a675cea0a5a4d4a57a6f5c0508c01ce4d4b36..7704301d7a53a47aeb797ab35b2dddb4badca73e 100644 (file)
@@ -241,19 +241,7 @@ bool build(Diagnostics& diags, dyld3::Manifest& manifest, const std::string& mas
         auto queueEntry = buildQueue[index];
         pthread_setname_np(queueEntry.options.loggingPrefix.substr(0, MAXTHREADNAMESIZE - 1).c_str());
         
-        DyldSharedCache::CreateResults results;
-        while (1) {
-            results = DyldSharedCache::create(queueEntry.options, queueEntry.dylibsForCache, queueEntry.otherDylibsAndBundles, queueEntry.mainExecutables);
-            if (!results.overflowed)
-                break;
-            auto evicted = manifest.removeLargestLeafDylib(queueEntry.configNames, queueEntry.options.archName);
-            if (evicted.empty())
-                break;
-            queueEntry = manifest.makeQueueEntry(queueEntry.outputPath, queueEntry.configNames, queueEntry.options.archName, queueEntry.options.optimizeStubs,  queueEntry.options.loggingPrefix, queueEntry.options.verbose);
-            dispatch_sync(warningQueue, ^{
-                warnings.insert("[WARNING] CACHE OVERFLOW: " + queueEntry.options.loggingPrefix + " evicted dylib: " + evicted);
-            });
-        }
+        DyldSharedCache::CreateResults results = DyldSharedCache::create(queueEntry.options, queueEntry.dylibsForCache, queueEntry.otherDylibsAndBundles, queueEntry.mainExecutables);
         dispatch_sync(warningQueue, ^{
             warnings.insert(results.warnings.begin(), results.warnings.end());
             bool chooseSecondCdHash = agileChooseSHA256CdHash;
@@ -262,13 +250,16 @@ bool build(Diagnostics& diags, dyld3::Manifest& manifest, const std::string& mas
                 chooseSecondCdHash = false;
             }
             for (const auto& configName : queueEntry.configNames) {
-                manifest.configuration(configName).architecture(queueEntry.options.archName).results.warnings = results.warnings;
+                auto& configResults = manifest.configuration(configName).architecture(queueEntry.options.archName).results;
+                for (const auto& mh : results.evictions) {
+                    auto parser = dyld3::MachOParser(mh);
+                    configResults.exclude(&parser, "VM overflow, evicting");
+                }
+                configResults.warnings = results.warnings;
                 if (queueEntry.options.optimizeStubs) {
-                    manifest.configuration(configName).architecture(queueEntry.options.archName)
-                    .results.developmentCache.cdHash = chooseSecondCdHash ? results.cdHashSecond : results.cdHashFirst;
+                    configResults.developmentCache.cdHash = chooseSecondCdHash ? results.cdHashSecond : results.cdHashFirst;
                 } else {
-                    manifest.configuration(configName).architecture(queueEntry.options.archName)
-                    .results.productionCache.cdHash =  chooseSecondCdHash ? results.cdHashSecond : results.cdHashFirst;
+                    configResults.productionCache.cdHash =  chooseSecondCdHash ? results.cdHashSecond : results.cdHashFirst;
                 }
             }
         });
index b4fe35a6b6f8d7bf0a236f4e7b7499b592c66639..89cd41872e2bd9cc0b7f22d9faa8d053173e4afe 100644 (file)
@@ -119,6 +119,11 @@ const std::set<std::string> CacheBuilder::warnings()
     return _diagnostics.warnings();
 }
 
+const std::set<const mach_header*> CacheBuilder::evictions()
+{
+    return _evictions;
+}
+
 void CacheBuilder::deleteBuffer()
 {
     vm_deallocate(mach_task_self(), (vm_address_t)_buffer, _allocatedBufferSize);
@@ -176,7 +181,7 @@ bool CacheBuilder::cacheOverflow(const dyld_cache_mapping_info regions[3])
     }
 }
 
-bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs,
+void CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs,
                          const std::vector<DyldSharedCache::MappedMachO>& otherOsDylibsInput,
                          const std::vector<DyldSharedCache::MappedMachO>& osExecutables)
 {
@@ -184,7 +189,7 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     // FIXME: plist should specify required vs optional dylibs
     if ( dylibs.size() < 30 ) {
         _diagnostics.error("missing required minimum set of dylibs");
-        return false;
+        return;
     }
     uint64_t t1 = mach_absolute_time();
 
@@ -196,10 +201,10 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     // assign addresses for each segment of each dylib in new cache
     dyld_cache_mapping_info regions[3];
     SegmentMapping segmentMapping = assignSegmentAddresses(sortedDylibs, regions);
-    if ( cacheOverflow(regions) ) {
+    while ( cacheOverflow(regions) ) {
         if ( !_options.evictLeafDylibsOnOverflow ) {
             _diagnostics.error("cache overflow: %lluMB (max %lluMB)", _vmSize / 1024 / 1024, (_archLayout->sharedMemorySize) / 1024 / 1024);
-            return false;
+            return;
         }
         // find all leaf (not referenced by anything else in cache) dylibs
 
@@ -248,6 +253,7 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
             for (std::vector<DyldSharedCache::MappedMachO>::iterator it=sortedDylibs.begin(); it != sortedDylibs.end(); ++it) {
                 dyld3::MachOParser parser(it->mh);
                 if ( installName == parser.installName() ) {
+                    _evictions.insert(parser.header());
                     otherOsDylibs.push_back(*it);
                     sortedDylibs.erase(it);
                     break;
@@ -256,10 +262,10 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
         }
         // re-layout cache
         segmentMapping = assignSegmentAddresses(sortedDylibs, regions);
-        if ( cacheOverflow(regions) ) {
+        if ( unreferencedDylibs.size() == 0 && cacheOverflow(regions) ) {
             _diagnostics.error("cache overflow, tried evicting %ld leaf daylibs, but still too big: %lluMB (max %lluMB)",
                                toRemove.size(), _vmSize / 1024 / 1024, (_archLayout->sharedMemorySize) / 1024 / 1024);
-            return false;
+            return;
         }
     }
 
@@ -267,7 +273,7 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     _allocatedBufferSize = std::max(_currentFileSize, (uint64_t)0x100000)*1.1; // add 10% to allocation to support large closures
     if ( vm_allocate(mach_task_self(), (vm_address_t*)&_buffer, _allocatedBufferSize, VM_FLAGS_ANYWHERE) != 0 ) {
         _diagnostics.error("could not allocate buffer");
-        return false;
+        return;
     }
     _currentFileSize = _allocatedBufferSize;
 
@@ -276,17 +282,17 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     copyRawSegments(sortedDylibs, segmentMapping);
     adjustAllImagesForNewSegmentLocations(sortedDylibs, segmentMapping);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     bindAllImagesInCacheFile(regions);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     // optimize ObjC
     if ( _options.optimizeObjC )
         optimizeObjC(_buffer, _archLayout->is64, _options.optimizeStubs, _pointersForASLR, _diagnostics);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     // optimize away stubs
     std::vector<uint64_t> branchPoolOffsets;
@@ -355,10 +361,10 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
                                                                                           _options.pathPrefixes, _patchTable,
                                                                                           _options.optimizeStubs, !_options.dylibsRemovedDuringMastering);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
     addCachedDylibsImageGroup(dylibGroup);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     uint64_t t4 = mach_absolute_time();
 
@@ -366,10 +372,10 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     dyld3::ImageProxyGroup* otherGroup = dyld3::ImageProxyGroup::makeOtherOsGroup(_diagnostics, dyldCacheParser, dylibGroup, otherOsDylibs,
                                                                                   _options.inodesAreSameAsRuntime, _options.pathPrefixes);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
     addCachedOtherDylibsImageGroup(otherGroup);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     uint64_t t5 = mach_absolute_time();
 
@@ -393,7 +399,7 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     }
     addClosures(closures);
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     uint64_t t6 = mach_absolute_time();
 
@@ -455,13 +461,13 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
     // last sanity check on size
     if ( _vmSize > _archLayout->sharedMemorySize ) {
         _diagnostics.error("cache overflow after optimizations.  %lluMB (max %lluMB)", _vmSize / 1024 / 1024, (_archLayout->sharedMemorySize) / 1024 / 1024);
-        return true;
+        return;
     }
 
     // codesignature is part of file, but is not mapped
     codeSign();
     if ( _diagnostics.hasError() )
-        return false;
+        return;
 
     uint64_t t8 = mach_absolute_time();
 
@@ -483,7 +489,7 @@ bool CacheBuilder::build(const std::vector<DyldSharedCache::MappedMachO>& dylibs
         _allocatedBufferSize = _currentFileSize;
     }
 
-    return false;
+    return;
 }
 
 
index 4a6227c39146ff9fd0bf40401a0d28eeb6e24f96..582ac3ecf5f623f187d843346f210396c09a0839 100644 (file)
@@ -47,19 +47,20 @@ namespace  dyld3 {
 
 struct CacheBuilder {
 
-                                    CacheBuilder(const DyldSharedCache::CreateOptions& options);
-
-    bool                            build(const std::vector<DyldSharedCache::MappedMachO>&  dylibsToCache,
-                                          const std::vector<DyldSharedCache::MappedMachO>&  otherOsDylibs,
-                                          const std::vector<DyldSharedCache::MappedMachO>&  osExecutables);
-    void                            deleteBuffer();
-    const DyldSharedCache*          buffer() { return _buffer; }
-    size_t                          bufferSize() { return (size_t)_allocatedBufferSize; }
-    std::string                     errorMessage();
-    const std::set<std::string>     warnings();
-    const bool                      agileSignature();
-    const std::string               cdHashFirst();
-    const std::string               cdHashSecond();
+                                        CacheBuilder(const DyldSharedCache::CreateOptions& options);
+
+    void                                build(const std::vector<DyldSharedCache::MappedMachO>&  dylibsToCache,
+                                              const std::vector<DyldSharedCache::MappedMachO>&  otherOsDylibs,
+                                              const std::vector<DyldSharedCache::MappedMachO>&  osExecutables);
+    void                                deleteBuffer();
+    const DyldSharedCache*              buffer() { return _buffer; }
+    size_t                              bufferSize() { return (size_t)_allocatedBufferSize; }
+    std::string                         errorMessage();
+    const std::set<std::string>         warnings();
+    const std::set<const mach_header*>  evictions();
+    const bool                          agileSignature();
+    const std::string                   cdHashFirst();
+    const std::string                   cdHashSecond();
 
     struct SegmentMappingInfo {
         const void*     srcSegment;
@@ -126,6 +127,7 @@ private:
     const DyldSharedCache::CreateOptions&       _options;
     DyldSharedCache*                            _buffer;
     Diagnostics                                 _diagnostics;
+    std::set<const mach_header*>               _evictions;
     const ArchLayout*                           _archLayout;
     uint32_t                                    _aliasCount;
     uint64_t                                    _slideInfoFileOffset;
index 4fbdd235324987a89a977d5343780bb6122fbfeb..f544c190e27bf1cdd57748bb1cc0b0b83aeab7f2 100644 (file)
@@ -64,12 +64,14 @@ DyldSharedCache::CreateResults DyldSharedCache::create(const CreateOptions&
     CreateResults  results;
     CacheBuilder   cache(options);
 
-    results.overflowed = cache.build(dylibsToCache, otherOsDylibs, osExecutables);
+    cache.build(dylibsToCache, otherOsDylibs, osExecutables);
 
     results.agileSignature = cache.agileSignature();
     results.cdHashFirst = cache.cdHashFirst();
     results.cdHashSecond = cache.cdHashSecond();
     results.warnings = cache.warnings();
+    results.evictions = cache.evictions();
+
     if ( cache.errorMessage().empty() ) {
         results.cacheContent = cache.buffer();
         results.cacheLength  = cache.bufferSize();
index 2d84065d3be0d3e98711b632b7d7be09019b600c..56008b5107bd8228ae268117c1ecbe1350fad8cc 100644 (file)
@@ -97,14 +97,14 @@ public:
 
     struct CreateResults
     {
-        const DyldSharedCache*      cacheContent    = nullptr;    // caller needs to vm_deallocate() when done
-        size_t                      cacheLength     = 0;
-        std::string                 errorMessage;
-        std::set<std::string>       warnings;
-        bool                        agileSignature = false;
-        std::string                 cdHashFirst;
-        std::string                 cdHashSecond;
-        bool                        overflowed = false;
+        const DyldSharedCache*          cacheContent    = nullptr;    // caller needs to vm_deallocate() when done
+        size_t                          cacheLength     = 0;
+        std::string                     errorMessage;
+        std::set<std::string>           warnings;
+        std::set<const mach_header*>    evictions;
+        bool                            agileSignature = false;
+        std::string                     cdHashFirst;
+        std::string                     cdHashSecond;
     };
 
 
index fcd6db5508851d166396882d1fe2964c0d13a4af..960e1b96293083f0d3c5dd38d64b6141932b74f2 100644 (file)
@@ -1212,7 +1212,7 @@ ImageProxyGroup* ImageProxyGroup::makeOtherOsGroup(Diagnostics& diag, const Dyld
     // add every dylib/bundle in "other: list to _images
     uint32_t indexInGroup = 0;
     for (const DyldSharedCache::MappedMachO& mapping : otherDylibsAndBundles) {
-        ImageProxy* proxy = new ImageProxy(mapping, 1, indexInGroup++, false);
+        ImageProxy* proxy = new ImageProxy(mapping, 1, indexInGroup++, true);
         groupProxy->_images.push_back(proxy);
         groupProxy->_pathToProxy[mapping.runtimePath] = proxy;
     }
@@ -1304,7 +1304,7 @@ BinaryClosureData* ImageProxyGroup::makeClosure(Diagnostics& diag, const DyldCac
     ImageProxyGroup mainClosureGroupProxy(2, dyldCache, nullptr, otherOsDylibs, mainProgMapping.runtimePath, existingGroups, buildTimePrefixes,
                                           emptyEnvVars, false, true, inodesAreSameAsRuntime);
 
-    ImageProxy* mainProxy = new ImageProxy(mainProgMapping, 2, 0, false);
+    ImageProxy* mainProxy = new ImageProxy(mainProgMapping, 2, 0, true);
     if ( mainProxy == nullptr ) {
         diag.error("can't find slice matching dyld cache in %s", mainProgMapping.runtimePath.c_str());
         return nullptr;
@@ -2149,7 +2149,10 @@ void ImageProxyGroup::populateGroupWriter(Diagnostics& diag, launch_cache::Image
                             assert(interposeReplacement.isGroupImageTarget(replacementGroupNum, replacementIndexInGroup, replacementOffsetInImage));
                             assert(replacementGroupNum == 2);
                             assert(replacementIndexInGroup < (1 << 8));
-                            assert(replacementOffsetInImage < 0xFFFFFFFFULL);
+                            if ( replacementOffsetInImage >= 0xFFFFFFFFULL ) {
+                                diag.warning("bad interposing implementation in %s", _images[imageIndex]->runtimePath().c_str());
+                                return;
+                            }
                             DyldCacheOverride cacheOverride;
                             cacheOverride.patchTableIndex = patchTableIndex;
                             cacheOverride.imageIndex      = replacementIndexInGroup;
@@ -2225,7 +2228,10 @@ void ImageProxyGroup::populateGroupWriter(Diagnostics& diag, launch_cache::Image
                             MachOParser::FoundSymbol foundInfo;
                             if ( weakDefParser.findExportedSymbol(weakDiag, entry.first.c_str(), nullptr, foundInfo, nullptr) ) {
                                 assert(proxy->indexInGroup() < (1 << 8));
-                                assert(foundInfo.value < (1ULL << 32));
+                                if ( foundInfo.value >= (1ULL << 32) ) {
+                                    diag.warning("bad weak symbol address in %s", proxy->runtimePath().c_str());
+                                    return;
+                                }
                                 entry.second.imageIndex  = proxy->indexInGroup();
                                 entry.second.imageOffset = foundInfo.value;
                             }
index 3dd9f3347dec4ba90e4d0d212af91bed20c0d60e..abc23bba67ffd42f68212b902e37ddb0f08952d1 100644 (file)
@@ -279,7 +279,7 @@ BuildQueueEntry Manifest::makeQueueEntry(const std::string& outputPath, const st
     options.cacheSupportsASLR = true;
     options.forSimulator = false;
     options.verbose = verbose;
-    options.evictLeafDylibsOnOverflow = false;
+    options.evictLeafDylibsOnOverflow = true;
     options.loggingPrefix = prefix;
     options.pathPrefixes = { "" };
     options.dylibOrdering = loadOrderFile(_dylibOrderFile);
index 84e2a65293ab61628732db8ef6579ff5d1c88623..b8ac19f0f2ba3a49711636f1b79d2f8738362189 100644 (file)
@@ -296,9 +296,10 @@ AcceleratorTables<P>::AcceleratorTables(DyldSharedCache* cache, uint64_t linkedi
         DepNode& node = _depDAG[op->machHeader()];
         for (const char* depPath : op->getDownwardDependents()) {
             macho_header<P>* depMH = _dylibPathToMachHeader[depPath];
-            assert(depMH != NULL);
-            DepNode* depNode = &_depDAG[depMH];
-            node._dependents.push_back(depNode);
+            if ( depMH != nullptr ) {
+                DepNode* depNode = &_depDAG[depMH];
+                node._dependents.push_back(depNode);
+            }
         }
     }
 
index 1e82704f559286f499fbd1328dfba9f8626559c6..8fca51c983019adf55e22b80d406d988b556c287 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/xattr.h>
 #include <mach/mach.h>
 #include <mach/mach_time.h>
 #include <limits.h>
@@ -772,6 +773,11 @@ int main(int argc, const char* argv[])
         //    fprintf(stderr, "  %s\n", aFile.runtimePath.c_str());
         //}
 
+        // Clear the UUID xattr for the existing cache.
+        // This prevents the existing cache from being used by dyld3 as roots are probably involved
+        if (removexattr(outFile.c_str(), "cacheUUID", 0) != 0) {
+            fprintf(stderr, "update_dyld_shared_cache: warning: failure to remove UUID xattr on shared cache file %s with error %s\n", outFile.c_str(), strerror(errno));
+        }
 
         // build cache new cache file
         DyldSharedCache::CreateOptions options;
@@ -802,9 +808,16 @@ int main(int argc, const char* argv[])
         else {
             // save new cache file to disk and write new .map file
             assert(results.cacheContent != nullptr);
-            if ( !safeSave(results.cacheContent, results.cacheLength, outFile) )
+            if ( !safeSave(results.cacheContent, results.cacheLength, outFile) ) {
+                fprintf(stderr, "update_dyld_shared_cache: could not write dyld cache file %s\n", outFile.c_str());
                 cacheBuildFailure = true;
+            }
             if ( !cacheBuildFailure ) {
+                uuid_t cacheUUID;
+                results.cacheContent->getUUID(cacheUUID);
+                if (setxattr(outFile.c_str(), "cacheUUID", (const void*)&cacheUUID, sizeof(cacheUUID), 0, XATTR_CREATE) != 0) {
+                    fprintf(stderr, "update_dyld_shared_cache: warning: failure to set UUID xattr on shared cache file %s with error %s\n", outFile.c_str(), strerror(errno));
+                }
                 std::string mapStr = results.cacheContent->mapFile();
                 std::string outFileMap = cacheDir + "/dyld_shared_cache_" + fileSet.archName + ".map";
                 safeSave(mapStr.c_str(), mapStr.size(), outFileMap);
index feba249cb758c2e84d6b7ac69f59c6b0d4a3b2db..1becea3418b4e79ea5c02192339e8007015e3d24 100644 (file)
@@ -504,7 +504,7 @@ void ImageLoaderMachO::sniffLoadCommands(const macho_header* mh, const char* pat
 
        if ( symTabCmd != NULL ) {
                // validate symbol table fits in LINKEDIT
-               if ( symTabCmd->symoff < linkeditFileOffsetStart )
+               if ( (symTabCmd->nsyms > 0) && (symTabCmd->symoff < linkeditFileOffsetStart) )
                        throw "malformed mach-o image: symbol table underruns __LINKEDIT";
                if ( symTabCmd->nsyms > 0x10000000 )
                        throw "malformed mach-o image: symbol table too large";
@@ -1615,6 +1615,10 @@ void ImageLoaderMachO::doRebase(const LinkContext& context)
        if ( fRetainForObjC )
                this->setNeverUnload();
 
+    // dylibs with thread local variables cannot be unloaded because there is no way to clean up all threads
+    if ( !this->inSharedCache() && (this->machHeader()->flags & MH_HAS_TLV_DESCRIPTORS) )
+        this->setNeverUnload();
+
        // if prebound and loaded at prebound address, then no need to rebase
        if ( this->usablePrebinding(context) ) {
                // skip rebasing because prebinding is valid
index 020ec51fcd87f62f20e1d9eb2f6bf68b4f24c07a..627d572220b305d12b8938777dffeee75525faaf 100644 (file)
@@ -157,10 +157,6 @@ ImageLoaderMachOCompressed* ImageLoaderMachOCompressed::instantiateFromFile(cons
                // make sure path is stable before recording in dyld_all_image_infos
                image->setMapped(context);
 
-               // dylibs with thread local variables cannot be unloaded because there is no way to clean up all threads
-               if ( image->machHeader()->flags & MH_HAS_TLV_DESCRIPTORS )
-                       image->setNeverUnload();
-
                // pre-fetch content of __DATA and __LINKEDIT segment for faster launches
                // don't do this on prebound images or if prefetching is disabled
         if ( !context.preFetchDisabled && !image->isPrebindable()) {
index c98a9e356125434442d5923e9d67108bd08fedd6..2fd37875d220e6c093568bd52cf068d58e14c946 100644 (file)
@@ -40,6 +40,7 @@
 #include <sys/un.h>
 #include <sys/syslog.h>
 #include <sys/uio.h>
+#include <sys/xattr.h>
 #include <mach/mach.h>
 #include <mach-o/fat.h>
 #include <mach-o/loader.h> 
@@ -3139,8 +3140,15 @@ static ImageLoader* loadPhase5load(const char* path, const char* orgPath, const
                                return anImage;
                }
                // if RTLD_NOLOAD, do nothing if not already loaded
-               if ( context.dontLoad )
+               if ( context.dontLoad ) {
+                       // <rdar://33412890> possible that there is an override of cache
+                       if ( my_stat(path, &statBuf) == 0 ) {
+                               ImageLoader* imageLoader = findLoadedImage(statBuf);
+                               if ( imageLoader != NULL )
+                                       return imageLoader;
+                       }
                        return NULL;
+               }
                bool useCache = false;
                if ( shareCacheResults.imageData == nullptr ) {
                        // HACK to support old caches
@@ -5134,21 +5142,21 @@ static bool closureValid(const dyld3::launch_cache::BinaryClosureData* mainClosu
        }
 #if __MAC_OS_X_VERSION_MIN_REQUIRED
        else {
-               // HACK until closured for dlopen can run against live cache file
-               int fd = my_open(sSharedCacheLoadInfo.path, O_RDONLY, 0);
-               if ( fd != -1 ) {
-                       dyld_cache_header fileHeader;
-                       if ( pread(fd, &fileHeader, sizeof(fileHeader), 0) == sizeof(fileHeader) ) {
-                               uuid_t cacheUUID;
-                               sSharedCacheLoadInfo.loadAddress->getUUID(cacheUUID);
-                               if ( memcmp(fileHeader.uuid, cacheUUID, sizeof(uuid_t)) != 0 ) {
-                                       if ( gLinkContext.verboseWarnings )
-                                               dyld::log("dyld: closure %p not used because current cache on disk is not they one being used\n", mainClosureData);
-                                       ::close(fd);
-                                       return false;
-                               }
-                       }
-                       ::close(fd);
+               // If the in-memory cache doesn't have the same UUID xattr as the on-disk cache then we must
+               // have built a new cache but not rebooted.  In this case, don't use dyld3.
+               const char* sharedCachePath = getStandardSharedCacheFilePath();
+               uuid_t inMemoryUUID;
+               uuid_t onDiskUUID;
+               sharedCacheUUID(inMemoryUUID);
+               if (getxattr(sharedCachePath, "cacheUUID", (void*)&onDiskUUID, sizeof(uuid_t), 0, 0) != sizeof(uuid_t)) {
+                       if ( gLinkContext.verboseWarnings )
+                               dyld::log("dyld: closure %p on disk cache doesn't have a UUID xattr\n", mainClosureData);
+                       return false;
+               }
+               if (memcmp(&inMemoryUUID, &onDiskUUID, sizeof(uuid_t)) != 0) {
+                       if ( gLinkContext.verboseWarnings )
+                               dyld::log("dyld: closure %p not used because current cache on disk and in memory cache have UUID mismatches\n", mainClosureData);
+                       return false;
                }
        }
 #endif
index 65e568172bca605ab2434b6464e0057880941954..c77e6527f34d86a8efa7d8599ee7df227bce968b 100644 (file)
@@ -645,6 +645,7 @@ NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolN
        dyld::clearErrorMessage();
        ImageLoader* image = dyld::findImageByMachHeader(mh);
        if ( image != NULL ) {
+               const char* symbolToFind = symbolName;
                try {
                        if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY ) {
                                image->bindAllLazyPointers(dyld::gLinkContext, true);
@@ -658,7 +659,7 @@ NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolN
                                dyldAPIhalt(__func__, msg);
                        }
                }
-               symbol = image->findExportedSymbol(symbolName, true, NULL);
+               symbol = image->findExportedSymbol(symbolToFind, true, NULL);
        }
        if ( dyld::gLogAPIs && (symbol == NULL) )
                dyld::log("%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__, mh, symbolName, options);
index cf64f58d9f601e48d18d94881d51ff863e2f66f5..fb393fa0b45c15c8dfc3b1edbf6e3899f9a05e73 100644 (file)
@@ -126,18 +126,20 @@ void free(void* ptr)
 
 void* calloc(size_t count, size_t size)
 {
+    // Check for overflow of integer multiplication
+    size_t total = count * size;
+    if ( total/count != size ) {
+        dyld::log("dyld calloc overflow: count=%zu, size=%zu\n", count, size);
+        dyld::halt("dyld calloc overflow");
+    }
        if ( dyld::gLibSystemHelpers != NULL ) {
-               void* result = dyld::gLibSystemHelpers->malloc(size*count);
-               bzero(result, size*count);
+               void* result = dyld::gLibSystemHelpers->malloc(total);
+        if ( result != NULL )
+                   bzero(result, total);
                return result;
        }
        else {
-               // Check for overflow of integer multiplication
-               size_t total = count * size;
-               if ( total/count != size ) {
-                       dyld::log("dyld calloc overflow: count=%zu, size=%zu\n", count, size);
-                       exit(1);
-               }
+        // this allocates out of static buffer which is already zero filled
                return malloc(total);
        }
 }
index 6d5eee3afaf9d1c6c2acac78b8181c641317e17a..ec9bce4d65dd8ae0550dbb5cc01b3f0ffaa912d1 100644 (file)
@@ -53,7 +53,9 @@ struct __attribute__((visibility("hidden"))) dyld_process_info_notify_base
     static dyld_process_info_notify_base* make(task_t task, dispatch_queue_t queue, Notify notify, NotifyExit notifyExit, kern_return_t* kr);
                                                                                ~dyld_process_info_notify_base();
 
-    uint32_t&           retainCount() const { return _retainCount; }
+    bool                incRetainCount() const;
+    bool                decRetainCount() const;
+
        void                            setNotifyMain(NotifyMain notifyMain) const { _notifyMain = notifyMain; }
 
     // override new and delete so we don't need to link with libc++
@@ -67,7 +69,7 @@ private:
        kern_return_t           unpokeSendPortInTarget();
     void                               setMachSourceOnQueue();
 
-       mutable uint32_t        _retainCount;
+       mutable int32_t         _retainCount;
     dispatch_queue_t    _queue;
     Notify              _notify;
     NotifyExit          _notifyExit;
@@ -89,6 +91,7 @@ dyld_process_info_notify_base::dyld_process_info_notify_base(dispatch_queue_t qu
 dyld_process_info_notify_base::~dyld_process_info_notify_base()
 {
        if ( _machSource ) {
+        dispatch_source_cancel(_machSource);
                dispatch_release(_machSource);
                _machSource = NULL;
        }
@@ -106,6 +109,18 @@ dyld_process_info_notify_base::~dyld_process_info_notify_base()
        }
 }
 
+bool dyld_process_info_notify_base::incRetainCount() const
+{
+    int32_t newCount = OSAtomicIncrement32(&_retainCount);
+    return ( newCount == 1 );
+}
+
+bool dyld_process_info_notify_base::decRetainCount() const
+{
+    int32_t newCount = OSAtomicDecrement32(&_retainCount);
+    return ( newCount == 0 );
+}
+
 
 dyld_process_info_notify_base* dyld_process_info_notify_base::make(task_t task, dispatch_queue_t queue, Notify notify, NotifyExit notifyExit, kern_return_t* kr)
 {
@@ -173,6 +188,10 @@ void dyld_process_info_notify_base::setMachSourceOnQueue()
        NotifyExit exitHandler = _notifyExit;
        _machSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, _receivePortInMonitor, 0, _queue);
     dispatch_source_set_event_handler(_machSource, ^{
+        // This event handler block has an implicit reference to "this"
+        // if incrementing the count goes to one, that means the object may have already been destroyed
+        if ( incRetainCount() )
+            return;
         uint8_t messageBuffer[DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE];
         mach_msg_header_t* h = (mach_msg_header_t*)messageBuffer;
 
@@ -229,7 +248,9 @@ void dyld_process_info_notify_base::setMachSourceOnQueue()
                                fprintf(stderr, "received unknown message id=0x%X, size=%d\n", h->msgh_id, h->msgh_size);
                        }
         }
-    });
+        if ( decRetainCount() )
+            delete this;
+   });
     dispatch_resume(_machSource);
 }
 
@@ -323,13 +344,14 @@ void _dyld_process_info_notify_main(dyld_process_info_notify object, void (^noti
 
 void _dyld_process_info_notify_retain(dyld_process_info_notify object)
 {
-    object->retainCount() += 1;
+    object->incRetainCount();
 }
 
 void _dyld_process_info_notify_release(dyld_process_info_notify object)
 {
-    object->retainCount() -= 1;
-    if ( object->retainCount() == 0 )
+    // Note if _machSource is currently handling a message, the retain count will not be zero
+    // and object will instead be deleted when handling is done.
+    if ( object->decRetainCount() )
         delete object;
 }
 
index 6954ad1db3d271f22bf6eded121a656e2ad2514d..3872e7dbe5fdde16c8b88e9693a6790bbd3feeda 100644 (file)
@@ -111,10 +111,6 @@ static bool alwaysGetImages(struct task_and_pid tp, bool launchedSuspended)
     // ideally the fail count would be zero.  But the target is dlopen/dlclosing in a tight loop, so there may never be a stable set of images.
     // The real bug driving this test case was _dyld_process_info_create() crashing when the the image list changed too fast.
     // The important thing is to not crash.  Getting NULL back is ok.
-    if ( failCount > 50 ) {
-        printf("[FAIL] dyld_process_info_unload %d out of 100 calls to _dyld_process_info_create() failed\n", failCount);
-        return false;
-    }
     return true;
 }
 
diff --git a/testing/test-cases/flat-namespace-absolute-symbol.dtest/foo.s b/testing/test-cases/flat-namespace-absolute-symbol.dtest/foo.s
new file mode 100644 (file)
index 0000000..5435411
--- /dev/null
@@ -0,0 +1,4 @@
+
+       .global  _myAbs1
+_myAbs1 = 0
+
diff --git a/testing/test-cases/flat-namespace-absolute-symbol.dtest/main.c b/testing/test-cases/flat-namespace-absolute-symbol.dtest/main.c
new file mode 100644 (file)
index 0000000..6fcd005
--- /dev/null
@@ -0,0 +1,28 @@
+// BUILD_ONLY: MacOSX
+
+// BUILD:  $CC foo.s -dynamiclib -o $BUILD_DIR/libfoo.dylib -install_name $RUN_DIR/libfoo.dylib
+// BUILD:  $CC main.c $BUILD_DIR/libfoo.dylib -o $BUILD_DIR/flat-namespace.exe -flat_namespace
+
+// RUN:    ./flat-namespace.exe
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern int myAbs1;
+int* ptr = &myAbs1;
+
+int main()
+{
+    printf("[BEGIN] flat-namespace-absolute-symbol\n");
+
+    if ( ptr != 0 ) {
+        printf("[FAIL] absolute symbol not bound to zero with flat lookup\n");
+        return 0;
+    }
+
+    printf("[PASS] flat-namespace-absolute-symbol\n");
+       return 0;
+}