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/MappedFileAccessor.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/MappedFileAccessor.h')
| -rw-r--r-- | view/sharedcache/core/MappedFileAccessor.h | 103 |
1 files changed, 0 insertions, 103 deletions
diff --git a/view/sharedcache/core/MappedFileAccessor.h b/view/sharedcache/core/MappedFileAccessor.h deleted file mode 100644 index 35d2d5e7..00000000 --- a/view/sharedcache/core/MappedFileAccessor.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include "binaryninjaapi.h" -#include "MappedFile.h" - -#include <cstdint> -#include <list> - -class UnmappedAccessException : public std::exception -{ - uint64_t m_address; - uint64_t m_fileLen; - -public: - explicit UnmappedAccessException(uint64_t address, uint64_t fileLength) : m_address(address), m_fileLen(fileLength) - {} - - virtual const char* what() const throw() - { - thread_local std::string message; - message = - fmt::format("Tried to access unmapped address {0:x} for file with length of {1:x}", m_address, m_fileLen); - return message.c_str(); - } -}; - -// std::enable_shared_from_this allows weak pointers to "revive" the shared pointer in the FileAccessorCache. -class MappedFileAccessor : public std::enable_shared_from_this<MappedFileAccessor> -{ - MappedFile m_file; - bool m_dirty = false; - -public: - explicit MappedFileAccessor(MappedFile file) : m_file(std::move(file)) {} - - ~MappedFileAccessor() = default; - - MappedFileAccessor(const MappedFileAccessor&) = delete; - - MappedFileAccessor& operator=(const MappedFileAccessor&) = delete; - - MappedFileAccessor(MappedFileAccessor&&) noexcept = default; - - MappedFileAccessor& operator=(MappedFileAccessor&&) noexcept = default; - - static std::shared_ptr<MappedFileAccessor> Open(const std::string& filePath); - - size_t Length() const { return m_file.len; }; - - void* Data() const { return m_file._mmap; }; - - bool IsDirty() const { return m_dirty; } - - /** - * Writes to files are implemented for performance reasons and should be treated with utmost care - * - * They _MAY_ disappear as _soon_ as you release the lock on the file. - * They may also NOT disappear for the lifetime of the application. - * - * The former is more likely to occur when concurrent DSC processing is happening. The latter is the typical - * scenario. - * - * This is used explicitly for slide information in a locked scope and _NOTHING_ else. It should probably not be - * used for anything else. - * - * \param address The address to write the pointer to - * \param pointer The pointer to be written - */ - void WritePointer(size_t address, size_t pointer); - - std::string ReadNullTermString(size_t address, size_t maxLength = -1) const; - - uint8_t ReadUInt8(size_t address) const; - - int8_t ReadInt8(size_t address) const; - - uint16_t ReadUInt16(size_t address) const; - - int16_t ReadInt16(size_t address) const; - - uint32_t ReadUInt32(size_t address) const; - - int32_t ReadInt32(size_t address) const; - - uint64_t ReadUInt64(size_t address) const; - - int64_t ReadInt64(size_t address) const; - - BinaryNinja::DataBuffer ReadBuffer(size_t addr, size_t length) const; - - // Returns a range of pointers within the mapped memory region corresponding to - // {addr, length}. - // WARNING: The pointers returned by this method is only valid for the lifetime - // of this file accessor. - // TODO: This should use std::span<const uint8_t> once the minimum supported - // C++ version supports it. - std::pair<const uint8_t*, const uint8_t*> ReadSpan(size_t addr, size_t length); - - void Read(void* dest, size_t addr, size_t length) const; - - template <typename T> - T Read(size_t address) const; -}; |
