From c22d54c5d95f4d23629484579414387b0c7503ee Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Sun, 6 Apr 2025 20:00:00 -0400 Subject: [SharedCache] Replace write log with callback registration for reapplying slide info This improves performance by ~10x with the only real issue being a copy of the cache entry existing for each weak ref. Also fixes - Some old TODO's that are no longer relevant - Some function signatures not being const - FileAccessorCache not evicting enough accessors to fit under an adjusted cache size - Added a warning if we are over the global cache size in view initialization - Logger name not having a `.` in `SlideInfoProcessor::SlideInfoProcessor` - Re-added the accessor dirty check before applying slide info to fix https://github.com/Vector35/binaryninja-api/issues/6570 --- view/sharedcache/core/SharedCache.cpp | 36 +++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'view/sharedcache/core/SharedCache.cpp') diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 9bbe51e4..c6950a84 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -397,10 +397,42 @@ void SharedCache::ProcessEntryRegions(const CacheEntry& entry) } } -void SharedCache::ProcessEntrySlideInfo(const CacheEntry& entry) +void SharedCache::ProcessEntrySlideInfo(const CacheEntry& entry) const { auto slideInfoProcessor = SlideInfoProcessor(GetBaseAddress()); - slideInfoProcessor.ProcessEntry(*m_vm, entry); + + // This will be set for every associated `VirtualMemoryRegion` so that any accesses though the VM will be always be slid. + // NOTE: This MUST be called on the CacheEntry object owned by SharedCache, otherwise persistence through the `SharedCacheController` will not occur. + // NOTE: This will keep a copy of a processor in the `WeakFileAccessor` until that object is destroyed (likely view destruction). + // NOTE: This will keep a copy of the cache entry in the `WeakFileAccessor` until that object is destroyed (likely view destruction). + auto reviveCallback = [slideInfoProcessor, entry](MappedFileAccessor& revivedAccessor) { + slideInfoProcessor.ProcessEntry(revivedAccessor, entry); + }; + + // Use the current entry accessor, don't register the callback for this one as we want calls through the VM to be slid only. + // Actually process the slide info for this entry, everything else besides this is to support revived file accessors. + auto slideMappings = slideInfoProcessor.ProcessEntry(*entry.GetAccessor().lock(), entry); + + // Register the revive callback for all virtual memory regions that have been slid. + // The reason we don't just set this on the entry accessor is that accessor is not consulted for anything really after + // this point, everything else will be going through the virtual memory, and because the callback is on the weak accessor + // reference and not the file accessor cache itself this matters. + auto vm = GetVirtualMemory(); + for (const auto& mapping : slideMappings) + { + // Because the mapping address is a file offset for us to consult the virtual memory we must first call `GetMappedAddress`. + if (auto mappedMappingAddr = entry.GetMappedAddress(mapping.address)) + { + if (auto vmRegion = vm->GetRegionAtAddress(*mappedMappingAddr)) + { + // Ok we have the virtual memory region, lets register the callback on its accessor. + vmRegion->fileAccessor.RegisterReviveCallback(reviveCallback); + continue; + } + } + + LogWarn("Failed to register revive callback for slide mapping %llx in entry '%s'", mapping.address, entry.GetFileName().c_str()); + } } void SharedCache::ProcessSymbols() -- cgit v1.3.1