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/MappedFileAccessor.cpp | 111 --------------------------- 1 file changed, 111 deletions(-) delete mode 100644 view/sharedcache/core/MappedFileAccessor.cpp (limited to 'view/sharedcache/core/MappedFileAccessor.cpp') diff --git a/view/sharedcache/core/MappedFileAccessor.cpp b/view/sharedcache/core/MappedFileAccessor.cpp deleted file mode 100644 index 4f9f99a8..00000000 --- a/view/sharedcache/core/MappedFileAccessor.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "MappedFileAccessor.h" - -std::shared_ptr MappedFileAccessor::Open(const std::string& filePath) -{ - auto file = MappedFile::OpenFile(filePath); - if (!file.has_value()) - return nullptr; - if (file->Map() != MapStatus::Success) - return nullptr; - return std::make_shared(std::move(*file)); -} - -// TODO: Will obviously not work on 32bit binaries, need to make WritePointer64 and 32 equiv. -void MappedFileAccessor::WritePointer(size_t address, size_t pointer) -{ - if (address + sizeof(size_t*) > Length()) - throw UnmappedAccessException(address + sizeof(size_t*), Length()); - m_dirty = true; - *reinterpret_cast(&m_file._mmap[address]) = pointer; -} - -std::string MappedFileAccessor::ReadNullTermString(size_t address, const size_t maxLength) const -{ - if (address > Length()) - return ""; - // If we are not given a maxLength (i.e. -1) than we will set the max address to the length of the file. - const size_t maxAddr = (maxLength != -1) ? std::min(address + maxLength, Length()) : Length(); - // Read a null-terminated string manually to avoid errors related to string length on Linux. - std::string str; - str.reserve(140); - for (size_t currAddr = address; currAddr < maxAddr; ++currAddr) - { - char c = m_file._mmap[currAddr]; - if (c == '\0') - break; - str += c; - } - str.shrink_to_fit(); - return str; -} - -uint8_t MappedFileAccessor::ReadUInt8(size_t address) const -{ - return Read(address); -} - -int8_t MappedFileAccessor::ReadInt8(size_t address) const -{ - return Read(address); -} - -uint16_t MappedFileAccessor::ReadUInt16(size_t address) const -{ - return Read(address); -} - -int16_t MappedFileAccessor::ReadInt16(size_t address) const -{ - return Read(address); -} - - -uint32_t MappedFileAccessor::ReadUInt32(size_t address) const -{ - return Read(address); -} - -int32_t MappedFileAccessor::ReadInt32(size_t address) const -{ - return Read(address); -} - -uint64_t MappedFileAccessor::ReadUInt64(size_t address) const -{ - return Read(address); -} - -int64_t MappedFileAccessor::ReadInt64(size_t address) const -{ - return Read(address); -} - -BinaryNinja::DataBuffer MappedFileAccessor::ReadBuffer(size_t addr, size_t length) const -{ - if (addr + length > Length()) - throw UnmappedAccessException(addr + length, Length()); - return {&m_file._mmap[addr], length}; -} - -std::pair MappedFileAccessor::ReadSpan(size_t addr, size_t length) -{ - if (addr + length > Length()) - throw UnmappedAccessException(addr + length, Length()); - const uint8_t* data = &m_file._mmap[addr]; - return {data, data + length}; -} - -void MappedFileAccessor::Read(void* dest, size_t addr, size_t length) const -{ - if (addr + length > Length()) - throw UnmappedAccessException(addr + length, Length()); - memcpy(dest, &m_file._mmap[addr], length); -} - -template -T MappedFileAccessor::Read(size_t address) const -{ - T result; - Read(&result, address, sizeof(T)); - return result; -} -- cgit v1.3.1