From 3234ae2852fb2003e444eaab4afbc460bf89f5c9 Mon Sep 17 00:00:00 2001 From: duke Date: Tue, 23 Jun 2026 18:52:52 +0000 Subject: [PATCH 1/5] Backport f4209dff3ba14ccbdc0846d9bfcc62688361b6d5 --- src/hotspot/os/windows/os_windows.cpp | 52 +++++---------- src/hotspot/os/windows/os_windows.hpp | 2 + .../os/windows/safefetch_static_windows.cpp | 64 ++++++++++++++++++ .../windows_aarch64/os_windows_aarch64.cpp | 4 ++ .../safefetch_windows_aarch64.S | 65 +++++++++++++++++++ src/hotspot/share/runtime/safefetch.hpp | 4 +- .../UncaughtNativeExceptionTest.java | 2 +- .../ErrorHandling/libNativeException.c | 5 +- 8 files changed, 157 insertions(+), 41 deletions(-) create mode 100644 src/hotspot/os/windows/safefetch_static_windows.cpp create mode 100644 src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 4969f0ecf73..5a255a7b82d 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2628,14 +2628,13 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { DWORD exception_code = exception_record->ExceptionCode; #if defined(_M_ARM64) address pc = (address) exceptionInfo->ContextRecord->Pc; + + if (handle_safefetch(exception_code, pc, (void*)exceptionInfo->ContextRecord)) { + return EXCEPTION_CONTINUE_EXECUTION; + } #elif defined(_M_AMD64) address pc = (address) exceptionInfo->ContextRecord->Rip; -#else - #error unknown architecture -#endif - Thread* t = Thread::current_or_null_safe(); -#if defined(_M_AMD64) if ((exception_code == EXCEPTION_ACCESS_VIOLATION) && VM_Version::is_cpuinfo_segv_addr(pc)) { // Verify that OS save/restore AVX registers. @@ -2648,6 +2647,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { VM_Version::clear_apx_test_state(); return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr_apx()); } +#else + #error unknown architecture #endif #ifdef CAN_SHOW_REGISTERS_ON_ASSERT @@ -2658,6 +2659,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } #endif + Thread* t = Thread::current_or_null_safe(); if (t != nullptr && t->is_Java_thread()) { JavaThread* thread = JavaThread::cast(t); bool in_java = thread->thread_state() == _thread_in_Java; @@ -2688,10 +2690,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { // Fatal red zone violation. overflow_state->disable_stack_red_zone(); tty->print_raw_cr("An unrecoverable stack overflow has occurred."); -#if !defined(USE_VECTORED_EXCEPTION_HANDLING) report_error(t, exception_code, pc, exception_record, exceptionInfo->ContextRecord); -#endif return EXCEPTION_CONTINUE_SEARCH; } } else if (exception_code == EXCEPTION_ACCESS_VIOLATION) { @@ -2743,10 +2743,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } // Stack overflow or null pointer exception in native code. -#if !defined(USE_VECTORED_EXCEPTION_HANDLING) report_error(t, exception_code, pc, exception_record, exceptionInfo->ContextRecord); -#endif return EXCEPTION_CONTINUE_SEARCH; } // /EXCEPTION_ACCESS_VIOLATION // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2821,41 +2819,21 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } } -#if !defined(USE_VECTORED_EXCEPTION_HANDLING) - if (exception_code != EXCEPTION_BREAKPOINT) { - report_error(t, exception_code, pc, exception_record, - exceptionInfo->ContextRecord); - } -#endif - return EXCEPTION_CONTINUE_SEARCH; -} + bool should_report_error = (exception_code != EXCEPTION_BREAKPOINT); -#if defined(USE_VECTORED_EXCEPTION_HANDLING) -LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { - PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; #if defined(_M_ARM64) - address pc = (address) exceptionInfo->ContextRecord->Pc; -#elif defined(_M_AMD64) - address pc = (address) exceptionInfo->ContextRecord->Rip; -#else - #error unknown architecture + should_report_error = should_report_error && + FAILED(exception_code) && + (exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION); #endif - // Fast path for code part of the code cache - if (CodeCache::low_bound() <= pc && pc < CodeCache::high_bound()) { - return topLevelExceptionFilter(exceptionInfo); - } - - // If the exception occurred in the codeCache, pass control - // to our normal exception handler. - CodeBlob* cb = CodeCache::find_blob(pc); - if (cb != nullptr) { - return topLevelExceptionFilter(exceptionInfo); + if (should_report_error) { + report_error(t, exception_code, pc, exception_record, + exceptionInfo->ContextRecord); } return EXCEPTION_CONTINUE_SEARCH; } -#endif #if defined(USE_VECTORED_EXCEPTION_HANDLING) LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { @@ -4488,7 +4466,7 @@ jint os::init_2(void) { // Setup Windows Exceptions #if defined(USE_VECTORED_EXCEPTION_HANDLING) - topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelVectoredExceptionFilter); + topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelExceptionFilter); previousUnhandledExceptionFilter = SetUnhandledExceptionFilter(topLevelUnhandledExceptionFilter); #endif diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index efb7b414989..f1153bbbfd3 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -150,6 +150,8 @@ class os::win32 { // signal support static void* install_signal_handler(int sig, signal_handler_t handler); static void* user_handler(); + + static void context_set_pc(CONTEXT* uc, address pc); }; #endif // OS_WINDOWS_OS_WINDOWS_HPP diff --git a/src/hotspot/os/windows/safefetch_static_windows.cpp b/src/hotspot/os/windows/safefetch_static_windows.cpp new file mode 100644 index 00000000000..3ea8b96b32d --- /dev/null +++ b/src/hotspot/os/windows/safefetch_static_windows.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 SAP SE. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + + +#include "os_windows.hpp" +#include "runtime/os.hpp" +#include "runtime/safefetch.hpp" +#include "utilities/globalDefinitions.hpp" + +#ifdef SAFEFETCH_METHOD_STATIC_ASSEMBLY + +// SafeFetch handling, static assembly style: +// +// SafeFetch32 and SafeFetchN are implemented via static assembly +// and live in os_cpu/xx_xx/safefetch_xx_xx.S + +extern "C" char _SafeFetch32_continuation[]; +extern "C" char _SafeFetch32_fault[]; + +#ifdef _LP64 +extern "C" char _SafeFetchN_continuation[]; +extern "C" char _SafeFetchN_fault[]; +#endif // _LP64 + +bool handle_safefetch(int exception_code, address pc, void* context) { + CONTEXT* ctx = (CONTEXT*)context; + if (exception_code == EXCEPTION_ACCESS_VIOLATION && ctx != nullptr) { + if (pc == (address)_SafeFetch32_fault) { + os::win32::context_set_pc(ctx, (address)_SafeFetch32_continuation); + return true; + } +#ifdef _LP64 + if (pc == (address)_SafeFetchN_fault) { + os::win32::context_set_pc(ctx, (address)_SafeFetchN_continuation); + return true; + } +#endif + } + return false; +} + +#endif // SAFEFETCH_METHOD_STATIC_ASSEMBLY diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp index 01105e6d51e..d99e0167cbd 100644 --- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp @@ -115,6 +115,10 @@ intptr_t* os::fetch_bcp_from_context(const void* ucVoid) { return reinterpret_cast(uc->REG_BCP); } +void os::win32::context_set_pc(CONTEXT* uc, address pc) { + uc->Pc = (intptr_t)pc; +} + bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread, struct _EXCEPTION_POINTERS* exceptionInfo, address pc, frame* fr) { PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; diff --git a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S new file mode 100644 index 00000000000..494b68fe4cd --- /dev/null +++ b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S @@ -0,0 +1,65 @@ +; +; Copyright (c) 2022 SAP SE. All rights reserved. +; Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; This code is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License version 2 only, as +; published by the Free Software Foundation. +; +; This code is distributed in the hope that it will be useful, but WITHOUT +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +; version 2 for more details (a copy is included in the LICENSE file that +; accompanied this code). +; +; You should have received a copy of the GNU General Public License version +; 2 along with this work; if not, write to the Free Software Foundation, +; Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +; +; Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +; or visit www.oracle.com if you need additional information or have any +; questions. +; + + ; Support for int SafeFetch32(int* address, int defaultval); + ; + ; x0 : address + ; w1 : defaultval + + ; needed to align function start to 4 byte + ALIGN 4 + EXPORT _SafeFetch32_fault + EXPORT _SafeFetch32_continuation + EXPORT SafeFetch32_impl + AREA safefetch_text, CODE + +SafeFetch32_impl +_SafeFetch32_fault + ldr w0, [x0] + ret + +_SafeFetch32_continuation + mov x0, x1 + ret + + ; Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval); + ; + ; x0 : address + ; x1 : defaultval + + ALIGN 4 + EXPORT _SafeFetchN_fault + EXPORT _SafeFetchN_continuation + EXPORT SafeFetchN_impl + +SafeFetchN_impl +_SafeFetchN_fault + ldr x0, [x0] + ret + +_SafeFetchN_continuation + mov x0, x1 + ret + + END diff --git a/src/hotspot/share/runtime/safefetch.hpp b/src/hotspot/share/runtime/safefetch.hpp index 71a542e25e8..a1781962ec0 100644 --- a/src/hotspot/share/runtime/safefetch.hpp +++ b/src/hotspot/share/runtime/safefetch.hpp @@ -31,8 +31,8 @@ // Safefetch allows to load a value from a location that's not known // to be valid. If the load causes a fault, the error value is returned. -#ifdef _WIN32 - // Windows uses Structured Exception Handling +#if defined(_WIN32) && !defined(_M_ARM64) + // Windows x86_64 uses Structured Exception Handling #include "safefetch_windows.hpp" #elif defined(ZERO) || defined (_AIX) // These platforms implement safefetch via Posix sigsetjmp/longjmp. diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/UncaughtNativeExceptionTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/UncaughtNativeExceptionTest.java index 14aca26f39f..d432181aacb 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/UncaughtNativeExceptionTest.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/UncaughtNativeExceptionTest.java @@ -64,7 +64,7 @@ public void testNativeExceptionReporting() throws Exception { assertTrue(Files.exists(hsErrPath)); Pattern[] positivePatterns = { - Pattern.compile(".*Internal Error \\(0x2a\\).*") + Pattern.compile(".*Internal Error \\(0xdeadbeef\\).*") }; HsErrFileUtils.checkHsErrFileContent(hsErrFile, positivePatterns, null, true /* check end marker */, false /* verbose */); } diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/libNativeException.c b/test/hotspot/jtreg/runtime/ErrorHandling/libNativeException.c index 3bf71cf9c67..20216a2e1de 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/libNativeException.c +++ b/test/hotspot/jtreg/runtime/ErrorHandling/libNativeException.c @@ -25,7 +25,10 @@ #include -const DWORD EX_CODE = 42; +// Use an exception code that causes the Windows FAILED() macro to return true. +// Windows AArch64 uses vectored exception handling and therefore runs error +// reporting only for failed exception codes. +const DWORD EX_CODE = 0xdeadbeef; JNIEXPORT void JNICALL Java_UncaughtNativeExceptionTest_00024Crasher_throwException(JNIEnv* env, jclass cls) { RaiseException(EX_CODE, EXCEPTION_NONCONTINUABLE, 0, NULL); From 2ed58eb6294c206f36a3e2a4c2c7dcc0c66a506b Mon Sep 17 00:00:00 2001 From: Ashay Rane <253344819+raneashay@users.noreply.github.com> Date: Wed, 24 Jun 2026 10:54:37 -0500 Subject: [PATCH 2/5] Fix armasm64 parsing error Newer versions of armasm64 seem to be more lenient so that might be why we don't see this error when building this same code in JDK tip. --- src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S index 494b68fe4cd..8e3cb0f1906 100644 --- a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S +++ b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S @@ -27,12 +27,13 @@ ; x0 : address ; w1 : defaultval + AREA safefetch_text, CODE + ; needed to align function start to 4 byte ALIGN 4 EXPORT _SafeFetch32_fault EXPORT _SafeFetch32_continuation EXPORT SafeFetch32_impl - AREA safefetch_text, CODE SafeFetch32_impl _SafeFetch32_fault From fbca6ed400424a93730a255aa6b459ce641935d0 Mon Sep 17 00:00:00 2001 From: Ashay Rane <253344819+raneashay@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:17:54 -0500 Subject: [PATCH 3/5] Use the conventional form of the `AREA` directive This is to prevent parsing errors on older versions of the armasm64 assembler. --- src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S index 8e3cb0f1906..8153b746a42 100644 --- a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S +++ b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S @@ -27,7 +27,7 @@ ; x0 : address ; w1 : defaultval - AREA safefetch_text, CODE + AREA |.text|, CODE, READONLY ; needed to align function start to 4 byte ALIGN 4 From 8d5f7a6d16c92cfef582d65ea73c40dbf8a02134 Mon Sep 17 00:00:00 2001 From: Ashay Rane <253344819+raneashay@users.noreply.github.com> Date: Mon, 29 Jun 2026 11:59:52 -0500 Subject: [PATCH 4/5] Revert "Use the conventional form of the `AREA` directive" This reverts commit fbca6ed400424a93730a255aa6b459ce641935d0. --- src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S index 8153b746a42..8e3cb0f1906 100644 --- a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S +++ b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S @@ -27,7 +27,7 @@ ; x0 : address ; w1 : defaultval - AREA |.text|, CODE, READONLY + AREA safefetch_text, CODE ; needed to align function start to 4 byte ALIGN 4 From 9a372d8560fc276b1756c02060f20cfd0ef291df Mon Sep 17 00:00:00 2001 From: Ashay Rane <253344819+raneashay@users.noreply.github.com> Date: Mon, 29 Jun 2026 11:59:56 -0500 Subject: [PATCH 5/5] Revert "Fix armasm64 parsing error" This reverts commit 2ed58eb6294c206f36a3e2a4c2c7dcc0c66a506b. --- src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S index 8e3cb0f1906..494b68fe4cd 100644 --- a/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S +++ b/src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S @@ -27,13 +27,12 @@ ; x0 : address ; w1 : defaultval - AREA safefetch_text, CODE - ; needed to align function start to 4 byte ALIGN 4 EXPORT _SafeFetch32_fault EXPORT _SafeFetch32_continuation EXPORT SafeFetch32_impl + AREA safefetch_text, CODE SafeFetch32_impl _SafeFetch32_fault