summaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.org>2025-03-27 23:25:24 +1000
committerMike Lothian <mike@fireburn.co.uk>2025-05-12 12:46:19 +0100
commit79c7213e9f6173750b836997e78a4ddf3a10fead (patch)
tree49e5fa72e91e1b506bc611277b832ef24fa15b74 /src/core/memory.cpp
parent898ef9d51113e2b77dbe32e74dc215926399878e (diff)
memory: Implement enhanced memory management system
Add a flexible memory region management system that provides: - Memory region type classification (System, Graphics, IO, Binary) - Memory region permission management (executable, writable) - Binary base address randomization for ASLR - Dynamic memory mapping capabilities Credit: boss.smc@citron-emu.org Signed-off-by: Zephyron <zephyron@citron-emu.org>
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp49
1 files changed, 48 insertions, 1 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index abb2ce314..0b249ff0c 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -1,5 +1,6 @@
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
+// SPDX-FileCopyrightText: 2025 Citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
@@ -909,7 +910,9 @@ struct Memory::Impl {
#endif
};
-Memory::Memory(Core::System& system_) : system{system_} {
+Memory::Memory(Core::System& system_) : system(system_), impl(std::make_unique<Impl>(system_)), gen(rd()) {
+ // Initialize the random number distribution
+ dis = std::uniform_int_distribution<u64>(0, std::numeric_limits<u64>::max());
Reset();
}
@@ -1151,4 +1154,48 @@ bool Memory::InvalidateSeparateHeap(void* fault_address) {
#endif
}
+Common::ProcessAddress Memory::GenerateRandomBaseAddress() {
+ u64 random_bits = dis(gen);
+ return Common::ProcessAddress((random_bits & ~NRO_BASE_ADDRESS_RANDOMIZATION_MASK) |
+ (random_bits & NRO_BASE_ADDRESS_RANDOMIZATION_MASK));
+}
+
+Memory::MemoryRegion* Memory::FindRegion(Common::ProcessAddress address) {
+ for (auto& entry : memory_regions) {
+ if (address >= entry.second.start_address &&
+ address < entry.second.start_address + entry.second.size) {
+ return &entry.second;
+ }
+ }
+ return nullptr;
+}
+
+void Memory::MapMemoryRegion(Common::ProcessAddress start_address, u64 size, MemoryRegionType type,
+ bool exec, bool write) {
+ if (start_address + size > EMULATED_MEMORY_SIZE) {
+ LOG_ERROR(HW_Memory, "Memory mapping exceeds emulated memory boundaries at address {:016X}",
+ GetInteger(start_address));
+ return;
+ }
+
+ // Create the memory region
+ memory_regions[start_address] = MemoryRegion(start_address, size, type, exec, write);
+
+ // Map the region in the page table
+ Common::MemoryPermission perms{};
+ if (exec) perms |= Common::MemoryPermission::Execute;
+ if (write) perms |= Common::MemoryPermission::Write;
+ perms |= Common::MemoryPermission::Read;
+
+ // Using the MapMemoryRegion method defined in the Impl struct
+ impl->MapMemoryRegion(*impl->current_page_table, start_address, size,
+ Common::PhysicalAddress(GetInteger(start_address)), perms, false);
+}
+
+Common::ProcessAddress Memory::MapBinary(u64 size) {
+ Common::ProcessAddress base_address = GenerateRandomBaseAddress();
+ MapMemoryRegion(base_address, size, MemoryRegionType::BinaryMemory, true, true);
+ return base_address;
+}
+
} // namespace Core::Memory