mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-20 04:03:57 +00:00
Implement guard pages (#406)
Hey, looking for feedback on my guard page implementation. I wasn't sure on how to structure the additional windows specific memory flags, since the emulation backends won't like additional guard flag. I opted to create a new `memory_permission_ext` enum to hold the guard flag, and a `nt_memory_permission` struct to wrap the "common" memory permission flags, with the new extended flags. This struct implicitly coerces to the original `memory_permission` to reduce the amount of changes for the PR. This however meant that I changed signatures of `map_memory` and `apply_memory_protection` in `memory_interface` to accommodate this new structure, and was an afterthought. The `map_nt_to_emulator_protection` function might also need some attention now, too. For future reference, windows uses [MiMakeProtectionMask](https://doxygen.reactos.org/d1/d9a/marea_8c.html#adfb66408771a4df77c1056cc2a99ef21) in ntoskrnl to map `PAGE_*` flags to [MM PTE constants](https://reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel). The test added to the `test-sample` binary seems to be passing. Fixes #21
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "memory_region.hpp"
|
||||
#include "address_utils.hpp"
|
||||
#include "memory_permission_ext.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
@@ -73,7 +74,7 @@ namespace utils
|
||||
static void deserialize(buffer_deserializer& buffer, memory_manager::committed_region& region)
|
||||
{
|
||||
region.length = static_cast<size_t>(buffer.read<uint64_t>());
|
||||
region.permissions = buffer.read<memory_permission>();
|
||||
region.permissions = buffer.read<nt_memory_permission>();
|
||||
}
|
||||
|
||||
static void serialize(buffer_serializer& buffer, const memory_manager::reserved_region& region)
|
||||
@@ -189,8 +190,8 @@ void memory_manager::deserialize_memory_state(utils::buffer_deserializer& buffer
|
||||
}
|
||||
}
|
||||
|
||||
bool memory_manager::protect_memory(const uint64_t address, const size_t size, const memory_permission permissions,
|
||||
memory_permission* old_permissions)
|
||||
bool memory_manager::protect_memory(const uint64_t address, const size_t size, const nt_memory_permission permissions,
|
||||
nt_memory_permission* old_permissions)
|
||||
{
|
||||
const auto entry = this->find_reserved_region(address);
|
||||
if (entry == this->reserved_regions_.end())
|
||||
@@ -268,7 +269,7 @@ bool memory_manager::allocate_mmio(const uint64_t address, const size_t size, mm
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_manager::allocate_memory(const uint64_t address, const size_t size, const memory_permission permissions,
|
||||
bool memory_manager::allocate_memory(const uint64_t address, const size_t size, const nt_memory_permission permissions,
|
||||
const bool reserve_only)
|
||||
{
|
||||
if (this->overlaps_reserved_region(address, size))
|
||||
@@ -286,8 +287,9 @@ bool memory_manager::allocate_memory(const uint64_t address, const size_t size,
|
||||
|
||||
if (!reserve_only)
|
||||
{
|
||||
this->map_memory(address, size, permissions);
|
||||
entry->second.committed_regions[address] = committed_region{size, memory_permission::read_write};
|
||||
this->map_memory(address, size, permissions.is_guarded() ? memory_permission::none : permissions.common);
|
||||
entry->second.committed_regions[address] =
|
||||
committed_region{size, nt_memory_permission{memory_permission::read_write, permissions.extended}};
|
||||
}
|
||||
|
||||
this->update_layout_version();
|
||||
@@ -295,7 +297,7 @@ bool memory_manager::allocate_memory(const uint64_t address, const size_t size,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_manager::commit_memory(const uint64_t address, const size_t size, const memory_permission permissions)
|
||||
bool memory_manager::commit_memory(const uint64_t address, const size_t size, const nt_memory_permission permissions)
|
||||
{
|
||||
const auto entry = this->find_reserved_region(address);
|
||||
if (entry == this->reserved_regions_.end())
|
||||
@@ -473,7 +475,7 @@ void memory_manager::unmap_all_memory()
|
||||
this->reserved_regions_.clear();
|
||||
}
|
||||
|
||||
uint64_t memory_manager::allocate_memory(const size_t size, const memory_permission permissions,
|
||||
uint64_t memory_manager::allocate_memory(const size_t size, const nt_memory_permission permissions,
|
||||
const bool reserve_only)
|
||||
{
|
||||
const auto allocation_base = this->find_free_allocation_base(size);
|
||||
@@ -519,8 +521,8 @@ region_info memory_manager::get_region_info(const uint64_t address)
|
||||
region_info result{};
|
||||
result.start = MIN_ALLOCATION_ADDRESS;
|
||||
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
|
||||
result.permissions = memory_permission::none;
|
||||
result.initial_permissions = memory_permission::none;
|
||||
result.permissions = nt_memory_permission();
|
||||
result.initial_permissions = nt_memory_permission();
|
||||
result.allocation_base = {};
|
||||
result.allocation_length = result.length;
|
||||
result.is_committed = false;
|
||||
|
||||
Reference in New Issue
Block a user