@@ -1015,6 +1015,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock)
10151015 sectionRegion.prettyName = imageHeader.value ().identifierPrefix + " ::" + std::string (segName);
10161016 sectionRegion.start = segment.vmaddr ;
10171017 sectionRegion.size = segment.vmsize ;
1018+ sectionRegion.imageStart = start.second ;
10181019 uint32_t flags = SegmentFlagsFromMachOProtections (segment.initprot , segment.maxprot );
10191020
10201021 // if we're positive we have an entry point for some reason, force the segment
@@ -1529,18 +1530,16 @@ const SharedCacheMachOHeader* SharedCache::HeaderForAddress(uint64_t address)
15291530 if (auto it = m_cacheInfo->headers .find (address); it != m_cacheInfo->headers .end ())
15301531 return &it->second ;
15311532
1532- // We _could_ mark each page with the image start? :grimacing emoji:
1533- // But that'd require mapping pages :grimacing emoji: :grimacing emoji:
1534- // There's not really any other hacks that could make this faster, that I can think of...
1535- for (const auto & [start, header] : m_cacheInfo->headers )
1536- {
1537- for (const auto & segment : header.segments )
1538- {
1539- if (segment.vmaddr <= address && segment.vmaddr + segment.vmsize > address)
1540- return &header;
1541- }
1542- }
1543- return {};
1533+ auto it = m_cacheInfo->memoryRegions .find (address);
1534+ if (it == m_cacheInfo->memoryRegions .end ())
1535+ return nullptr ;
1536+
1537+ if (auto headerAddress = it->second .imageStart )
1538+ return HeaderForAddress (headerAddress);
1539+
1540+ // Found a region, but its `imageStart` was 0. This should mean it doesn't belong to an image.
1541+ assert (it->second .type != MemoryRegion::Type::Image);
1542+ return nullptr ;
15441543}
15451544
15461545std::string SharedCache::NameForAddress (uint64_t address)
@@ -1561,16 +1560,9 @@ std::string SharedCache::ImageNameForAddress(uint64_t address)
15611560
15621561bool SharedCache::LoadImageContainingAddress (uint64_t address, bool skipObjC)
15631562{
1564- for (const auto & [start, header] : m_cacheInfo->headers )
1565- {
1566- for (const auto & segment : header.segments )
1567- {
1568- if (segment.vmaddr <= address && segment.vmaddr + segment.vmsize > address)
1569- {
1570- std::lock_guard lock (m_mutex);
1571- return LoadImageWithInstallName (lock, header.installName , skipObjC);
1572- }
1573- }
1563+ if (auto header = HeaderForAddress (address)) {
1564+ std::lock_guard lock (m_mutex);
1565+ return LoadImageWithInstallName (lock, header->installName , skipObjC);
15741566 }
15751567
15761568 return false ;
@@ -3387,6 +3379,29 @@ std::optional<SharedCache::CacheInfo> SharedCache::CacheInfo::Load(Deserializati
33873379 cacheInfo.MSL (objcOptimizationDataRange);
33883380 cacheInfo.MSL (baseFilePath);
33893381 cacheInfo.MSL_CAST (cacheFormat, uint8_t , SharedCacheFormat);
3382+
3383+ // Older metadata may be missing the `imageStart` field on `MemoryRegion`.
3384+ bool regionsMissingImageStart =
3385+ std::any_of (cacheInfo.memoryRegions .begin (), cacheInfo.memoryRegions .end (), [](const auto & pair) {
3386+ const auto & region = pair.second ;
3387+ return region.type == MemoryRegion::Type::Image && region.imageStart == 0 ;
3388+ });
3389+
3390+ if (regionsMissingImageStart)
3391+ {
3392+ for (const auto & [start, header] : cacheInfo.headers )
3393+ {
3394+ for (const auto & segment : header.segments )
3395+ {
3396+ const auto regionIt = cacheInfo.memoryRegions .find (segment.vmaddr );
3397+ assert (regionIt != cacheInfo.memoryRegions .end ());
3398+ auto & region = regionIt->second ;
3399+ assert (!region.imageStart || region.imageStart == start);
3400+ region.imageStart = start;
3401+ }
3402+ }
3403+ }
3404+
33903405 return cacheInfo;
33913406}
33923407void State::Store (SerializationContext& context, std::optional<DSCViewState> viewState) const
0 commit comments