rpcsx/rx/src/Mappable.cpp
DH 390dadf78e
Some checks failed
Formatting check / formatting-check (push) Has been cancelled
Build RPCSX / build-linux (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv8-a) (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv8.1-a) (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv8.2-a) (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv8.4-a) (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv8.5-a) (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv9-a) (push) Has been cancelled
Build RPCSX / build-android (arm64-v8a, armv9.1-a) (push) Has been cancelled
Build RPCSX / build-android (x86_64, x86-64) (push) Has been cancelled
fix android build
2025-10-17 02:43:13 +03:00

146 lines
3.4 KiB
C++

#include "Mappable.hpp"
#include "mem.hpp"
#include <system_error>
#ifndef _WIN32
#include <cerrno>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#else
#include <cstdint>
#define NTDDI_VERSION NTDDI_WIN10_NI
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#ifdef ANDROID
#include <sys/syscall.h>
static int memfd_create(const char *name, uint flags) {
// FIXME: requires modern android
return syscall(__NR_memfd_create, name, flags);
}
#endif
std::pair<rx::Mappable, std::errc>
rx::Mappable::CreateMemory(std::size_t size) {
rx::Mappable result;
#ifdef _WIN32
auto handle = CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr,
FILE_MAP_ALL_ACCESS, PAGE_EXECUTE_READWRITE,
SEC_COMMIT, size, nullptr, nullptr, 0);
if (!handle) {
return {rx::Mappable{}, std::errc::invalid_argument};
}
result.m_handle = handle;
#else
auto fd = ::memfd_create("", 0);
if (fd < 0) {
return {{}, std::errc{errno}};
}
result.m_handle = fd;
if (::ftruncate(fd, size) < 0) {
return {{}, std::errc{errno}};
}
#endif
return {std::move(result), std::errc{}};
}
std::pair<rx::Mappable, std::errc> rx::Mappable::CreateSwap(std::size_t size) {
#ifdef _WIN32
return CreateMemory(size);
#else
char temp_filename[] = "./.rx-swap-XXXXXXXXXXX";
int fd = ::mkstemp(temp_filename);
if (fd < 0) {
return {{}, std::errc{errno}};
}
::unlink(temp_filename);
rx::Mappable result;
result.m_handle = fd;
if (::ftruncate(fd, size) < 0) {
return {{}, std::errc{errno}};
}
return {std::move(result), {}};
#endif
}
std::errc rx::Mappable::map(rx::AddressRange virtualRange, std::size_t offset,
rx::EnumBitSet<mem::Protection> protection,
[[maybe_unused]] std::size_t alignment) {
#ifdef _WIN32
static const DWORD protTable[] = {
PAGE_NOACCESS, // 0
PAGE_READONLY, // R
PAGE_EXECUTE_READWRITE, // W
PAGE_EXECUTE_READWRITE, // RW
PAGE_EXECUTE, // X
PAGE_EXECUTE_READWRITE, // XR
PAGE_EXECUTE_READWRITE, // XW
PAGE_EXECUTE_READWRITE, // XRW
};
auto prot = protTable[(protection & (mem::Protection::R | mem::Protection::W |
mem::Protection::X))
.toUnderlying()];
mem::release(virtualRange, alignment);
for (std::uintptr_t address = virtualRange.beginAddress();
address < virtualRange.endAddress();
address += alignment, offset += alignment) {
auto pointer = std::bit_cast<void *>(address);
auto result =
MapViewOfFile3((HANDLE)m_handle, nullptr, pointer, offset, alignment,
MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
if (!result) {
return std::errc::invalid_argument;
}
}
#else
int prot = 0;
if (protection & mem::Protection::R) {
prot |= PROT_READ;
}
if (protection & mem::Protection::W) {
prot |= PROT_READ | PROT_WRITE;
}
if (protection & mem::Protection::X) {
prot |= PROT_EXEC;
}
auto address = std::bit_cast<void *>(virtualRange.beginAddress());
auto result = ::mmap(address, virtualRange.size(), prot,
MAP_SHARED | MAP_FIXED, m_handle, offset);
if (result == MAP_FAILED) {
return std::errc{errno};
}
#endif
return {};
}
void rx::Mappable::destroy() {
#ifdef _WIN32
CloseHandle((HANDLE)m_handle);
#else
::close(m_handle);
#endif
}