## Summary
The native Apple Silicon build ArmA3 AS Native.app crashes during startup, 100% reproducibly,
always at the same instruction. The Rosetta build ArmA3.app runs fine on the same machine.
Root cause: eON reserves its module heap at the hard-coded address 0x300000000. On macOS 27 that
address is inside the dyld shared cache mapping, so the reservation fails. The return value is not
checked, the region is never registered, and the first winpe_LoadFromMemory() dereferences the NULL
returned by the region lookup.
## Environment
MacBookPro18,1, Apple M1 Pro, 32 GB โ macOS 27.0 (26A5425a)
Arma 3 via Steam, com.vpltd.Arma3, CFBundleVersion 20241031.1, binary signed 2026-08-26 15:51:18
Game installed on the internal SSD.
## Crash
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x10
esr: 0x92000006 (Data Abort, read, translation fault)
PC = ArmA3 AS Native + 25468 (image offset 0x637C)
Faulting instruction (confirmed against instructionByteStream in the crash report):
100006378 mov x0, #0x0
10000637c ldr x8, [x0, #0x10] <-- PC, x0 = 0, reads from 0x10
x0 is the result of a region lookup at +0x62F4 and is used without a NULL check. Three code paths
in that function can produce NULL (+0x6378, +0x641C, +0x6430) and all three fall into the same load.
## Root cause
At +0x59A38, inside the eON JIT / code-cache initialiser:
100059a30 mov w8, #0x1
100059a34 strb w8, [x19] ; use-commit-path flag = 1
100059a38 mov x0, #0x300000000 ; hard-coded base address
100059a3c mov w1, #0x57d0000 ; 92,078,080 bytes (87.8 MB)
100059a40 mov w2, #0x2000 ; MEM_RESERVE
100059a44 mov w3, #0x1 ; PAGE_NOACCESS
100059a48 bl 0x100005dcc ; eON VirtualAlloc
100059a4c ldur x8, [x19, #0x14] ; return value never inspected
This ends up in mach_vm_map(FIXED | VM_FLAGS_OVERWRITE) at +0x4F80. On failure the region is not
inserted into the list at +0x5228, and nothing upstream notices.
On macOS 27 the address is occupied. vmmap of the live process:
__LINKEDIT 2df898000-342e44000 [ 1.6G ] r--/r-- SM=COW
dyld shared cache combined __LINKEDIT
0x300000000 sits 519 MB inside that mapping; the whole intended reservation
(0x300000000-0x3057D0000) is contained in it. The crash report agrees: shared cache base
0x182034000, size 7.01 GB, i.e. it extends to 0x342E48000.
## Standalone reproduction (outside the game)
A 15-line C program issuing the identical mach_vm_map() call:
FIXED|OVERWRITE @3G want=0x300000000 kr=2 ((os/kern) protection failure)
FIXED @3G want=0x300000000 kr=3 ((os/kern) no space available)
FIXED|OVERWRITE @16G want=0x400000000 kr=0 ((os/kern) successful)
ANYWHERE want=0x0 kr=0 ((os/kern) successful)
KERN_NO_SPACE says the range is occupied; KERN_PROTECTION_FAILURE says the occupant cannot be
replaced - the signature of a shared-cache mapping. Both 0x400000000 and ANYWHERE succeed, so this
is not a general VM problem.
## Crash-report registers (image slide 0x4c54000)
x19 = 0x300000000 requested address = module-heap base, i.e. the FIRST module allocation
x20 = 0x24d0000 38,600,704 bytes = Arma3Retail_DX11_x64.exe image
x21 = 0x1069390d0 - slide = 0x101ce50d0 = the region-list global
x8 = 0x116a00000 base+size of the last region examined = end of the binary's own EON_RESERVE
x24 = 0x140000000 the PE's preferred base (matches eon.txt)
x0 = 0 the NULL that is dereferenced
The only region eON ever registered is its own EON_RESERVE segment. Nothing covers 0x300000000.
## Two observed stacks, one cause
With a pre-built code cache present, it fails within seconds while replaying the cache chunk stream:
+4123364 init -> +3575256 eON_Core::init -> +371644 JIT init -> +1981944 code-cache loader
-> +393816 chunk parser -> +361300 module allocator -> +25468 CRASH
With no code cache, it fails after ~2 minutes on the real module load path:
+4123624 init -> +3576592 "Loading executable ... failed!" -> +4048712 DLL LOADING
-> +4047436 winpe_LoadFromFile -> +4043192 winpe_LoadFromMemory -> +361152 -> +361300
-> +25468 CRASH
eon.txt ends on the last line before the crash:
[thread 00000001][I][118328]: eON_LoadLibraryExA(): AOT module analysis for
'Arma3Retail_DX11_x64.exe' done
## Suggested fixes
1. Do not reserve at a hard-coded address. Reserve the module heap with VM_FLAGS_ANYWHERE (or retry
over a list of candidate bases) and store the resulting base in the cursor global.
2. Check the result of the reservation at +0x59A48 and fail loudly.
3. Add the missing NULL check in +0x62F4 (all three paths).
4. Add a bounds check on the bump cursor in +0x58308 so an oversized module set errors out instead
of walking past the end of the region.
5. If the code cache stores absolute module addresses, record the base it was generated against.
## Secondary issue: released build ships without a signed code cache
On a clean profile the app shows "Code cache for this CPU architecture not found in signed
resources! This means it's probably a TestFlight build of the game...". eon.txt confirms
Contents/Resources/eonJit64.cache is missing. Consequences: ~2 minute startup while everything is
JIT-compiled from scratch, and dev-mode per-instruction logging grows
~/Library/Application Support/com.vpltd.Arma3/eon.txt to 3 GB.
## Already ruled out
Steam Overlay disabled; game moved from external volume to internal SSD; eONprecompiledShaders.dat
deleted; ~/Library/Application Support/com.vpltd.Arma3 moved aside (clean profile); eonJit64.cache
deleted from both the bundle and Application Support. Crash address and register state identical
every time. Resolution, RAM and GPU are not factors - the crash happens before any rendering.
Full analysis with disassembly, vmmap and the reproduction program is attached as a PDF.
Activity
You are not signed in. Please sign in to see more details and to reply.