mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
BepInEx loads no plugins and writes no log when the game runs as arm64 rather than under Rosetta. There is no crash and no error. MonoMod picks DetourNativeMonoPosixPlatform on Mono, whose MakeWritable and MakeExecutable call mprotect with PROT_READ|PROT_WRITE|PROT_EXEC. macOS on Apple Silicon answers EACCES: without the entitlement com.apple.security.cs.allow-unsigned-executable-memory no page may be writable and executable at once. Unity ships allow-jit instead, so Mono's code lives in a MAP_JIT region, which also refuses mach_vm_write with KERN_INVALID_ADDRESS. The failure is invisible. DetourHelper.get_Runtime sets _RuntimeInit before constructing the platform and returns null on every later call once set, so the one EACCES turns every subsequent Harmony patch into a NullReferenceException in DetourHelper.GetIdentifiable. HarmonyX swallows the first inside Harmony..cctor, and Entrypoint.Start writes the rest to preloader_*.log beside the executable, not to LogOutput.log. AppleSiliconDetourFix installs a detour platform that keeps DetourNativeARMPlatform's AArch64 encoding and routes code writes through doorstop_jit_memcpy, which brackets its memcpy with pthread_jit_write_protect_np. That toggle cannot be done from managed code, because it removes execute permission for the calling thread and that thread is running JIT-compiled code. XTermFix forced DetourNativeX86Platform on every non-Windows target, which on Apple Silicon encodes x86 branches into arm64 method bodies and reinstates the failing mprotect. It is now skipped when the fix applies. Preloader.Run logs a warning if the fix cannot install, so this cannot fail silently again. Requires doorstop_jit_memcpy from UnityDoorstop.