From 25cc02431b61097b2adfc2fbc493b648b0300c3b Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Mon, 10 Mar 2025 11:05:40 -0400 Subject: [SharedCache] Refactor Shared Cache In absence of a better name, this commit refactors the shared cache code. --- view/sharedcache/core/VM.h | 368 --------------------------------------------- 1 file changed, 368 deletions(-) delete mode 100644 view/sharedcache/core/VM.h (limited to 'view/sharedcache/core/VM.h') diff --git a/view/sharedcache/core/VM.h b/view/sharedcache/core/VM.h deleted file mode 100644 index e245751a..00000000 --- a/view/sharedcache/core/VM.h +++ /dev/null @@ -1,368 +0,0 @@ -// -// Created by kat on 5/23/23. -// - -#ifndef SHAREDCACHE_VM_H -#define SHAREDCACHE_VM_H - -#include - -#include -#include -#include - -void VMShutdown(); - -std::string ResolveFilePath(BinaryNinja::Ref dscView, const std::string& path); - -template -class SelfAllocatingWeakPtr { -public: - SelfAllocatingWeakPtr(std::function()> allocator) : allocator(allocator) {} - - std::shared_ptr lock() { - std::shared_ptr sharedPtr = weakPtr.lock(); - if (!sharedPtr) { - sharedPtr = allocator(); - weakPtr = sharedPtr; - } - return sharedPtr; - } - - std::shared_ptr lock_no_allocate() { - return weakPtr.lock(); - } - -private: - std::weak_ptr weakPtr; // Weak reference to the object - std::function()> allocator; // Function to recreate the object -}; - - -class MissingFileException : public std::exception -{ - virtual const char* what() const throw() - { - return "Missing File."; - } -}; - -class MMappedFileAccessor; - -class MMAP { - friend MMappedFileAccessor; - - uint8_t *_mmap; - FILE *fd; - size_t len; - -#ifdef _MSC_VER - HANDLE hFile = INVALID_HANDLE_VALUE; // For Windows -#endif - - bool mapped = false; - - void Map(); - - void Unmap(); -}; - -class LazyMappedFileAccessor : public SelfAllocatingWeakPtr { -public: - LazyMappedFileAccessor( - std::string filePath, std::function(const std::string&)> allocator) : - SelfAllocatingWeakPtr([this, allocator = std::move(allocator)] { return allocator(m_filePath); }), - m_filePath(std::move(filePath)) - {} - ~LazyMappedFileAccessor() = default; - - std::string_view filePath() const { return m_filePath; } - -private: - std::string m_filePath; -}; - -uint64_t MMapCount(); - -class MMappedFileAccessor { - std::string m_path; - MMAP m_mmap; - bool m_slideInfoWasApplied = false; - -public: - MMappedFileAccessor(const std::string &path); - ~MMappedFileAccessor(); - - static std::shared_ptr Open(const uint64_t sessionID, const std::string &path, std::function)> postAllocationRoutine = nullptr); - - static void CloseAll(const uint64_t sessionID); - - static void InitialVMSetup(); - - const std::string& Path() const { return m_path; }; - - size_t Length() const { return m_mmap.len; }; - - void *Data() const { return m_mmap._mmap; }; - - bool SlideInfoWasApplied() const { return m_slideInfoWasApplied; } - - void SetSlideInfoWasApplied(bool slideInfoWasApplied) { m_slideInfoWasApplied = slideInfoWasApplied; } - - /** - * 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 this 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 - * \param pointer - */ - void WritePointer(size_t address, size_t pointer); - - std::string ReadNullTermString(size_t address); - - uint8_t ReadUChar(size_t address); - - int8_t ReadChar(size_t address); - - uint16_t ReadUShort(size_t address); - - int16_t ReadShort(size_t address); - - uint32_t ReadUInt32(size_t address); - - int32_t ReadInt32(size_t address); - - uint64_t ReadULong(size_t address); - - int64_t ReadLong(size_t address); - - BinaryNinja::DataBuffer ReadBuffer(size_t addr, size_t length); - - // 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 once the minimum supported - // C++ version supports it. - std::pair ReadSpan(size_t addr, size_t length); - - void Read(void *dest, size_t addr, size_t length); - - template - T Read(size_t address); -}; - -class FileAccessorCache -{ -public: - static FileAccessorCache& Shared(); - - std::shared_ptr OpenLazily( - const uint64_t sessionID, const std::string& path, - std::function)> postAllocationRoutine); - - void SetCacheSize(uint64_t size); - -private: - FileAccessorCache(); - - std::shared_ptr Open( - const uint64_t sessionID, const std::string& path); - - void Close(MMappedFileAccessor* accessor); - - void RecordAccess(const std::string& path); - void EvictFromCacheIfNeeded(); - - std::mutex m_mutex; - std::unordered_map> m_lazyAccessors; - - // Ordered from least recently opened (front) to most recently opened (end). - std::list m_leastRecentlyOpened; - std::unordered_map, std::list::iterator>> - m_accessors; - - uint64_t m_cacheSize = 8; -}; - -struct PageMapping { - std::shared_ptr fileAccessor; - size_t fileOffset; - PageMapping(std::shared_ptr fileAccessor, size_t fileOffset) - : fileAccessor(std::move(fileAccessor)), fileOffset(fileOffset) {} -}; - - -class VMException : public std::exception { - virtual const char *what() const throw() { - return "Generic VM Exception"; - } -}; - -class MappingPageAlignmentException : public VMException { - virtual const char *what() const throw() { - return "Tried to create a mapping not aligned to given page size"; - } -}; - -class MappingReadException : VMException { - virtual const char *what() const throw() { - return "Tried to access unmapped page"; - } -}; - -class MappingCollisionException : VMException { - virtual const char *what() const throw() { - return "Tried to remap a page"; - } -}; - -class VMReader; - -// Represents a range of addresses [start, end). -// Note that `end` is not included within the range. -struct AddressRange { - uint64_t start; - uint64_t end; - - bool operator<(const AddressRange& b) const { - return start < b.start || (start == b.start && end < b.end); - } - - friend bool operator<(const AddressRange& range, uint64_t address) { - return range.end <= address; - } - - friend bool operator<(uint64_t address, const AddressRange& range) { - return address < range.start; - } -}; - -// A map keyed by address ranges that can be looked up via any -// address within a range thanks to C++14's transparent comparators. -template -using AddressRangeMap = std::map>; - -class VM { - // A map keyed by address ranges that can be looked up via any - // address within a range thanks to C++14's transparent comparators. - AddressRangeMap m_map; - size_t m_pageSize; - bool m_safe; - - friend VMReader; - -public: - - VM(size_t pageSize, bool safe = true); - - ~VM(); - - void MapPages(BinaryNinja::Ref dscView, uint64_t sessionID, size_t vm_address, size_t fileoff, size_t size, const std::string& filePath, std::function)> postAllocationRoutine); - - bool AddressIsMapped(uint64_t address); - - std::pair MappingAtAddress(size_t address); - - std::string ReadNullTermString(size_t address); - - uint8_t ReadUChar(size_t address); - - int8_t ReadChar(size_t address); - - uint16_t ReadUShort(size_t address); - - int16_t ReadShort(size_t address); - - uint32_t ReadUInt32(size_t address); - - int32_t ReadInt32(size_t address); - - uint64_t ReadULong(size_t address); - - int64_t ReadLong(size_t address); - - BinaryNinja::DataBuffer ReadBuffer(size_t addr, size_t length); - - void Read(void *dest, size_t addr, size_t length); -}; - - -class VMReader { - std::shared_ptr m_vm; - size_t m_cursor; - size_t m_addressSize; - - BNEndianness m_endianness = LittleEndian; - -public: - VMReader(std::shared_ptr vm, size_t addressSize = 8); - - void SetEndianness(BNEndianness endianness) { m_endianness = endianness; } - - BNEndianness GetEndianness() const { return m_endianness; } - - void Seek(size_t address); - - void SeekRelative(size_t offset); - - [[nodiscard]] size_t GetOffset() const { return m_cursor; } - - std::string ReadCString(size_t address); - - uint64_t ReadULEB128(size_t cursorLimit); - - int64_t ReadSLEB128(size_t cursorLimit); - - uint8_t Read8(); - - int8_t ReadS8(); - - uint16_t Read16(); - - int16_t ReadS16(); - - uint32_t Read32(); - - int32_t ReadS32(); - - uint64_t Read64(); - - int64_t ReadS64(); - - size_t ReadPointer(); - - uint8_t ReadUChar(size_t address); - - int8_t ReadChar(size_t address); - - uint16_t ReadUShort(size_t address); - - int16_t ReadShort(size_t address); - - uint32_t ReadUInt32(size_t address); - - int32_t ReadInt32(size_t address); - - uint64_t ReadULong(size_t address); - - int64_t ReadLong(size_t address); - - size_t ReadPointer(size_t address); - - BinaryNinja::DataBuffer ReadBuffer(size_t length); - - BinaryNinja::DataBuffer ReadBuffer(size_t addr, size_t length); - - void Read(void *dest, size_t length); - - void Read(void *dest, size_t addr, size_t length); -}; - -#endif //SHAREDCACHE_VM_H -- cgit v1.3.1