#30

ntdll ARM64EC: no emulator callbacks after its DLL_PROCESS_DETACH

Openakshaynexuswants to merge intofrom

Problem

When Rocket League (64-bit, ARM64EC session) quit from its own menu, it ended with an access violation instead of exiting:

  1. NtTerminateProcess(0, 0), then LdrShutdownProcess sends DLL_PROCESS_DETACH to every module, including the emulator, xtajit64.dll.
  2. Its CRT runs FEX's C++ static destructors in that detach: the FEX context is destroyed.
  3. Modules detached after it (ucrtbase, and ntdll's heap) still free memory. Each NtFreeVirtualMemory goes through the ARM64EC hook to FEX's NotifyMemoryFree → InvalidationTracker::InvalidateAlignedInterval, which calls through the destroyed context's vtable: a null read at +0xf0 (libarm64ecfex.dll+0x12d058, called from ntdll.dll+0x5ba30, NtFreeVirtualMemory).

Change

  • load_arm64ec_module records the emulator module.
  • process_detach calls arm64ec_emulator_detach() just before the emulator's detach notification.
  • From then on enter_syscall_callback() returns FALSE, so every hook makes the plain syscall and nothing calls into the emulator again. Only native ARM64EC code (ucrtbase, ntdll) runs after that point, so no translation is lost.

No DLL should get callbacks after its own DLL_PROCESS_DETACH, so this is fixed in the loader, not in FEX.

Testing

iPad Pro 12.9" (6th generation), iPadOS 27.0.1: Rocket League → QUIT in the game's menu. Before: access violation at exit. After: exit_process(0), "Wine exited with code 0", and Madeira returns to its library.

Independent of #29 (UCRT); willfaust/Madeira#265 pins a branch with both.

Activity

3
125hz7d ago

Conflicts with madeira-lgpl now; could you rebase?

akshaynexus6d ago

done