From 70546f6404c5927a9868a80ccbf4c6c2beaea671 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 5 Aug 2021 13:37:29 +0200 Subject: [PATCH] runtime: allow arm64 SEH to be called if illegal instruction DLLs built with recent Microsoft toolchains for ARM64 test for ARMv8.1 atomics by potentially calling an illegal instruction, and then trapping the exception to disable use of them by way of a structured exception handler. However, vectored exception handlers are always called before structured exception handlers. When LoadLibrary-ing DLLs that do this probing during initialization, our lastcontinuehandler winds up being called, and then crashing, but actually it should give execution back to the library to handle the exception and fix up the state. So special case this for arm64 with illegal instructions, and hope that we're not masking other things in external DLLs that might more fatally trigger an illegal instruction exception. Updates #47576. Change-Id: I341ab99cd8d513ae999b75596749d49779072022 Reviewed-on: https://go-review.googlesource.com/c/go/+/340070 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick Reviewed-by: Russ Cox --- src/runtime/signal_windows.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index f2ce24d735c..b720ddcf164 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -183,6 +183,17 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { return _EXCEPTION_CONTINUE_SEARCH } + // VEH is called before SEH, but arm64 MSVC DLLs use SEH to trap + // illegal instructions during runtime initialization to determine + // CPU features, so if we make it to the last handler and we're + // arm64 and it's an illegal instruction and this is coming from + // non-Go code, then assume it's this runtime probing happen, and + // pass that onward to SEH. + if GOARCH == "arm64" && info.exceptioncode == _EXCEPTION_ILLEGAL_INSTRUCTION && + (r.ip() < firstmoduledata.text || firstmoduledata.etext < r.ip()) { + return _EXCEPTION_CONTINUE_SEARCH + } + winthrow(info, r, gp) return 0 // not reached }