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/VirtualMemory.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/VirtualMemory.h')
| -rw-r--r-- | view/sharedcache/core/VirtualMemory.h | 65 |
1 files changed, 21 insertions, 44 deletions
diff --git a/view/sharedcache/core/VirtualMemory.h b/view/sharedcache/core/VirtualMemory.h index a490fa24..0cd23a4c 100644 --- a/view/sharedcache/core/VirtualMemory.h +++ b/view/sharedcache/core/VirtualMemory.h @@ -1,6 +1,5 @@ #pragma once -#include "FileAccessorCache.h" -#include "MappedFileAccessor.h" +#include "MappedFileRegion.h" #include "Utility.h" class UnmappedRegionException : public std::exception @@ -22,21 +21,10 @@ public: struct VirtualMemoryRegion { uint64_t fileOffset; - // Access the memory regions contents through this. - // NOTE: Any read through this should be seeked to `fileOffset` - WeakFileAccessor fileAccessor; + std::shared_ptr<MappedFileRegion> file; - VirtualMemoryRegion(uint64_t offset, WeakFileAccessor accessor) - : fileOffset(offset), fileAccessor(std::move(accessor)) {} - - - VirtualMemoryRegion(const VirtualMemoryRegion&) = default; - - VirtualMemoryRegion& operator=(const VirtualMemoryRegion&) = default; - - VirtualMemoryRegion(VirtualMemoryRegion&&) = default; - - VirtualMemoryRegion& operator=(VirtualMemoryRegion&&) = default; + VirtualMemoryRegion(uint64_t offset, std::shared_ptr<MappedFileRegion> f) + : fileOffset(offset), file(std::move(f)) {} }; // Contains information to handle mapping of multiple mapped files into a single memory space. @@ -44,7 +32,6 @@ struct VirtualMemoryRegion // and map them into Binary Ninja. class VirtualMemory { - std::shared_mutex m_regionMutex; AddressRangeMap<VirtualMemoryRegion> m_regions; uint64_t m_addressSize = 8; @@ -53,45 +40,39 @@ public: uint64_t GetAddressSize() const { return m_addressSize; } - // At no point do we ever store a strong pointer to a file accessor, that is the job of the `FileAccessorCache`. - void MapRegion(WeakFileAccessor fileAccessor, AddressRange mappedRange, uint64_t fileOffset); + void MapRegion(std::shared_ptr<MappedFileRegion> file, AddressRange mappedRange, uint64_t fileOffset); - // Returns the region in virtual memory, along with the offset into that region where the address is located. - // Using the regions file accessor and the address offset you can read a regions content. - std::optional<VirtualMemoryRegion> GetRegionAtAddress(uint64_t address, uint64_t& addressOffset); + const VirtualMemoryRegion* FindRegionAtAddress(uint64_t address, uint64_t& addressOffset) const; - std::optional<VirtualMemoryRegion> GetRegionAtAddress(uint64_t address); + const VirtualMemoryRegion* FindRegionAtAddress(uint64_t address) const; - bool IsAddressMapped(uint64_t address); + bool IsAddressMapped(uint64_t address) const; - // Write a pointer at a given address. This pointer is never persisted when a file accessor is closed. - void WritePointer(uint64_t address, size_t pointer); + uint64_t ReadPointer(uint64_t address) const; - uint64_t ReadPointer(uint64_t address); + std::string ReadCString(uint64_t address) const; - std::string ReadCString(uint64_t address); + uint8_t ReadUInt8(uint64_t address) const; - uint8_t ReadUInt8(uint64_t address); + int8_t ReadInt8(uint64_t address) const; - int8_t ReadInt8(uint64_t address); + uint16_t ReadUInt16(uint64_t address) const; - uint16_t ReadUInt16(uint64_t address); + int16_t ReadInt16(uint64_t address) const; - int16_t ReadInt16(uint64_t address); + uint32_t ReadUInt32(uint64_t address) const; - uint32_t ReadUInt32(uint64_t address); + int32_t ReadInt32(uint64_t address) const; - int32_t ReadInt32(uint64_t address); + uint64_t ReadUInt64(uint64_t address) const; - uint64_t ReadUInt64(uint64_t address); + int64_t ReadInt64(uint64_t address) const; - int64_t ReadInt64(uint64_t address); + BinaryNinja::DataBuffer ReadBuffer(uint64_t address, size_t length) const; - BinaryNinja::DataBuffer ReadBuffer(uint64_t address, size_t length); + std::span<const uint8_t> ReadSpan(uint64_t address, size_t length) const; - std::pair<const uint8_t*, const uint8_t*> ReadSpan(uint64_t address, size_t length); - - void Read(void* dest, uint64_t address, size_t length); + void Read(void* dest, uint64_t address, size_t length) const; }; class VirtualMemoryReader @@ -115,10 +96,6 @@ public: std::string ReadCString(uint64_t address, size_t maxLength = -1); - uint64_t ReadULEB128(size_t cursorLimit); - - int64_t ReadSLEB128(size_t cursorLimit); - uint64_t ReadPointer(); uint64_t ReadPointer(uint64_t address); |
