summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/VirtualMemory.h
diff options
context:
space:
mode:
authorMark Rowe <mark@vector35.com>2026-02-23 23:26:27 -0800
committerMark Rowe <mark@vector35.com>2026-02-24 14:24:54 -0800
commita72b98ed5a357bb380d81f07f3f36946aa729bb2 (patch)
treeca48b3607721fa2c109b7989ae4b911bab89ea6d /view/sharedcache/core/VirtualMemory.h
parent3eda43f185a0411538745a99e251122e6a9192e0 (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.h65
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);