diff options
| author | Mark Rowe <mark@vector35.com> | 2026-02-23 23:26:27 -0800 |
|---|---|---|
| committer | Mark Rowe <mark@vector35.com> | 2026-02-24 14:24:54 -0800 |
| commit | a72b98ed5a357bb380d81f07f3f36946aa729bb2 (patch) | |
| tree | ca48b3607721fa2c109b7989ae4b911bab89ea6d /view/sharedcache/core/FileAccessorCache.h | |
| parent | 3eda43f185a0411538745a99e251122e6a9192e0 (diff) | |
[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`.
Diffstat (limited to 'view/sharedcache/core/FileAccessorCache.h')
| -rw-r--r-- | view/sharedcache/core/FileAccessorCache.h | 76 |
1 files changed, 0 insertions, 76 deletions
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 <shared_mutex> - -#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<CacheAccessorID> m_cache; - std::unordered_map<CacheAccessorID, std::shared_ptr<MappedFileAccessor>> 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<void(MappedFileAccessor&)>; - - // Weak pointer to the mapped file accessor, once this is expired we will re-open. - std::weak_ptr<MappedFileAccessor> 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<ReviveCallback> 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<MappedFileAccessor> 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<MappedFileAccessor> lock(); -}; |
