mirror of
https://github.com/ApfelTeeSaft/ps4-fortniteserver.git
synced 2026-08-26 19:33:25 +00:00
67 lines
2.2 KiB
C++
67 lines
2.2 KiB
C++
// OrbisHookah, Copyright @2026 apfelteesaft
|
|
|
|
#include "memory.h"
|
|
|
|
#include <sys/mman.h> // mmap, munmap, mprotect, MAP_ANON, MAP_PRIVATE, PROT_*
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
namespace Hookah {
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Internal helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Round 'addr' down to the nearest PS4 page boundary.
|
|
static inline uintptr_t PageFloor(uintptr_t addr) {
|
|
return addr & ~(kPageSize - 1u);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Public API
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void* AllocateExecutable(size_t size) {
|
|
// MAP_ANON is the BSD name for MAP_ANONYMOUS; both are 0x1000 on FreeBSD.
|
|
// Combining PROT_WRITE + PROT_EXEC is required so we can write the
|
|
// trampoline bytes and then execute them without a second mprotect call.
|
|
void* mem = mmap(nullptr, size,
|
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
|
|
// mmap returns MAP_FAILED ((void*)-1) on error, not nullptr.
|
|
if (mem == reinterpret_cast<void*>(-1))
|
|
return nullptr;
|
|
|
|
return mem;
|
|
}
|
|
|
|
void FreeExecutable(void* addr, size_t size) {
|
|
if (addr && addr != reinterpret_cast<void*>(-1))
|
|
munmap(addr, size);
|
|
}
|
|
|
|
bool ProtectMemory(void* address, size_t size, int prot) {
|
|
// mprotect requires that the start address be page-aligned on PS4.
|
|
uintptr_t raw = reinterpret_cast<uintptr_t>(address);
|
|
uintptr_t aligned = PageFloor(raw);
|
|
size_t span = size + (raw - aligned); // cover the full original range
|
|
|
|
return mprotect(reinterpret_cast<void*>(aligned), span, prot) == 0;
|
|
}
|
|
|
|
bool SafeWrite(void* dst, const void* src, size_t size) {
|
|
// Temporarily open the target page for writing.
|
|
if (!ProtectMemory(dst, size, PROT_READ | PROT_WRITE | PROT_EXEC))
|
|
return false;
|
|
|
|
memcpy(dst, src, size);
|
|
|
|
// Restore to read+execute; the page no longer needs to be writable at
|
|
// runtime (only the trampoline buffer stays RWX after allocation).
|
|
ProtectMemory(dst, size, PROT_READ | PROT_EXEC);
|
|
return true;
|
|
}
|
|
|
|
} // namespace Hookah
|