#1140177 wine: arm64 Wine fails on HW with pointer authentication

Package:
wine
Source:
wine
Submitter:
Martin Storsjö
Date:
2026-06-19 13:17:01 UTC
Severity:
normal
Tags:
#1140177#5
Date:
2026-06-16 20:40:07 UTC
From:
To:
Dear Maintainer,

When running Wine on arm64, on HW with pointer authentication
(armv8.3 and newer), Wine fails to run.

In some cases, it hangs directly on startup for any case (e.g.
"wine wineboot" hangs), in some cases it seemingly runs
successfully, but any case that requires unwinding in the user
executables fail.

(Exactly what makes it seemingly succeed in some cases and
hang in others is unclear.)

The issue can be consistently observed by running
"WINEDEBUG=+seh wine wineboot" in a fresh install with no
preexisting wine prefix (~/.wine).

On older hardware, without support for pointer authentication,
Wine starts up nicely (and there are a handful of debug printouts
about unwinding one exception). On newer hardware, it results in
repeated printouts about EXCEPTION_ILLEGAL_INSTRUCTION.

The root cause of this issue is that Clang 19 and newer has
regressed the code generation for return address signing on
Windows on aarch64 - this issue has been filed upstream at
[1]. Debian builds of Wine have pointer authentication enabled
for the internal PE components of Wine (and those components
are compiled with Clang), which causes Wine to trip over itself
when unwinding through those components.

However, the issue is made visible due to the fact that Wine's
unwinding of pointer authentication was more strict than
what really is necessary. A fix for this was merged in [2].
This fix avoids triggering illegal instructions and breaking
on these cases.

This fix will be in the upcoming development release Wine 11.12,
but it also applies cleanly on e.g. Wine 10.0. Applying this
patch in the Debian packaging will likely fix this issue.


[1] https://github.com/llvm/llvm-project/issues/203852
[2] https://gitlab.winehq.org/wine/wine/-/commit/a83427f29e925d8b29cf58a55406d28bd95750a2

#1140177#10
Date:
2026-06-17 15:58:45 UTC
From:
To:
Hi Martin,

[...]

On systems with FEAT_FPAC support, indeed I could reproduce the behavior
you mentioned: EXCEPTION_ILLEGAL_INSTRUCTION printed out repeatedly,
immediate failure.

On systems with pointer authentication but without FEAT_FPAC, the issue
is more subtle: things seem to more or less work, but explorer.exe maxes
out one CPU core. Also, running simple stuff like `wine cmd` does not
really work.

I built a local version of wine with your patch, and it does seem to fix
the issue for systems without FEAT_FPAC. I don't see explorer.exe maxing
out cores, and `wine cmd` works fine.

However, on systems with FEAT_FPAC I still get illegal instructions.

The general difference between the two is that with FEAT_FPAC, the
autiasp (or equivalent) instruction fails with a SIGILL when failing to
validate the value stored in LR. Without FEAT_FPAC, the autiasp
instruction itself does not cause an exception, but instead it leaves a
faulting value in LR. The crash then occurs when that corrupted value is
next used.

See https://wiki.debian.org/ToolChain/PACBTI#PAC-1.

Here's the SIGILL with your patch:

 $ WINEDEBUG=+seh gdb /usr/lib/aarch64-linux-gnu/wine/wine
 [...]
 (gdb) run wineboot
 [...]
 wine_dbg_output: debugstr buffer overflow (contents: '002c:trace:seh:dispatch_exception code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D76230
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c000001d (EXCEPTION_ILLEGAL_INSTRUCTION) flags=0 addr=0000FFFFF7D763F0
 code=c00000fd (EXCEPTION_STACK_OVERFLOW) flags=0 addr=00006FFFFFD567C4
 ')
 002c:err:virtual:virtual_setup_exception nested exception on signal stack addr 0xfffff7e7b5bc stack 0x7ffce130

 Program received signal SIGILL, Illegal instruction.
 0x0000fffff7d76230 in __wine_syscall_dispatcher () from /usr/lib/aarch64-linux-gnu/wine/aarch64-unix/ntdll.so

For anyone who wants to follow along and build a patched wine, the
version currently in sid (10.0~repack-12) does not build for several
reasons.

First you have to install a bunch of unicode-related packages from
stable due to https://bugs.debian.org/1125336

# apt install unicode-data=15.1.0-1 unicode-idna=16.0.0-1 unicode-cldr-core=46-0.1

Then the make_vulkan bits fail due to the XML files shipped by libvulkan
being too new. Again installing stuff from stable helps:

# apt install libvulkan-dev=1.4.309.0-1 libvulkan1=1.4.309.0-1

The patch disable/duplicate-nls.patch does not seem to apply, I've
commented it out in debian/patch/series. Then later the build fails due
to NLS files not being installed anywhere. Out of time, I just added the
following to debian/wine-common.install to carry on with the build:

usr/* usr/share/wine/nls

#1140177#15
Date:
2026-06-19 10:23:56 UTC
From:
To:
Hi Emanuele,

Thanks for testing and looking into this, I appreciate it a lot!

This issue here can also be observed by trying to run a test app that does
unwinding. E.g. https://martin.st/temp/hello-exception-aarch64.exe is a
build of
https://github.com/mstorsjo/llvm-mingw/blob/master/test/hello-exception.cpp,
built with an llvm-mingw toolchain. This program fails when throwing a C++
exception, if Wine is built with
CROSSCFLAGS="-mbranch-protection=standard", like it is in the Debian
packages.

But anyway, this part is fixed by the previously referenced patch.

Thanks for these hints for how to fix rebuilding it! Yeah due to troubles
with rebuilding the Debian package I didn't get to testing the final fix
in the full context.

With these hints, I was able to rebuild the package on Debian sid nicely,
and reproduce the remaining problem.

Actually, it turns out that this second issue isn't related to PAC or FPAC
at all - but related to BTI.

This issue is actually fixed in latest upstream Wine already, in [1].
Unfortunately, this fix doesn't apply cleanly on Wine 10.0, but it's easy
enough to backport. I tested a backport of it, which I pushed at [2].

With these fixes, the packages now run fine on both a Cortex A720, and on
Neoverse V2 (Graviton 4), where I previously hit the immediate
EXCEPTION_ILLEGAL_INSTRUCTION.

[1] https://gitlab.winehq.org/wine/wine/-/commit/da0b77340302d90b6b11ef030a8861fdfe728f48
[2] https://gitlab.winehq.org/mstorsjo/wine/-/commit/64c22e090351fd37c6b4f38ce5235d4c9c1bdaa2

// Martin

#1140177#20
Date:
2026-06-19 13:14:34 UTC
From:
To: