summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/MappedFileAccessor.h
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-03-10 11:05:40 -0400
committerMason Reed <mason@vector35.com>2025-04-02 05:36:54 -0400
commit25cc02431b61097b2adfc2fbc493b648b0300c3b (patch)
treea79d9c4f4f67234d3bf9bda413e8608f479a4cc8 /view/sharedcache/core/MappedFileAccessor.h
parentfa85bf28502286c4821427c5d0ed91a7ed46f8f6 (diff)
[SharedCache] Refactor Shared Cache
In absence of a better name, this commit refactors the shared cache code.
Diffstat (limited to 'view/sharedcache/core/MappedFileAccessor.h')
-rw-r--r--view/sharedcache/core/MappedFileAccessor.h103
1 files changed, 103 insertions, 0 deletions
diff --git a/view/sharedcache/core/MappedFileAccessor.h b/view/sharedcache/core/MappedFileAccessor.h
new file mode 100644
index 00000000..7b01cb0d
--- /dev/null
+++ b/view/sharedcache/core/MappedFileAccessor.h
@@ -0,0 +1,103 @@
+#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 {0: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);
+
+ int8_t ReadInt8(size_t address);
+
+ uint16_t ReadUInt16(size_t address);
+
+ int16_t ReadInt16(size_t address);
+
+ uint32_t ReadUInt32(size_t address);
+
+ int32_t ReadInt32(size_t address);
+
+ uint64_t ReadUInt64(size_t address);
+
+ int64_t ReadInt64(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<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);
+};