Files
ppsspp/Common/MemArena.h
T
Henrik RydgårdandClaude Opus 5.5 8e2bb1faed 32-bit: Keep the memory view range reserved, and mask guest addresses to it
Find4GBBase found 256 MB of free address space for the views and then
unmapped it, so the gaps between the views went back to the system. On a
32-bit Android device, a running game had malloc heaps between VRAM and RAM
and GPU driver buffers just past RAM, and masked guest addresses (bits 30-31
cleared) reach a whole GB above base, mostly heap. A stray guest access
landed in those silently instead of faulting, and another thread could even
map something where a view was about to go, which the view's MAP_FIXED then
replaced. That fits the 32-bit-only crashes deep in system libraries and in
our own heap structures.

Keep the range reserved as PROT_NONE and map the views over it, putting the
reservation back when a view is released. Mask out bits 28-29 too on 32-bit
(no valid address has them), so accesses stay inside the reservation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 23:21:11 +02:00

72 lines
2.2 KiB
C++

// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include <cstdint>
#ifdef _WIN32
#include "CommonWindows.h"
#elif defined(__APPLE__)
#include <mach/mach.h>
#endif
#include "Common/CommonTypes.h"
// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
// Multiple views can mirror the same section of the block, which makes it very convient for emulating
// memory mirrors.
struct MemArenaData;
class MemArena {
public:
size_t roundup(size_t x);
bool GrabMemSpace(size_t size);
void ReleaseSpace();
void *CreateView(s64 offset, size_t size, void *base = 0);
void ReleaseView(s64 offset, void *view, size_t size);
// This only finds 1 GB in 32-bit
u8 *Find4GBBase();
bool NeedsProbing();
#if defined(__APPLE__)
// Asks the kernel for a free range of this size for the views, and keeps it reserved (inaccessible), so
// CreateView can map over it without anything else taking it in between. ReleaseSpace releases it too.
// alignMask: the address bits that must be zero.
u8 *ReserveViewSpace(size_t size, size_t alignMask);
void ReleaseViewSpace();
#endif
private:
#ifdef _WIN32
HANDLE hMemoryMapping;
SYSTEM_INFO sysInfo;
#elif defined(__APPLE__)
size_t vm_size;
vm_address_t vm_mem; // same type as vm_address_t
vm_address_t reserved_mem = 0;
size_t reserved_size = 0;
#else
int fd = -1;
// Where Find4GBBase keeps the view range reserved (inaccessible) until ReleaseSpace, so nothing else
// can be mapped between the views.
void *reserved_mem = nullptr;
size_t reserved_size = 0;
#endif
};