From a72b98ed5a357bb380d81f07f3f36946aa729bb2 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Mon, 23 Feb 2026 23:26:27 -0800 Subject: [DSC] Simplify file mapping to fix intermittent unrelocated pointers The `FileAccessorCache`'s LRU eviction could discard a file's mapped data after slide info had already been applied to it. Future accesses to the file produced a fresh mapping, but failed to reapply the slide info. This could result in pointers not correctly being slid, such as in https://github.com/Vector35/binaryninja-api/issues/7689. The LRU cache existed to stay within OS file descriptor limits, since the old `MappedFile` held its fd open for the lifetime of the mapping. There's no real reason for it to hold the file descriptor open like this. Closing it after `mmap` is sufficient to avoid the file descriptor limits. `MappedFileRegion` replaces the combination of `FileAccessorCache`, `WeakFileAccessor`, and `MappedFileAccessor`. It closes the fd immediately after mmap, so all files can stay mapped without consuming descriptors, making the cache unnecessary. `MappedFileRegion` is owned directly by the `CacheEntry` for its full lifetime. Slide info is applied exactly once to each `MappedFileRegion`. --- view/sharedcache/core/FileAccessorCache.h | 76 ------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 view/sharedcache/core/FileAccessorCache.h (limited to 'view/sharedcache/core/FileAccessorCache.h') diff --git a/view/sharedcache/core/FileAccessorCache.h b/view/sharedcache/core/FileAccessorCache.h deleted file mode 100644 index 46de6fcc..00000000 --- a/view/sharedcache/core/FileAccessorCache.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include - -#include "MappedFileAccessor.h" - -typedef uint32_t CacheAccessorID; - -// TODO: We might want to make this more than just the path, for example -// TODO: We might want to make it unique to a view session (session id). -// Get a unique entry id for the given file path. -CacheAccessorID GetCacheAccessorID(const std::string& filePath); - -class WeakFileAccessor; - -class FileAccessorCache -{ - size_t m_cacheSize; - std::mutex m_mutex; - // NOTE: If we end up wanting to handle 1000's of files we should consider std::list. - std::deque m_cache; - std::unordered_map> m_accessors; - - explicit FileAccessorCache(size_t cacheSize = 8); - - void EvictLastUsed(); - -public: - static FileAccessorCache& Global(); - - // Get a weak reference to a file accessor, the reference at this point is alive. - // The reference is always alive at this point either because it is in the cache or it has been inserted in. - // Subsequent calls to this might kill the backing file accessor resulting in the weak ref recreating the file - // accessor and inserting itself back into its related cache. - WeakFileAccessor Open(const std::string& filePath); - - void RemoveAccessor(CacheAccessorID id); - - // Adjust the cache size limit. - // This will NOT evict current cache entries, as they are already available. - // Any subsequent call to `Open` will assume this cache size, evicting until the size is equal to the cache size. - void SetCacheSize(const uint64_t size) { m_cacheSize = size; }; - - size_t GetCacheSize() const { return m_cacheSize; } - - size_t GetCacheCount() const { return m_accessors.size(); } -}; - -class WeakFileAccessor -{ - using ReviveCallback = std::function; - - // Weak pointer to the mapped file accessor, once this is expired we will re-open. - std::weak_ptr m_weakPtr; - // File path for re-opening if needed - std::string m_filePath; - - // Used to re-add writes once the file accessor is "revived". - std::optional m_reviveCallback; - - // TODO: Store a weak_ptr/shared_ptr to FileAccessorCache? That way we dont access Global() - // TODO: Only need to do the above if we want multiple caches. - -public: - explicit WeakFileAccessor(std::weak_ptr weakPtr, std::string filePath) : - m_weakPtr(std::move(weakPtr)), m_filePath(std::move(filePath)) - {} - - // Register the function to be called once the file accessor is revived, this is typically - // used to re-apply writes such as from slide info. - void RegisterReviveCallback(const ReviveCallback& callback) { - m_reviveCallback = callback; - } - - std::shared_ptr lock(); -}; -- cgit v1.3.1