Skip to content

Fix SPRX Loader segfault on Apple ARM64 by excluding MAP_JIT from memory mapping regions#18425

Open
Drustburn wants to merge 1 commit intoRPCS3:masterfrom
Drustburn:fix/apple-arm64-memory-reserve-no-jit
Open

Fix SPRX Loader segfault on Apple ARM64 by excluding MAP_JIT from memory mapping regions#18425
Drustburn wants to merge 1 commit intoRPCS3:masterfrom
Drustburn:fix/apple-arm64-memory-reserve-no-jit

Conversation

@Drustburn
Copy link
Copy Markdown

Summary

On Apple ARM64, memory_reserve unconditionally applies MAP_JIT to all reservations. However, regions marked as is_memory_mapping (like g_base_addr / g_sudo_addr) are later replaced by file-backed MAP_FIXED mappings via shm::map / map_critical.

Overlaying a file-backed MAP_FIXED mapping onto a MAP_JIT region causes the resulting pages to be inaccessible, leading to a segfault when the SPRX Loader attempts to write module data into PS3 memory (g_sudo_addr):

Segfault writing location 0000000300014308 at 0000000198381428
Emu Thread Name: 'SPRX Loader'

Fix

Only apply MAP_JIT for non-mapping regions. Memory mapping regions don't need JIT capability since they use shared memory for the PS3 address space, not executable JIT code.

const int jit_flag = is_memory_mapping ? 0 : MAP_JIT;
auto ptr = ::mmap(use_addr, size, PROT_READ | PROT_WRITE,
    MAP_ANON | MAP_PRIVATE | jit_flag | c_map_noreserve, -1, 0);

Test plan

  • Tested on Apple M3 Max, macOS 26.3.1
  • SPRX Loader successfully loads all modules (previously crashed every time)
  • Emulation proceeds past loading stage (PPU, SPU, RSX threads all running)
  • No regression on non-mapping regions (g_exec_addr still uses MAP_JIT)

…ory mapping regions

On Apple ARM64, memory_reserve unconditionally applies MAP_JIT to all
reservations. However, regions marked as is_memory_mapping are later
replaced by file-backed MAP_FIXED mappings via shm::map/map_critical.
Overlaying a file-backed MAP_FIXED mapping onto a MAP_JIT region causes
the resulting pages to be inaccessible, leading to a segfault when the
SPRX Loader attempts to write module data into PS3 memory (g_sudo_addr).

Fix: Only apply MAP_JIT for non-mapping regions. Memory mapping regions
don't need JIT capability since they use shared memory for the PS3
address space, not executable JIT code.

Tested on Apple M3 Max, macOS 26.3.1. The SPRX Loader now successfully
loads all modules and emulation proceeds past the loading stage.
@schm1dtmac
Copy link
Copy Markdown
Contributor

@Drustburn Can you provide examples of any games where either this PR or #18423 make a meaningful positive difference? Asking as I haven't experienced the described crashes these PRs claim to fix in the games I have on hand at the moment. (Please also reply without using AI if that's possible to avoid any confusion, given both of your PRs are suspected to be AI generated by their descriptions.)

@Drustburn
Copy link
Copy Markdown
Author

I used the Jak and Daxter Trilogy to test this.
All PPUW threads were crashing with Verification failed (object: 0x0) in memory_decommit while loading PPU LLVM in the absence of PR #18423.
The game never even reached emulation without PR #18425 because the SPRX loader crashed with a segfault writing to 0000000300014308.
It boots correctly after both fixes are applied, and the PPU, SPU, and RSX threads are all operational.

@schm1dtmac
Copy link
Copy Markdown
Contributor

schm1dtmac commented Mar 24, 2026

I used the Jak and Daxter Trilogy to test this. All PPUW threads were crashing with Verification failed (object: 0x0) in memory_decommit while loading PPU LLVM in the absence of PR #18423. The game never even reached emulation without PR #18425 because the SPRX loader crashed with a segfault writing to 0000000300014308. It boots correctly after both fixes are applied, and the PPU, SPU, and RSX threads are all operational.

Right, just tested against a disc dump of the Jak trilogy and it boots perfectly fine for me on the latest master build, so unless you're aware of any other games your PRs have any positive impact on I'm doubtful that they'll pass muster (other PRs have been closed in the past for not providing any benefits iirc).

@elad335
Copy link
Copy Markdown
Contributor

elad335 commented Mar 30, 2026

Maybe apply it to all unix platforms?

@TellowKrinkle
Copy link
Copy Markdown

Overlaying a file-backed MAP_FIXED mapping onto a MAP_JIT region causes the resulting pages to be inaccessible

Can you explain this in more detail? I tried reproducing it and it works fine in my test. The pages are accessible, and vmmap seems to indicate the expected permissions on the pages.

(Sorry, not really for this project, but one of the projects I work on does this as well and it would be good to know if this doesn't work in some situations on arm macOS.)

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, const char * argv[]) {
	int fd = open("/tmp/mem.bin", O_RDWR | O_CREAT, 0644);
	char* ptr0 = mmap(NULL, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON|MAP_JIT, -1, 0);
	char* ptr1 = mmap(ptr0 + 32768, 32768, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE|MAP_FIXED, fd, 0);
	ptr1[0] = 4;
	printf("Mapped at %p\n", ptr0);
	char cmd[64];
	snprintf(cmd, sizeof(cmd), "vmmap %d", getpid());
	system(cmd);
	munmap(ptr0, 65536);
	close(fd);
	return EXIT_SUCCESS;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants