diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index c9ef08e3510..ba05d390c9f 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2630,14 +2630,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. @@ -2650,6 +2649,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 @@ -2660,6 +2661,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; @@ -2690,10 +2692,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) { @@ -2745,10 +2745,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 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2808,41 +2806,21 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } } -#if !defined(USE_VECTORED_EXCEPTION_HANDLING) - if (exception_code != EXCEPTION_BREAKPOINT) { + bool should_report_error = (exception_code != EXCEPTION_BREAKPOINT); + +#if defined(_M_ARM64) + should_report_error = should_report_error && + FAILED(exception_code) && + (exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION); +#endif + + if (should_report_error) { report_error(t, exception_code, pc, exception_record, exceptionInfo->ContextRecord); } -#endif - return EXCEPTION_CONTINUE_SEARCH; -} - -#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 -#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); - } return EXCEPTION_CONTINUE_SEARCH; } -#endif #if defined(USE_VECTORED_EXCEPTION_HANDLING) LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { @@ -4519,7 +4497,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 @@ public: // 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 class UncaughtNativeExceptionTest { 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);